diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b6425650..1490e0610 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@ Features:
- 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 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.
- CLI bots: you can now optionally specify a default download link URL (used by `getDownloadLink`) in the settings.
diff --git a/README.md b/README.md
index 81b6191e9..0360e7c0f 100644
--- a/README.md
+++ b/README.md
@@ -771,9 +771,9 @@ Want to add your own open-source project to this list? [Click here!](https://doc
* Returns the session name: getSessionName
* Returns the support user for the "ask a question" feature: help.getSupport
* Returns users found by username substring: contacts.search
- * Returns whether the current user is a bot: isBot
+ * Returns whether the current user is a bot: isSelfBot
* Returns whether the current user is a premium user, cached: isPremium
- * Returns whether the current user is a user: isUser
+ * Returns whether the current user is a user: isSelfUser
* Reupload telegram file: uploadFromTgfile
* Save a message draft associated to a chat: messages.saveDraft
* Save a theme: account.saveTheme
diff --git a/docs b/docs
index 54835c5b7..8c9a9de03 160000
--- a/docs
+++ b/docs
@@ -1 +1 @@
-Subproject commit 54835c5b71a119041f6639d69262a81b6b7ca310
+Subproject commit 8c9a9de0318fb2e52cf802bdc5dcb83660ee4fc6
diff --git a/examples/bot.php b/examples/bot.php
index 0a00123f8..6f755bbf6 100755
--- a/examples/bot.php
+++ b/examples/bot.php
@@ -151,7 +151,7 @@ class MyEventHandler extends SimpleEventHandler
#[FilterCommand('story')]
public function storyCommand(Message & FromAdmin $message): void
{
- if ($this->isBot()) {
+ if ($this->isSelfBot()) {
$message->reply("Only users can post Telegram Stories!");
return;
}
diff --git a/examples/tgstories_dl_bot.php b/examples/tgstories_dl_bot.php
new file mode 100644
index 000000000..c969ccfdc
--- /dev/null
+++ b/examples/tgstories_dl_bot.php
@@ -0,0 +1,87 @@
+.
+ *
+ * @author Daniil Gentili
+ * @copyright 2016-2023 Daniil Gentili
+ * @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 = '';
+
+StoriesEventHandler::startAndLoopBot('stories.madeline', $token);
diff --git a/src/InternalDoc.php b/src/InternalDoc.php
index a3eaff9fa..6df8908dd 100644
--- a/src/InternalDoc.php
+++ b/src/InternalDoc.php
@@ -1189,13 +1189,6 @@ abstract class InternalDoc
{
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.
*
@@ -1225,6 +1218,20 @@ abstract class InternalDoc
{
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.
*
@@ -1234,13 +1241,6 @@ abstract class InternalDoc
{
return \danog\MadelineProto\MTProto::isSupergroup($id);
}
- /**
- * Returns whether the current user is a user.
- */
- public function isUser(): bool
- {
- return $this->wrapper->getAPI()->isUser();
- }
/**
* Logger.
*
diff --git a/src/MTProto.php b/src/MTProto.php
index e0b5c906c..5f0b4de1b 100644
--- a/src/MTProto.php
+++ b/src/MTProto.php
@@ -1532,14 +1532,14 @@ final class MTProto implements TLCallback, LoggerGetter
/**
* Returns whether the current user is a bot.
*/
- public function isBot(): bool
+ public function isSelfBot(): bool
{
return $this->authorization['user']['bot'];
}
/**
* Returns whether the current user is a user.
*/
- public function isUser(): bool
+ public function isSelfUser(): bool
{
return !$this->authorization['user']['bot'];
}
diff --git a/src/Serialization.php b/src/Serialization.php
index d28e2f24f..caee0c5a0 100644
--- a/src/Serialization.php
+++ b/src/Serialization.php
@@ -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('Please start the event handler or unset it to use the IPC server.', Logger::ERROR);
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 {