mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 04:59:00 +01:00
Update
This commit is contained in:
parent
a2270bae9e
commit
60a7afb6a8
19
CHANGELOG.md
19
CHANGELOG.md
@ -2,6 +2,8 @@ Introducing MadelineProto's biggest update yet, 8.0.0-beta100!
|
||||
|
||||
This version introduces [plugins](https://docs.madelineproto.xyz/docs/PLUGINS.html), [bound methods](https://docs.madelineproto.xyz/docs/UPDATES.html#bound-methods), [filters](https://docs.madelineproto.xyz/docs/FILTERS.html), [a built-in cron system](https://docs.madelineproto.xyz/docs/UPDATES.html#cron), [IPC support for the event handler](https://docs.madelineproto.xyz/docs/UPDATES.html#persisting-data-and-ipc) and automatic static analysis for event handler code.
|
||||
|
||||
- [Plugins](https://docs.madelineproto.xyz/docs/PLUGINS.html)
|
||||
|
||||
To create a plugin, simply create an event handler that extends PluginEventHandler.
|
||||
|
||||
For example, create a `plugins/Danogentili/PingPlugin.php` file:
|
||||
@ -44,10 +46,16 @@ And use a [plugin base](https://raw.githubusercontent.com/danog/MadelineProto/v8
|
||||
|
||||
See the [documentation](https://docs.madelineproto.xyz/docs/PLUGINS.html) for more info on how to create MadelineProto plugins!
|
||||
|
||||
- [Message](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message.html) objects with bound methods
|
||||
|
||||
Both plugins and normal bots can make use of [bound update methods](https://docs.madelineproto.xyz/docs/UPDATES.html#bound-methods) like `reply()`, `delete()`, `getReply()`, `getHTML()` and simplified properties like `chatId`, `senderId`, `command`, `commandArgs` and many more, see the [documentation](https://docs.madelineproto.xyz/docs/UPDATES.html#bound-methods) for more info!
|
||||
|
||||
- [Filters](https://docs.madelineproto.xyz/docs/FILTERS.html)
|
||||
|
||||
Plugins and bots can now use three different filtering systems, to easily receive only updates satisfying certain conditions (incoming/outgoing, from group, channel, private, from an admin or a specific peer, with an audio/sticker/..., satisfying a certain regex or a certain /command, and much more!), [see the documentation](https://docs.madelineproto.xyz/docs/FILTERS.html) for more info!
|
||||
|
||||
- [Built-in cron system](https://docs.madelineproto.xyz/docs/UPDATES.html#cron)
|
||||
|
||||
All event handler methods marked by the `Cron` attribute are now automatically invoked by MadelineProto every `period` seconds:
|
||||
|
||||
```
|
||||
@ -68,10 +76,17 @@ class MyEventHandler extends SimpleEventHandler
|
||||
|
||||
See the [documentation](https://docs.madelineproto.xyz/docs/UPDATES.html#cron) for more info!
|
||||
|
||||
- [IPC support for the event handler](https://docs.madelineproto.xyz/docs/UPDATES.html#persisting-data-and-ipc)
|
||||
|
||||
You can now call event handler and plugin methods from outside of the event handler, using `getEventHandler()` on an `API` instance, see [the docs for more info](https://docs.madelineproto.xyz/docs/PLUGINS.html#limitations)!
|
||||
|
||||
- Automatic static analysis of event handler code
|
||||
|
||||
Finally, all new bots and plugins will be automatically analyzed by MadelineProto, blocking execution if performance or security issues are detected!
|
||||
|
||||
Other features:
|
||||
- Thanks to the many translation contributors @ https://weblate.madelineproto.xyz/, MadelineProto is now localized in Hebrew, Persian, Kurdish, Uzbek, Russian, French and Italian!
|
||||
- Added simplified `sendMessage`, `sendDocument`, `sendPhoto` methods that return abstract [Message](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message.html) objects with simplified properties and bound methods!
|
||||
- You can now use `Tools::callFork` to fork a new green thread!
|
||||
- You can now automatically pin messages broadcasted using `broadcastMessages`, `broadcastForwardMessages` by using the new `pin: true` parameter!
|
||||
- You can now use `sendMessageToAdmins` to send messages to the bot's admin (the peers returned by `getReportPeers`).
|
||||
@ -84,10 +99,6 @@ Other features:
|
||||
- You can now use `reportMemoryProfile()` to generate and send a `pprof` memory profile to all report peers to debug the causes of high memory usage.
|
||||
- Added support for `pay`, `login_url`, `web_app` and `tg://user?id=` buttons in bot API syntax!
|
||||
- Added a `getAdminIds` function that returns the IDs of the admin of the bot (equal to the peers returned by getReportPeers in the event handler).
|
||||
- getEventHandler can now be used from IPC clients!
|
||||
- Added `Cron`
|
||||
- Added plugins, filters, simple filters
|
||||
- `getReply`, `sendMessage`, `sendDocument`, `sendPhoto`, `reply`, `delete`
|
||||
|
||||
Fixes:
|
||||
- Fixed file uploads with ext-uv!
|
||||
|
@ -111,6 +111,7 @@ Want to add your own open-source project to this list? [Click here!](https://doc
|
||||
* [Filters](https://docs.madelineproto.xyz/docs/FILTERS.html)
|
||||
* [Simple filters](https://docs.madelineproto.xyz/docs/FILTERS.html#simple-filters)
|
||||
* [Attribute filters](https://docs.madelineproto.xyz/docs/FILTERS.html#attribute-filters)
|
||||
* [Creating custom attribute filters](https://docs.madelineproto.xyz/docs/FILTERS.html#creating-custom-attribute-filters)
|
||||
* [MTProto filters](https://docs.madelineproto.xyz/docs/FILTERS.html#mtproto-filters)
|
||||
* [Plugins](https://docs.madelineproto.xyz/docs/PLUGINS.html)
|
||||
* [Installing plugins](https://docs.madelineproto.xyz/docs/PLUGINS.html#installing-plugins)
|
||||
|
2
docs
2
docs
@ -1 +1 @@
|
||||
Subproject commit d3eb81be0cad837e7fd3f7f6d6e2f7b518b78b55
|
||||
Subproject commit 64bf195ee68d92bde6f49955ef735f58e9d6083c
|
@ -45,6 +45,7 @@ final class Progress implements JsonSerializable
|
||||
) {
|
||||
$this->percent = $pendingCount ? (int) (($successCount+$failCount)*100/$pendingCount) : 0;
|
||||
}
|
||||
/** @internal */
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return \get_object_vars($this);
|
||||
|
@ -9,6 +9,7 @@ enum CommandType: string implements JsonSerializable
|
||||
case SLASH = '/';
|
||||
case DOT = '.';
|
||||
case BANG = '!';
|
||||
/** @internal */
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return $this->value;
|
||||
|
@ -20,11 +20,14 @@ final class FilterNot extends Filter
|
||||
{
|
||||
$filter = $this->filter->initialize($API);
|
||||
if ($filter === null) {
|
||||
// The nested filter didn't replace itself
|
||||
return $this;
|
||||
}
|
||||
if ($filter instanceof self) {
|
||||
// The nested filter is a FilterNot, optimize !!A => A
|
||||
return $filter->filter;
|
||||
}
|
||||
// The nested filter replaced itself, re-wrap it
|
||||
return new self($filter);
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ abstract class Media extends IpcCapable implements JsonSerializable
|
||||
$this->spoiler = $rawMedia['spoiler'] ?? false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$v = \get_object_vars($this);
|
||||
|
@ -12,6 +12,7 @@ enum MaskPosition: int implements JsonSerializable
|
||||
case Mouth = 2;
|
||||
case Chin = 3;
|
||||
|
||||
/** @internal */
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return $this->value;
|
||||
|
@ -47,10 +47,8 @@ abstract class Message extends AbstractMessage
|
||||
|
||||
/**
|
||||
* Attached media.
|
||||
*
|
||||
* @var Audio|Document|DocumentPhoto|Gif|MaskSticker|Photo|RoundVideo|Sticker|Video|Voice|null
|
||||
*/
|
||||
public readonly ?Media $media;
|
||||
public readonly Audio|Document|DocumentPhoto|Gif|MaskSticker|Photo|RoundVideo|Sticker|Video|Voice|null $media;
|
||||
|
||||
/** Whether this message is a sent scheduled message */
|
||||
public readonly bool $fromScheduled;
|
||||
|
@ -10,6 +10,7 @@ use JsonSerializable;
|
||||
*/
|
||||
abstract class Update extends IpcCapable implements JsonSerializable
|
||||
{
|
||||
/** @internal */
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
$v = \get_object_vars($this);
|
||||
|
@ -28,14 +28,14 @@ final class FileCallback implements FileCallbackInterface
|
||||
/**
|
||||
* Callback.
|
||||
*
|
||||
* @var callable(float, float, float)
|
||||
* @var callable(float, float, int)
|
||||
*/
|
||||
public readonly mixed $callback;
|
||||
/**
|
||||
* Construct file callback.
|
||||
*
|
||||
* @param mixed $file File to download/upload
|
||||
* @param callable(float, float, float) $callback Callback
|
||||
* @param callable(float, float, int) $callback Callback
|
||||
*/
|
||||
public function __construct(public readonly mixed $file, callable $callback)
|
||||
{
|
||||
|
@ -767,7 +767,7 @@ abstract class InternalDoc
|
||||
/**
|
||||
* Get event handler (or plugin instance).
|
||||
*
|
||||
* @param ?class-string<PluginEventHandler>
|
||||
* @param ?class-string<PluginEventHandler> $class
|
||||
*/
|
||||
public function getEventHandler(?string $class = null): \danog\MadelineProto\EventHandler|\danog\MadelineProto\Ipc\EventHandlerProxy|\__PHP_Incomplete_Class|null
|
||||
{
|
||||
@ -1497,7 +1497,7 @@ abstract class InternalDoc
|
||||
* @param Message|Media|LocalFile|RemoteUrl|BotApiFileId|ReadableStream $file File to upload: can be a message to reuse media present in a message.
|
||||
* @param Message|Media|LocalFile|RemoteUrl|BotApiFileId|ReadableStream|null $thumb Optional: Thumbnail to upload
|
||||
* @param string $caption Caption of document
|
||||
* @param ?callable(float, float, float) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?callable(float, float, int) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?string $fileName Optional file name, if absent will be extracted from the passed $file.
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param integer|null $replyToMsgId ID of message to reply to.
|
||||
@ -1549,7 +1549,7 @@ abstract class InternalDoc
|
||||
* @param boolean $clearDraft Clears the draft field
|
||||
* @param boolean $noWebpage Set this flag to disable generation of the webpage preview
|
||||
*
|
||||
* @return list<Message>
|
||||
* @return list<\danog\Madelineproto\EventHandler\Message>
|
||||
*/
|
||||
public function sendMessageToAdmins(string $message, ?string $parseMode = null, ?array $replyMarkup = null, ?int $scheduleDate = null, bool $silent = false, bool $noForwards = false, bool $background = false, bool $clearDraft = false, bool $noWebpage = false): array
|
||||
{
|
||||
@ -1563,7 +1563,7 @@ abstract class InternalDoc
|
||||
* @param integer|string $peer Destination peer or username.
|
||||
* @param Message|Media|LocalFile|RemoteUrl|BotApiFileId|ReadableStream $file File to upload: can be a message to reuse media present in a message.
|
||||
* @param string $caption Caption of document
|
||||
* @param ?callable(float, float, float) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?callable(float, float, int) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?string $fileName Optional file name, if absent will be extracted from the passed $file.
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param integer|null $replyToMsgId ID of message to reply to.
|
||||
@ -1958,7 +1958,7 @@ abstract class InternalDoc
|
||||
/**
|
||||
* Wrap a media constructor into an abstract Media object.
|
||||
*/
|
||||
public function wrapMedia(array $media, bool $protected): ?\danog\MadelineProto\EventHandler\Media
|
||||
public function wrapMedia(array $media, bool $protected = false): ?\danog\MadelineProto\EventHandler\Media
|
||||
{
|
||||
return $this->wrapper->getAPI()->wrapMedia($media, $protected);
|
||||
}
|
||||
|
@ -1677,7 +1677,7 @@ final class MTProto implements TLCallback, LoggerGetter
|
||||
* @param boolean $clearDraft Clears the draft field
|
||||
* @param boolean $noWebpage Set this flag to disable generation of the webpage preview
|
||||
*
|
||||
* @return list<Message>
|
||||
* @return list<\danog\Madelineproto\EventHandler\Message>
|
||||
*/
|
||||
public function sendMessageToAdmins(
|
||||
string $message,
|
||||
|
@ -899,7 +899,7 @@ trait Files
|
||||
$seekable = false;
|
||||
}
|
||||
if ($offset === $end) {
|
||||
$cb(100, 0, 0);
|
||||
$cb(100.0, 0.0, 0);
|
||||
return true;
|
||||
}
|
||||
$params = [];
|
||||
@ -923,11 +923,11 @@ trait Files
|
||||
return true;
|
||||
}
|
||||
$count = \count($params);
|
||||
$time = 0;
|
||||
$speed = 0;
|
||||
$time = 0.0;
|
||||
$speed = 0.0;
|
||||
$origCb = $cb;
|
||||
$cb = static function () use ($cb, $count, &$time, &$speed): void {
|
||||
static $cur = 0;
|
||||
static $cur = 0.0;
|
||||
$cur++;
|
||||
$cb($cur * 100 / $count, $time, $speed);
|
||||
};
|
||||
@ -981,7 +981,7 @@ trait Files
|
||||
$this->clearCdnHashes($messageMedia['file_token']);
|
||||
}
|
||||
if (!isset($messageMedia['size'])) {
|
||||
$origCb(100, $time, $speed);
|
||||
$origCb(100.0, $time, $speed);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ trait FilesAbstraction
|
||||
/**
|
||||
* Wrap a media constructor into an abstract Media object.
|
||||
*/
|
||||
public function wrapMedia(array $media, bool $protected): ?Media
|
||||
public function wrapMedia(array $media, bool $protected = false): ?Media
|
||||
{
|
||||
if ($media['_'] === 'messageMediaPhoto') {
|
||||
if (!isset($media['photo'])) {
|
||||
@ -117,7 +117,7 @@ trait FilesAbstraction
|
||||
* @param Message|Media|LocalFile|RemoteUrl|BotApiFileId|ReadableStream $file File to upload: can be a message to reuse media present in a message.
|
||||
* @param Message|Media|LocalFile|RemoteUrl|BotApiFileId|ReadableStream|null $thumb Optional: Thumbnail to upload
|
||||
* @param string $caption Caption of document
|
||||
* @param ?callable(float, float, float) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?callable(float, float, int) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?string $fileName Optional file name, if absent will be extracted from the passed $file.
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param integer|null $replyToMsgId ID of message to reply to.
|
||||
@ -209,7 +209,7 @@ trait FilesAbstraction
|
||||
* @param integer|string $peer Destination peer or username.
|
||||
* @param Message|Media|LocalFile|RemoteUrl|BotApiFileId|ReadableStream $file File to upload: can be a message to reuse media present in a message.
|
||||
* @param string $caption Caption of document
|
||||
* @param ?callable(float, float, float) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?callable(float, float, int) $callback Upload callback (percent, speed in mpbs, time elapsed)
|
||||
* @param ?string $fileName Optional file name, if absent will be extracted from the passed $file.
|
||||
* @param "html"|"markdown"|null $parseMode Parse mode
|
||||
* @param integer|null $replyToMsgId ID of message to reply to.
|
||||
|
@ -21,6 +21,7 @@ declare(strict_types=1);
|
||||
namespace danog\MadelineProto\TL\Types;
|
||||
|
||||
use ArrayAccess;
|
||||
use AssertionError;
|
||||
use JsonSerializable;
|
||||
|
||||
/**
|
||||
@ -69,11 +70,7 @@ final class Bytes implements JsonSerializable, ArrayAccess
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->bytes .= $value;
|
||||
} else {
|
||||
$this->bytes[$offset] = $value;
|
||||
}
|
||||
throw new AssertionError("Cannot modify nested bytes!");
|
||||
}
|
||||
/**
|
||||
* Get char at offset.
|
||||
@ -92,7 +89,7 @@ final class Bytes implements JsonSerializable, ArrayAccess
|
||||
*/
|
||||
public function offsetUnset(mixed $offset): void
|
||||
{
|
||||
unset($this->bytes[$offset]);
|
||||
throw new AssertionError("Cannot modify nested bytes!");
|
||||
}
|
||||
/**
|
||||
* Check if char at offset exists.
|
||||
|
@ -28,6 +28,7 @@ use Countable;
|
||||
use Exception;
|
||||
use Fiber;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\Include_;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
@ -629,7 +630,8 @@ abstract class Tools extends AsyncTools
|
||||
{
|
||||
$code = (new ParserFactory)->create(ParserFactory::ONLY_PHP7)->parse($code);
|
||||
Assert::notNull($code);
|
||||
$traverser = new NodeTraverser([new NameResolver()]);
|
||||
$traverser = new NodeTraverser;
|
||||
$traverser->addVisitor(new NameResolver());
|
||||
$code = $traverser->traverse($code);
|
||||
$finder = new NodeFinder;
|
||||
|
||||
@ -640,7 +642,7 @@ abstract class Tools extends AsyncTools
|
||||
}
|
||||
$class = $class[0]->name->toString();
|
||||
|
||||
/** @var DeclareDeclare|null $call */
|
||||
/** @var DeclareDeclare|null $declare */
|
||||
$declare = $finder->findFirstInstanceOf($code, DeclareDeclare::class);
|
||||
if ($declare === null
|
||||
|| $declare->key->name !== 'strict_types'
|
||||
|
@ -141,7 +141,7 @@ trait Events
|
||||
/**
|
||||
* Get event handler (or plugin instance).
|
||||
*
|
||||
* @param ?class-string<PluginEventHandler>
|
||||
* @param ?class-string<PluginEventHandler> $class
|
||||
*/
|
||||
public function getEventHandler(?string $class = null): EventHandler|EventHandlerProxy|__PHP_Incomplete_Class|null
|
||||
{
|
||||
|
@ -166,7 +166,7 @@ function printTypes(array $types, string $type): string
|
||||
|
||||
foreach ($orderedfiles as $key => $filename) {
|
||||
$lines = file_get_contents($filename);
|
||||
$lines = preg_replace_callback('/\<\!-- cut_here (\S+) -->.*\<\!-- cut_here_end \1 --\>/sim', function ($matches) {
|
||||
$lines = preg_replace_callback('/\<\!--\s+cut_here\s+(\S+)\s+-->.*\<\!--\s+cut_here_end\s+\1\s+--\>/sim', function ($matches) {
|
||||
[, $match] = $matches;
|
||||
if ($match === "concretefilters") {
|
||||
$result = [Update::class, AbstractMessage::class, Message::class, ServiceMessage::class];
|
||||
|
Loading…
Reference in New Issue
Block a user