1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-26 23:34:44 +01:00

Add source code of @tgstories_dl_bot

This commit is contained in:
Daniil Gentili 2023-07-21 20:02:01 +02:00
parent 6cf245dc8f
commit fd1e2fae87
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
8 changed files with 110 additions and 22 deletions

View File

@ -6,7 +6,7 @@ Features:
- Add support for `parse_mode` parsing for story methods. - Add support for `parse_mode` parsing for story methods.
- `getReply` now simply returns null if the message doesn't reply to any other message. - `getReply` now simply returns null if the message doesn't reply to any other message.
- `getReply` now has an optional parameter that can be used to filter the returned message type. - `getReply` now has an optional parameter that can be used to filter the returned message type.
- Added `isUser()`, `isBot()` messages to check whether the current user is a user or a bot. - Added `isSelfUser()`, `isSelfBot()` messages to check whether the current user is a user or a bot.
- Improved IDE typehinting. - Improved IDE typehinting.
- CLI bots: you can now optionally specify a default download link URL (used by `getDownloadLink`) in the settings. - CLI bots: you can now optionally specify a default download link URL (used by `getDownloadLink`) in the settings.

View File

@ -771,9 +771,9 @@ Want to add your own open-source project to this list? [Click here!](https://doc
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getsessionname-string" name="getSessionName">Returns the session name: getSessionName</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getsessionname-string" name="getSessionName">Returns the session name: getSessionName</a>
* <a href="https://docs.madelineproto.xyz/API_docs/methods/help.getSupport.html" name="help.getSupport">Returns the support user for the "ask a question" feature: help.getSupport</a> * <a href="https://docs.madelineproto.xyz/API_docs/methods/help.getSupport.html" name="help.getSupport">Returns the support user for the "ask a question" feature: help.getSupport</a>
* <a href="https://docs.madelineproto.xyz/API_docs/methods/contacts.search.html" name="contacts.search">Returns users found by username substring: contacts.search</a> * <a href="https://docs.madelineproto.xyz/API_docs/methods/contacts.search.html" name="contacts.search">Returns users found by username substring: contacts.search</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#isbot-bool" name="isBot">Returns whether the current user is a bot: isBot</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#isselfbot-bool" name="isSelfBot">Returns whether the current user is a bot: isSelfBot</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#ispremium-bool" name="isPremium">Returns whether the current user is a premium user, cached: isPremium</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#ispremium-bool" name="isPremium">Returns whether the current user is a premium user, cached: isPremium</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#isuser-bool" name="isUser">Returns whether the current user is a user: isUser</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#isselfuser-bool" name="isSelfUser">Returns whether the current user is a user: isSelfUser</a>
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#uploadfromtgfile-mixed-media-callable-cb-null-bool-encrypted-false-mixed" name="uploadFromTgfile">Reupload telegram file: uploadFromTgfile</a> * <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#uploadfromtgfile-mixed-media-callable-cb-null-bool-encrypted-false-mixed" name="uploadFromTgfile">Reupload telegram file: uploadFromTgfile</a>
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.saveDraft.html" name="messages.saveDraft">Save a message draft associated to a chat: messages.saveDraft</a> * <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.saveDraft.html" name="messages.saveDraft">Save a message draft associated to a chat: messages.saveDraft</a>
* <a href="https://docs.madelineproto.xyz/API_docs/methods/account.saveTheme.html" name="account.saveTheme">Save a theme: account.saveTheme</a> * <a href="https://docs.madelineproto.xyz/API_docs/methods/account.saveTheme.html" name="account.saveTheme">Save a theme: account.saveTheme</a>

2
docs

@ -1 +1 @@
Subproject commit 54835c5b71a119041f6639d69262a81b6b7ca310 Subproject commit 8c9a9de0318fb2e52cf802bdc5dcb83660ee4fc6

View File

@ -151,7 +151,7 @@ class MyEventHandler extends SimpleEventHandler
#[FilterCommand('story')] #[FilterCommand('story')]
public function storyCommand(Message & FromAdmin $message): void public function storyCommand(Message & FromAdmin $message): void
{ {
if ($this->isBot()) { if ($this->isSelfBot()) {
$message->reply("Only users can post Telegram Stories!"); $message->reply("Only users can post Telegram Stories!");
return; return;
} }

View File

@ -0,0 +1,87 @@
<?php declare(strict_types=1);
/**
* Telegram stories downloader bot.
*
* Copyright 2016-2020 Daniil Gentili
* (https://daniil.it)
* This file is part of MadelineProto.
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU General Public License along with MadelineProto.
* If not, see <http://www.gnu.org/licenses/>.
*
* @author Daniil Gentili <daniil@daniil.it>
* @copyright 2016-2023 Daniil Gentili <daniil@daniil.it>
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
* @link https://docs.madelineproto.xyz MadelineProto documentation
*/
use danog\MadelineProto\API;
use danog\MadelineProto\EventHandler\Filter\FilterCommand;
use danog\MadelineProto\EventHandler\Message;
use danog\MadelineProto\EventHandler\SimpleFilter\Incoming;
use danog\MadelineProto\ParseMode;
use danog\MadelineProto\SimpleEventHandler;
require 'vendor/autoload.php';
final class StoriesEventHandler extends SimpleEventHandler
{
private const HELP = "Telegram stories downloader bot, powered by @MadelineProto!\n\nUsage:\n- /dlStories @username - Download all the stories of a username!";
private API $userInstance;
public function onStart(): void
{
// Login as a user
$this->userInstance = new API('stories_user.madeline');
$this->userInstance->start();
if (!$this->userInstance->isSelfUser()) {
throw new AssertionError("You must login as a user! Please delete the user.madeline folder to continue.");
}
}
#[FilterCommand('start')]
public function startCmd(Incoming&Message $message): void
{
$message->reply(self::HELP, parseMode: ParseMode::MARKDOWN);
}
/**
* Downloads all telegram stories of a user (including protected ones).
*
* The bot must be started via web for this command to work.
*
* You can also start it via CLI but you'll have to specify a download script URL in the settings: https://docs.madelineproto.xyz/docs/FILES.html#getting-a-download-link-cli-bots.
*/
#[FilterCommand('dlStories')]
public function dlStoriesCommand(Message $message): void
{
if (!$message->commandArgs) {
$message->reply("You must specify the @username or the Telegram ID of a user to download their stories!");
return;
}
$stories = $this->userInstance->stories->getUserStories(user_id: $message->commandArgs[0])['stories']['stories'];
// Skip deleted stories
$stories = array_filter($stories, fn (array $s): bool => $s['_'] === 'storyItem');
// Sort by date
usort($stories, fn ($a, $b) => $a['date'] <=> $b['date']);
$result = "Total stories: ".count($stories)."\n\n";
foreach ($stories as $story) {
$cur = "- ID {$story['id']}, posted ".date(DATE_RFC850, $story['date']);
if (isset($story['caption'])) {
$cur .= ', "'.self::markdownEscape($story['caption']).'"';
}
$result .= "$cur; [click here to download »]({$this->userInstance->getDownloadLink($story)})\n";
}
$message->reply($result, parseMode: ParseMode::MARKDOWN);
}
}
$token = '<token>';
StoriesEventHandler::startAndLoopBot('stories.madeline', $token);

View File

@ -1189,13 +1189,6 @@ abstract class InternalDoc
{ {
return \danog\MadelineProto\Tools::isArrayOrAlike($var); return \danog\MadelineProto\Tools::isArrayOrAlike($var);
} }
/**
* Returns whether the current user is a bot.
*/
public function isBot(): bool
{
return $this->wrapper->getAPI()->isBot();
}
/** /**
* Check if the specified peer is a forum. * Check if the specified peer is a forum.
* *
@ -1225,6 +1218,20 @@ abstract class InternalDoc
{ {
return $this->wrapper->getAPI()->isPremium(); return $this->wrapper->getAPI()->isPremium();
} }
/**
* Returns whether the current user is a bot.
*/
public function isSelfBot(): bool
{
return $this->wrapper->getAPI()->isSelfBot();
}
/**
* Returns whether the current user is a user.
*/
public function isSelfUser(): bool
{
return $this->wrapper->getAPI()->isSelfUser();
}
/** /**
* Check whether provided bot API ID is a channel or supergroup. * Check whether provided bot API ID is a channel or supergroup.
* *
@ -1234,13 +1241,6 @@ abstract class InternalDoc
{ {
return \danog\MadelineProto\MTProto::isSupergroup($id); return \danog\MadelineProto\MTProto::isSupergroup($id);
} }
/**
* Returns whether the current user is a user.
*/
public function isUser(): bool
{
return $this->wrapper->getAPI()->isUser();
}
/** /**
* Logger. * Logger.
* *

View File

@ -1532,14 +1532,14 @@ final class MTProto implements TLCallback, LoggerGetter
/** /**
* Returns whether the current user is a bot. * Returns whether the current user is a bot.
*/ */
public function isBot(): bool public function isSelfBot(): bool
{ {
return $this->authorization['user']['bot']; return $this->authorization['user']['bot'];
} }
/** /**
* Returns whether the current user is a user. * Returns whether the current user is a user.
*/ */
public function isUser(): bool public function isSelfUser(): bool
{ {
return !$this->authorization['user']['bot']; return !$this->authorization['user']['bot'];
} }

View File

@ -195,8 +195,9 @@ abstract class Serialization
Logger::log("We don't have access to the event handler class, so we can't start it.", Logger::ERROR); Logger::log("We don't have access to the event handler class, so we can't start it.", Logger::ERROR);
Logger::log('Please start the event handler or unset it to use the IPC server.', Logger::ERROR); Logger::log('Please start the event handler or unset it to use the IPC server.', Logger::ERROR);
return $ipcSocket ?? self::tryConnect($session->getIpcPath(), $cancelIpc->getFuture()); return $ipcSocket ?? self::tryConnect($session->getIpcPath(), $cancelIpc->getFuture());
} elseif (\is_subclass_of($class, EventHandler::class)) {
EventHandler::cachePlugins($class);
} }
EventHandler::cachePlugins($class);
} }
$tempId = Shutdown::addCallback($unlock = static function () use ($unlock): void { $tempId = Shutdown::addCallback($unlock = static function () use ($unlock): void {