mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-26 21:34:41 +01:00
Implement PSR-4 autoloading for plugin paths
This commit is contained in:
parent
7d47e1f126
commit
8f66319b66
@ -17,6 +17,7 @@ Features:
|
||||
- Added support for `pay`, `login_url`, `web_app` and `tg://user?id=` buttons in bot API syntax!
|
||||
- Added a `getAdmin` function that returns the ID of the admin of the bot (which is equal to the first peer returned by getReportPeers in the event handler).
|
||||
- getPlugin can now be used from IPC clients!
|
||||
- `getReply`, `sendMessage`, `reply`
|
||||
|
||||
Fixes:
|
||||
- Fixed file uploads with ext-uv!
|
||||
|
@ -458,7 +458,7 @@ 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#getdhconfig-array" name="getDhConfig">Get diffie-hellman configuration: getDhConfig</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getdownloadinfo-mixed-messagemedia-array-ext-string-name-string-mime-string-size-int-inputfilelocation-array" name="getDownloadInfo">Get download info of file: getDownloadInfo</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getpropicinfo-mixed-data-array" name="getPropicInfo">Get download info of the propic of a user: getPropicInfo</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#geteventhandler-danog-madelineproto-eventhandler-__php_incomplete_class-null" name="getEventHandler">Get event handler: getEventHandler</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#geteventhandler-danog-madelineproto-eventhandler-danog-madelineproto-ipc-eventhandlerproxy-__php_incomplete_class-null" name="getEventHandler">Get event handler: getEventHandler</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getextensionfromlocation-mixed-location-string-default-string" name="getExtensionFromLocation">Get extension from file location: getExtensionFromLocation</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getextensionfrommime-string-mime-string" name="getExtensionFromMime">Get extension from mime type: getExtensionFromMime</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.getFavedStickers.html" name="messages.getFavedStickers">Get faved stickers: messages.getFavedStickers</a>
|
||||
@ -628,7 +628,7 @@ Want to add your own open-source project to this list? [Click here!](https://doc
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.readMessageContents.html" name="messages.readMessageContents">Notifies the sender about the recipient having listened a voice message or watched a video: messages.readMessageContents</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.sendScreenshotNotification.html" name="messages.sendScreenshotNotification">Notify the other user in a private chat that a screenshot of the chat was taken: messages.sendScreenshotNotification</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/users.setSecureValueErrors.html" name="users.setSecureValueErrors">Notify the user that the sent passport data contains some errors The user will not be able to re-submit their Passport data to you until the errors are fixed (the contents of the field for which you returned the error must change): users.setSecureValueErrors</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getplugin-class-string-t-class-danog-madelineproto-plugineventhandler-danog-madelineproto-ipc-plugineventhandlerproxy-null" name="getPlugin">Obtain a certain event handler plugin instance: getPlugin</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#getplugin-class-string-t-class-danog-madelineproto-plugineventhandler-danog-madelineproto-ipc-eventhandlerproxy-null" name="getPlugin">Obtain a certain event handler plugin instance: getPlugin</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/bots.getBotCommands.html" name="bots.getBotCommands">Obtain a list of bot commands for the specified bot scope and language code: bots.getBotCommands</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.getEmojiKeywordsLanguages.html" name="messages.getEmojiKeywordsLanguages">Obtain a list of related languages that must be used when fetching emoji keyword lists »: messages.getEmojiKeywordsLanguages</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.getAvailableReactions.html" name="messages.getAvailableReactions">Obtain available message reactions »: messages.getAvailableReactions</a>
|
||||
@ -755,6 +755,7 @@ 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#broadcastmessages-array-messages-danog-madelineproto-broadcast-filter-filter-bool-pin-int" name="broadcastMessages">Sends a list of messages to all peers (users, chats, channels) of the bot: broadcastMessages</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.sendMessage.html" name="messages.sendMessage">Sends a message to a chat: messages.sendMessage</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.sendEncryptedFile.html" name="messages.sendEncryptedFile">Sends a message with a file attachment to a secret chat: messages.sendEncryptedFile</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#sendmessage-int-string-peer-string-message-html-markdown-null-parsemode-int-null-replytomsgid-int-null-topmsgid-array-null-replymarkup-int-null-sendas-int-null-scheduledate-bool-silent-bool-noforwards-bool-background-bool-cleardraft-bool-nowebpage-bool-updatestickersetsorder-message" name="sendMessage">Sends a message: sendMessage</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.sendEncryptedService.html" name="messages.sendEncryptedService">Sends a service message to a secret chat: messages.sendEncryptedService</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.sendEncrypted.html" name="messages.sendEncrypted">Sends a text message to a secret chat: messages.sendEncrypted</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#sendcustomevent-mixed-payload-void" name="sendCustomEvent">Sends an updateCustomEvent update to the event handler: sendCustomEvent</a>
|
||||
@ -827,7 +828,7 @@ 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#uploadfromcallable-mixed-callable-int-size-string-mime-string-filename-callable-cb-bool-seekable-bool-encrypted-mixed" name="uploadFromCallable">Upload file from callable: uploadFromCallable</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#uploadfromstream-mixed-stream-int-size-string-mime-string-filename-callable-cb-bool-encrypted-mixed" name="uploadFromStream">Upload file from stream: uploadFromStream</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#uploadencrypted-filecallbackinterface-string-array-file-string-filename-callable-cb-mixed" name="uploadEncrypted">Upload file to secret chat: uploadEncrypted</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#upload-filecallbackinterface-string-array-resource-file-string-filename-callable-cb-bool-encrypted-mixed" name="upload">Upload file: upload</a>
|
||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#upload-filecallbackinterface-localfile-string-array-resource-file-string-filename-callable-cb-bool-encrypted-mixed" name="upload">Upload file: upload</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/account.uploadRingtone.html" name="account.uploadRingtone">Upload notification sound, use account.saveRingtone to convert it and add it to the list of saved notification sounds: account.uploadRingtone</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/account.uploadTheme.html" name="account.uploadTheme">Upload theme: account.uploadTheme</a>
|
||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.setGameScore.html" name="messages.setGameScore">Use this method to set the score of the specified user in a game sent as a normal message (bots only): messages.setGameScore</a>
|
||||
|
@ -155,7 +155,6 @@ abstract class EventHandler extends AbstractAPI
|
||||
$this->setReportPeers(Tools::call($this->getReportPeers())->await());
|
||||
}
|
||||
|
||||
$old = true;
|
||||
$constructors = $this->getTL()->getConstructors();
|
||||
$methods = [];
|
||||
$handlers = [];
|
||||
@ -182,6 +181,9 @@ abstract class EventHandler extends AbstractAPI
|
||||
];
|
||||
continue;
|
||||
}
|
||||
if (!$this instanceof SimpleEventHandler) {
|
||||
continue;
|
||||
}
|
||||
if ($periodic = $methodRefl->getAttributes(Cron::class)) {
|
||||
$periodic = $periodic[0]->newInstance();
|
||||
$this->periodicLoops[$method] = new PeriodicLoop(
|
||||
@ -192,7 +194,6 @@ abstract class EventHandler extends AbstractAPI
|
||||
$periodic->period
|
||||
);
|
||||
$this->periodicLoops[$method]->start();
|
||||
$old = false;
|
||||
continue;
|
||||
}
|
||||
$filter = $methodRefl->getAttributes(
|
||||
@ -217,9 +218,8 @@ abstract class EventHandler extends AbstractAPI
|
||||
EventLoop::queue($closure, $update);
|
||||
}
|
||||
};
|
||||
$old = false;
|
||||
}
|
||||
if (!$old) {
|
||||
if ($this instanceof SimpleEventHandler) {
|
||||
self::validateEventHandler(static::class);
|
||||
}
|
||||
if ($has_any) {
|
||||
@ -236,6 +236,9 @@ abstract class EventHandler extends AbstractAPI
|
||||
$plugin = $pluginsPrev[$class] ?? $pluginsNew[$class] ?? new $class;
|
||||
$pluginsNew[$class] = $plugin;
|
||||
[$newMethods, $newHandlers] = $plugin->internalStart($MadelineProto, $pluginsPrev, $pluginsNew, false) ?? [];
|
||||
if (!$plugin->isPluginEnabled()) {
|
||||
continue;
|
||||
}
|
||||
foreach ($newMethods as $update => $method) {
|
||||
$methods[$update] ??= [];
|
||||
$methods[$update][] = $method;
|
||||
@ -303,22 +306,47 @@ abstract class EventHandler extends AbstractAPI
|
||||
private static array $includedPaths = [];
|
||||
/**
|
||||
* Obtain a list of plugin event handlers.
|
||||
*
|
||||
* @return list<class-string<PluginEventHandler>>
|
||||
*/
|
||||
private function internalGetPlugins(): array
|
||||
{
|
||||
$plugins = $this->getPlugins();
|
||||
$this->internalGetDirectoryPlugins($plugins);
|
||||
$plugins = \array_values(\array_unique($plugins, SORT_REGULAR));
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
Assert::classExists($plugin);
|
||||
Assert::true(\is_subclass_of($plugin, PluginEventHandler::class), "$plugin must extend ".PluginEventHandler::class);
|
||||
Assert::notEq($plugin, PluginEventHandler::class);
|
||||
Assert::true(\str_contains(\ltrim($plugin, '\\'), '\\'), "$plugin must be in a namespace!");
|
||||
self::validateEventHandler($plugin);
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
private function internalGetDirectoryPlugins(array &$plugins): void
|
||||
{
|
||||
if ($this instanceof PluginEventHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
$paths = $this->getPluginPaths();
|
||||
if (\is_string($paths)) {
|
||||
$paths = [$paths];
|
||||
} elseif ($paths === null) {
|
||||
$paths = [];
|
||||
}
|
||||
if (!$paths) {
|
||||
return;
|
||||
}
|
||||
$paths = \array_map(realpath(...), $paths);
|
||||
|
||||
$plugins = \array_values($this->getPlugins());
|
||||
|
||||
$recurse = static function (string $path) use (&$recurse, &$plugins): void {
|
||||
$recurse = static function (string $path, string $namespace = 'MadelinePlugin') use (&$recurse, &$plugins): void {
|
||||
foreach (listFiles($path) as $file) {
|
||||
if (isDirectory($file)) {
|
||||
$recurse($file);
|
||||
$recurse($file, $namespace.'\\'.\basename($file));
|
||||
} elseif (isFile($file) && \str_ends_with($file, "Plugin.php")) {
|
||||
$file = \realpath($file);
|
||||
if (isset(self::$includedPaths[$file])) {
|
||||
@ -328,8 +356,7 @@ abstract class EventHandler extends AbstractAPI
|
||||
try {
|
||||
require $file;
|
||||
} catch (PluginRegistration $e) {
|
||||
$name = \substr($e->plugin, \strrpos($e->plugin, '\\')+1);
|
||||
Assert::eq($name, \basename($file, '.php'));
|
||||
Assert::eq($e->plugin, $namespace.'\\'.\basename($file, '.php'));
|
||||
$plugins []= $e->plugin;
|
||||
continue;
|
||||
}
|
||||
@ -345,17 +372,19 @@ abstract class EventHandler extends AbstractAPI
|
||||
self::$includingPlugins = false;
|
||||
}
|
||||
|
||||
$plugins = \array_values(\array_unique($plugins, SORT_REGULAR));
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
Assert::classExists($plugin);
|
||||
Assert::true(\is_subclass_of($plugin, PluginEventHandler::class), "$plugin must extend ".PluginEventHandler::class);
|
||||
Assert::notEq($plugin, PluginEventHandler::class);
|
||||
Assert::true(\str_contains(\ltrim($plugin, '\\'), '\\'), "$plugin must be in a namespace!");
|
||||
self::validateEventHandler($plugin);
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
\spl_autoload_register(function (string $class) use ($paths): void {
|
||||
if (!\str_starts_with($class, 'MadelinePlugin\\')) {
|
||||
return;
|
||||
}
|
||||
// Has leading /
|
||||
$file = \str_replace('\\', DIRECTORY_SEPARATOR, \substr($class, 14)).'.php';
|
||||
foreach ($paths as $path) {
|
||||
if (\file_exists($path.$file)) {
|
||||
require $path.$file;
|
||||
Assert::classExists($class);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private const BANNED_FUNCTIONS = [
|
||||
|
@ -113,4 +113,50 @@ abstract class AbstractMessage extends Update implements SimpleFilters
|
||||
]
|
||||
)['messages'][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replies to the message.
|
||||
*
|
||||
* @param string $message Message to send
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param array|null $replyMarkup Keyboard information.
|
||||
* @param integer|null $sendAs Peer to send the message as.
|
||||
* @param integer|null $scheduleDate Schedule date.
|
||||
* @param boolean $silent Whether to send the message silently, without triggering notifications.
|
||||
* @param boolean $background Send this message as background message
|
||||
* @param boolean $clearDraft Clears the draft field
|
||||
* @param boolean $noWebpage Set this flag to disable generation of the webpage preview
|
||||
* @param boolean $updateStickersetsOrder Whether to move used stickersets to top
|
||||
*
|
||||
*/
|
||||
public function reply(
|
||||
string $message,
|
||||
?string $parseMode = null,
|
||||
?array $replyMarkup = null,
|
||||
int|string|null $sendAs = null,
|
||||
?int $scheduleDate = null,
|
||||
bool $silent = false,
|
||||
bool $noForwards = false,
|
||||
bool $background = false,
|
||||
bool $clearDraft = false,
|
||||
bool $noWebpage = false,
|
||||
bool $updateStickersetsOrder = false,
|
||||
): Message {
|
||||
return $this->API->sendMessage(
|
||||
peer: $this->chatId,
|
||||
message: $message,
|
||||
parseMode: $parseMode,
|
||||
replyToMsgId: $this->id,
|
||||
topMsgId: $this->topicId === 1 ? null : $this->topicId,
|
||||
replyMarkup: $replyMarkup,
|
||||
sendAs: $sendAs,
|
||||
scheduleDate: $scheduleDate,
|
||||
silent: $silent,
|
||||
noForwards: $noForwards,
|
||||
background: $background,
|
||||
clearDraft: $clearDraft,
|
||||
noWebpage: $noWebpage,
|
||||
updateStickersetsOrder: $updateStickersetsOrder
|
||||
);
|
||||
}
|
||||
}
|
||||
|
37
src/EventHandler/Filter/FilterFromSenders.php
Normal file
37
src/EventHandler/Filter/FilterFromSenders.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace danog\MadelineProto\EventHandler\Filter;
|
||||
|
||||
use Attribute;
|
||||
use danog\MadelineProto\EventHandler;
|
||||
use danog\MadelineProto\EventHandler\Message\GroupMessage;
|
||||
use danog\MadelineProto\EventHandler\Update;
|
||||
|
||||
/**
|
||||
* Allow incoming or outgoing group messages made by a certain list of senders.
|
||||
*/
|
||||
#[Attribute(Attribute::TARGET_METHOD)]
|
||||
final class FilterFromSenders extends Filter
|
||||
{
|
||||
/** @var array<string|int> */
|
||||
private readonly array $peers;
|
||||
/** @var list<string|int> */
|
||||
private readonly array $peersResolved;
|
||||
public function __construct(string|int ...$idOrUsername)
|
||||
{
|
||||
$this->peers = \array_unique($idOrUsername);
|
||||
}
|
||||
public function initialize(EventHandler $API): ?Filter
|
||||
{
|
||||
$res = [];
|
||||
foreach ($this->peers as $peer) {
|
||||
$res []= $API->getId($peer);
|
||||
}
|
||||
$this->peersResolved = $res;
|
||||
return null;
|
||||
}
|
||||
public function apply(Update $update): bool
|
||||
{
|
||||
return $update instanceof GroupMessage && \in_array($update->senderId, $this->peersResolved, true);
|
||||
}
|
||||
}
|
@ -767,7 +767,7 @@ abstract class InternalDoc
|
||||
/**
|
||||
* Get event handler.
|
||||
*/
|
||||
public function getEventHandler(): \danog\MadelineProto\EventHandler|\__PHP_Incomplete_Class|null
|
||||
public function getEventHandler(): \danog\MadelineProto\EventHandler|\danog\MadelineProto\Ipc\EventHandlerProxy|\__PHP_Incomplete_Class|null
|
||||
{
|
||||
return $this->wrapper->getAPI()->getEventHandler();
|
||||
}
|
||||
@ -951,7 +951,7 @@ abstract class InternalDoc
|
||||
*
|
||||
* return T|null
|
||||
*/
|
||||
public function getPlugin(string $class): \danog\MadelineProto\PluginEventHandler|\danog\MadelineProto\Ipc\PluginEventHandlerProxy|null
|
||||
public function getPlugin(string $class): \danog\MadelineProto\PluginEventHandler|\danog\MadelineProto\Ipc\EventHandlerProxy|null
|
||||
{
|
||||
return $this->wrapper->getAPI()->getPlugin($class);
|
||||
}
|
||||
@ -1485,6 +1485,28 @@ abstract class InternalDoc
|
||||
{
|
||||
$this->wrapper->getAPI()->sendCustomEvent($payload);
|
||||
}
|
||||
/**
|
||||
* Sends a message.
|
||||
*
|
||||
* @param integer|string $peer Destination peer or username.
|
||||
* @param string $message Message to send
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param integer|null $replyToMsgId ID of message to reply to.
|
||||
* @param integer|null $topMsgId ID of thread where to send the message.
|
||||
* @param array|null $replyMarkup Keyboard information.
|
||||
* @param integer|null $sendAs Peer to send the message as.
|
||||
* @param integer|null $scheduleDate Schedule date.
|
||||
* @param boolean $silent Whether to send the message silently, without triggering notifications.
|
||||
* @param boolean $background Send this message as background message
|
||||
* @param boolean $clearDraft Clears the draft field
|
||||
* @param boolean $noWebpage Set this flag to disable generation of the webpage preview
|
||||
* @param boolean $updateStickersetsOrder Whether to move used stickersets to top
|
||||
*
|
||||
*/
|
||||
public function sendMessage(string|int $peer, string $message, ?string $parseMode = null, ?int $replyToMsgId = null, ?int $topMsgId = null, ?array $replyMarkup = null, string|int|null $sendAs = null, ?int $scheduleDate = null, bool $silent = false, bool $noForwards = false, bool $background = false, bool $clearDraft = false, bool $noWebpage = false, bool $updateStickersetsOrder = false): \danog\MadelineProto\EventHandler\Message
|
||||
{
|
||||
return $this->wrapper->getAPI()->sendMessage($peer, $message, $parseMode, $replyToMsgId, $topMsgId, $replyMarkup, $sendAs, $scheduleDate, $silent, $noForwards, $background, $clearDraft, $noWebpage, $updateStickersetsOrder);
|
||||
}
|
||||
/**
|
||||
* Set NOOP update handler, ignoring all updates.
|
||||
*/
|
||||
@ -1740,10 +1762,10 @@ abstract class InternalDoc
|
||||
/**
|
||||
* Upload file.
|
||||
*
|
||||
* @param FileCallbackInterface|string|array|resource $file File, URL or Telegram file to upload
|
||||
* @param string $fileName File name
|
||||
* @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
|
||||
* @param boolean $encrypted Whether to encrypt file for secret chats
|
||||
* @param FileCallbackInterface|LocalFile|string|array|resource $file File, URL or Telegram file to upload
|
||||
* @param string $fileName File name
|
||||
* @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
|
||||
* @param boolean $encrypted Whether to encrypt file for secret chats
|
||||
*/
|
||||
public function upload($file, string $fileName = '', ?callable $cb = null, bool $encrypted = false)
|
||||
{
|
||||
|
@ -312,17 +312,12 @@ final class Client extends ClientAbstract
|
||||
{
|
||||
throw new Exception("Can't use ".__FUNCTION__.' in an IPC client instance, please use startAndLoop, instead!');
|
||||
}
|
||||
/**
|
||||
* Placeholder.
|
||||
*
|
||||
* @param mixed ...$params Params
|
||||
*/
|
||||
public function getEventHandler(mixed ...$params): void
|
||||
public function getEventHandler(): EventHandlerProxy
|
||||
{
|
||||
throw new Exception("Can't use ".__FUNCTION__.' in an IPC client instance, please use startAndLoop, instead!');
|
||||
return $this->hasEventHandler() ? new EventHandlerProxy(null, $this) : null;
|
||||
}
|
||||
public function getPlugin(string $class): ?PluginEventHandlerProxy
|
||||
public function getPlugin(string $class): ?EventHandlerProxy
|
||||
{
|
||||
return $this->hasPlugin($class) ? new PluginEventHandlerProxy($class, $this) : null;
|
||||
return $this->hasPlugin($class) ? new EventHandlerProxy($class, $this) : null;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ namespace danog\MadelineProto\Ipc;
|
||||
/**
|
||||
* Plugin event handler proxy object, for use through the IPC API.
|
||||
*/
|
||||
final class PluginEventHandlerProxy extends IpcCapable
|
||||
final class EventHandlerProxy extends IpcCapable
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ?string $__plugin,
|
16
src/Lang.php
16
src/Lang.php
@ -118,7 +118,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto ئامادەیە!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'نەتوانرا شێواز بدۆزرێتەوە: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -251,7 +251,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto is ready!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'Could not find method: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -384,7 +384,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto آماده است!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'تابع پیدا نشد: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -517,7 +517,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto est prêt!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'Could not find method: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -650,7 +650,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto מוכן!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'הפונקציה לא נמצא: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -916,7 +916,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto is ready!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'Could not find method: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -1049,7 +1049,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto tayyor!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'Metodni topib bo\'lmadi: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
@ -1184,7 +1184,7 @@ final class Lang
|
||||
'madelineproto_ready' => 'MadelineProto is ready!',
|
||||
'manualAdminActionRequired' => '!!!!!!!!! MANUAL SYSTEM ADMIN ACTION REQUIRED !!!!!!!!!',
|
||||
'method_not_found' => 'Could not find method: ',
|
||||
'mmapErrorPart1' => 'The maximum number of mmap\'ed regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart1' => 'The maximum number of memory mapped (mmap) regions was reached (%s): please increase the vm.max_map_count kernel config to 262144 to fix.',
|
||||
'mmapErrorPart2' => 'To fix, run the following command as root: %s',
|
||||
'mmapErrorPart3' => 'To persist the change across reboots: %s',
|
||||
'mmapErrorPart4' => 'On Windows and WSL, increasing the size of the pagefile might help; please switch to native Linux if the issue persists.',
|
||||
|
16
src/LocalFile.php
Normal file
16
src/LocalFile.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
/**
|
||||
* Indicates a local file to upload.
|
||||
*/
|
||||
final class LocalFile
|
||||
{
|
||||
public function __construct(
|
||||
public readonly string $file
|
||||
) {
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ use Amp\Sync\Lock;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\FileCallbackInterface;
|
||||
use danog\MadelineProto\Lang;
|
||||
use danog\MadelineProto\LocalFile;
|
||||
use danog\MadelineProto\NothingInTheSocketException;
|
||||
use danog\MadelineProto\Settings;
|
||||
use danog\MadelineProto\Stream\Common\BufferedRawStream;
|
||||
@ -229,10 +230,10 @@ trait FilesLogic
|
||||
/**
|
||||
* Upload file.
|
||||
*
|
||||
* @param FileCallbackInterface|string|array|resource $file File, URL or Telegram file to upload
|
||||
* @param string $fileName File name
|
||||
* @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
|
||||
* @param boolean $encrypted Whether to encrypt file for secret chats
|
||||
* @param FileCallbackInterface|LocalFile|string|array|resource $file File, URL or Telegram file to upload
|
||||
* @param string $fileName File name
|
||||
* @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
|
||||
* @param boolean $encrypted Whether to encrypt file for secret chats
|
||||
*/
|
||||
public function upload($file, string $fileName = '', ?callable $cb = null, bool $encrypted = false)
|
||||
{
|
||||
@ -250,10 +251,14 @@ trait FilesLogic
|
||||
if (\is_resource($file) || (\is_object($file) && $file instanceof ReadableStream)) {
|
||||
return $this->uploadFromStream($file, 0, '', $fileName, $cb, $encrypted);
|
||||
}
|
||||
$settings = $this->getSettings();
|
||||
/** @var Settings $settings */
|
||||
if (!$settings->getFiles()->getAllowAutomaticUpload()) {
|
||||
return $this->uploadFromUrl($file, 0, $fileName, $cb, $encrypted);
|
||||
if ($file instanceof LocalFile) {
|
||||
$file = $file->file;
|
||||
} else {
|
||||
/** @var Settings $settings */
|
||||
$settings = $this->getSettings();
|
||||
if (!$settings->getFiles()->getAllowAutomaticUpload()) {
|
||||
return $this->uploadFromUrl($file, 0, $fileName, $cb, $encrypted);
|
||||
}
|
||||
}
|
||||
$file = Tools::absolute($file);
|
||||
if (!exists($file)) {
|
||||
|
@ -101,7 +101,8 @@ final class MinDatabase implements TLCallback
|
||||
});
|
||||
}
|
||||
}
|
||||
public function sync(): void {
|
||||
public function sync(): void
|
||||
{
|
||||
if (!$this->synced) {
|
||||
EventLoop::queue(function (): void {
|
||||
$counter = 0;
|
||||
|
@ -31,11 +31,11 @@ use danog\MadelineProto\EventHandler\Message;
|
||||
use danog\MadelineProto\EventHandler\Message\ChannelMessage;
|
||||
use danog\MadelineProto\EventHandler\Message\GroupMessage;
|
||||
use danog\MadelineProto\EventHandler\Message\PrivateMessage;
|
||||
use danog\MadelineProto\EventHandler\Service\DialogCreated;
|
||||
use danog\MadelineProto\EventHandler\Service\DialogMemberLeft;
|
||||
use danog\MadelineProto\EventHandler\Service\DialogMembersJoined;
|
||||
use danog\MadelineProto\EventHandler\Service\DialogPhotoChanged;
|
||||
use danog\MadelineProto\EventHandler\Service\DialogTitleChanged;
|
||||
use danog\MadelineProto\EventHandler\Message\Service\DialogCreated;
|
||||
use danog\MadelineProto\EventHandler\Message\Service\DialogMemberLeft;
|
||||
use danog\MadelineProto\EventHandler\Message\Service\DialogMembersJoined;
|
||||
use danog\MadelineProto\EventHandler\Message\Service\DialogPhotoChanged;
|
||||
use danog\MadelineProto\EventHandler\Message\Service\DialogTitleChanged;
|
||||
use danog\MadelineProto\EventHandler\Update;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\Lang;
|
||||
@ -391,6 +391,60 @@ trait UpdateHandler
|
||||
API::PEER_TYPE_CHANNEL => new ChannelMessage($this, $message),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Sends a message.
|
||||
*
|
||||
* @param integer|string $peer Destination peer or username.
|
||||
* @param string $message Message to send
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param integer|null $replyToMsgId ID of message to reply to.
|
||||
* @param integer|null $topMsgId ID of thread where to send the message.
|
||||
* @param array|null $replyMarkup Keyboard information.
|
||||
* @param integer|null $sendAs Peer to send the message as.
|
||||
* @param integer|null $scheduleDate Schedule date.
|
||||
* @param boolean $silent Whether to send the message silently, without triggering notifications.
|
||||
* @param boolean $background Send this message as background message
|
||||
* @param boolean $clearDraft Clears the draft field
|
||||
* @param boolean $noWebpage Set this flag to disable generation of the webpage preview
|
||||
* @param boolean $updateStickersetsOrder Whether to move used stickersets to top
|
||||
*
|
||||
*/
|
||||
public function sendMessage(
|
||||
int|string $peer,
|
||||
string $message,
|
||||
?string $parseMode = null,
|
||||
?int $replyToMsgId = null,
|
||||
?int $topMsgId = null,
|
||||
?array $replyMarkup = null,
|
||||
int|string|null $sendAs = null,
|
||||
?int $scheduleDate = null,
|
||||
bool $silent = false,
|
||||
bool $noForwards = false,
|
||||
bool $background = false,
|
||||
bool $clearDraft = false,
|
||||
bool $noWebpage = false,
|
||||
bool $updateStickersetsOrder = false,
|
||||
): Message {
|
||||
return $this->wrapMessage($this->extractMessage($this->methodCallAsyncRead(
|
||||
'messages.sendMessage',
|
||||
[
|
||||
'peer' => $peer,
|
||||
'message' => $message,
|
||||
'parse_mode' => $parseMode,
|
||||
'reply_to_msg_id' => $replyToMsgId,
|
||||
'top_msg_id' => $topMsgId,
|
||||
'reply_markup' => $replyMarkup,
|
||||
'send_as' => $sendAs,
|
||||
'schedule_date' => $scheduleDate,
|
||||
'silent' => $silent,
|
||||
'noforwards' => $noForwards,
|
||||
'background' => $background,
|
||||
'clear_draft' => $clearDraft,
|
||||
'no_webpage' => $noWebpage,
|
||||
'update_stickersets_order' => $updateStickersetsOrder
|
||||
]
|
||||
)));
|
||||
}
|
||||
/**
|
||||
* Extract a message ID from an Updates constructor.
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@ namespace danog\MadelineProto;
|
||||
/**
|
||||
* Plugin event handler class.
|
||||
*/
|
||||
abstract class PluginEventHandler extends EventHandler
|
||||
abstract class PluginEventHandler extends SimpleEventHandler
|
||||
{
|
||||
/**
|
||||
* Plugins can require other plugins ONLY with the getPlugins() method.
|
||||
@ -32,4 +32,11 @@ abstract class PluginEventHandler extends EventHandler
|
||||
{
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Whether the plugin is enabled.
|
||||
*/
|
||||
public function isPluginEnabled(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ final class Files extends SettingsAbstract
|
||||
/**
|
||||
* Allow automatic upload of files from file paths present in constructors?
|
||||
*/
|
||||
protected bool $allowAutomaticUpload = true;
|
||||
protected bool $allowAutomaticUpload = false;
|
||||
/**
|
||||
* Upload parallel chunk count.
|
||||
*/
|
||||
|
28
src/SimpleEventHandler.php
Normal file
28
src/SimpleEventHandler.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* EventHandler module.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
namespace danog\MadelineProto;
|
||||
|
||||
/**
|
||||
* Simple event handler class: by extending this class, you can use filters, crons and the simplified event handler API.
|
||||
*/
|
||||
abstract class SimpleEventHandler extends EventHandler
|
||||
{
|
||||
}
|
@ -23,7 +23,7 @@ namespace danog\MadelineProto\Wrappers;
|
||||
use __PHP_Incomplete_Class;
|
||||
use danog\MadelineProto\EventHandler;
|
||||
use danog\MadelineProto\Exception;
|
||||
use danog\MadelineProto\Ipc\PluginEventHandlerProxy;
|
||||
use danog\MadelineProto\Ipc\EventHandlerProxy;
|
||||
use danog\MadelineProto\PluginEventHandler;
|
||||
use danog\MadelineProto\Settings;
|
||||
use danog\MadelineProto\UpdateHandlerType;
|
||||
@ -121,7 +121,7 @@ trait Events
|
||||
*
|
||||
* return T|null
|
||||
*/
|
||||
final public function getPlugin(string $class): PluginEventHandler|PluginEventHandlerProxy|null
|
||||
final public function getPlugin(string $class): PluginEventHandler|EventHandlerProxy|null
|
||||
{
|
||||
return $this->pluginInstances[$class] ?? null;
|
||||
}
|
||||
@ -141,7 +141,7 @@ trait Events
|
||||
/**
|
||||
* Get event handler.
|
||||
*/
|
||||
public function getEventHandler(): EventHandler|__PHP_Incomplete_Class|null
|
||||
public function getEventHandler(): EventHandler|EventHandlerProxy|__PHP_Incomplete_Class|null
|
||||
{
|
||||
return $this->event_handler_instance;
|
||||
}
|
||||
@ -153,28 +153,33 @@ trait Events
|
||||
return isset($this->event_handler_instance);
|
||||
}
|
||||
/** @internal */
|
||||
public function callPluginMethod(string $class, string $method, array $args): mixed
|
||||
public function callPluginMethod(?string $class, string $method, array $args): mixed
|
||||
{
|
||||
return $this->pluginInstances[$class]->$method(...$args);
|
||||
$obj = $class === null ? $this->event_handler_instance : $this->pluginInstances[$class];
|
||||
return $obj->$method(...$args);
|
||||
}
|
||||
/** @internal */
|
||||
public function setPluginProperty(string $class, string $property, mixed $value): void
|
||||
public function setPluginProperty(?string $class, string $property, mixed $value): void
|
||||
{
|
||||
$this->pluginInstances[$class]->$property = $value;
|
||||
$obj = $class === null ? $this->event_handler_instance : $this->pluginInstances[$class];
|
||||
$obj->$property = $value;
|
||||
}
|
||||
/** @internal */
|
||||
public function getPluginProperty(string $class, string $property): mixed
|
||||
public function getPluginProperty(?string $class, string $property): mixed
|
||||
{
|
||||
return $this->pluginInstances[$class]->$property;
|
||||
$obj = $class === null ? $this->event_handler_instance : $this->pluginInstances[$class];
|
||||
return $obj->$property;
|
||||
}
|
||||
/** @internal */
|
||||
public function issetPluginProperty(string $class, string $property): bool
|
||||
public function issetPluginProperty(?string $class, string $property): bool
|
||||
{
|
||||
return isset($this->pluginInstances[$class]->$property);
|
||||
$obj = $class === null ? $this->event_handler_instance : $this->pluginInstances[$class];
|
||||
return isset($obj->$property);
|
||||
}
|
||||
/** @internal */
|
||||
public function unsetPluginProperty(string $class, string $property): void
|
||||
public function unsetPluginProperty(?string $class, string $property): void
|
||||
{
|
||||
unset($this->pluginInstances[$class]->$property);
|
||||
$obj = $class === null ? $this->event_handler_instance : $this->pluginInstances[$class];
|
||||
unset($obj->$property);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user