mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-26 21:14:43 +01:00
Fixes
This commit is contained in:
parent
d3fa21feb6
commit
105ed6b9e5
@ -861,7 +861,7 @@ final class MTProto implements TLCallback, LoggerGetter
|
||||
|
||||
if (!isset($this->TL)) {
|
||||
$this->TL = new TL($this);
|
||||
$callbacks = [$this, $this->referenceDatabase];
|
||||
$callbacks = [$this, $this->referenceDatabase, $this->peerDatabase];
|
||||
if (!($this->authorization['user']['bot'] ?? false)) {
|
||||
$callbacks[] = $this->minDatabase;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use Amp\Sync\LocalKeyedMutex;
|
||||
use Amp\Sync\LocalMutex;
|
||||
use danog\MadelineProto\Db\DbArray;
|
||||
use danog\MadelineProto\Db\DbPropertiesTrait;
|
||||
use danog\MadelineProto\Exception;
|
||||
@ -69,10 +71,12 @@ final class MinDatabase implements TLCallback
|
||||
'db' => ['innerMadelineProto' => true],
|
||||
];
|
||||
|
||||
private LocalKeyedMutex $localMutex;
|
||||
public function __construct(MTProto $API)
|
||||
{
|
||||
$this->API = $API;
|
||||
$this->v = self::V;
|
||||
$this->localMutex = new LocalKeyedMutex;
|
||||
}
|
||||
public function __destruct()
|
||||
{
|
||||
@ -81,6 +85,10 @@ final class MinDatabase implements TLCallback
|
||||
{
|
||||
return ['db', 'pendingDb', 'API', 'v'];
|
||||
}
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->localMutex = new LocalKeyedMutex;
|
||||
}
|
||||
public function init(): void
|
||||
{
|
||||
$this->initDb($this->API);
|
||||
@ -200,10 +208,17 @@ final class MinDatabase implements TLCallback
|
||||
if (!isset($this->pendingDb[$id])) {
|
||||
return;
|
||||
}
|
||||
$pending = $this->pendingDb[$id];
|
||||
unset($this->pendingDb[$id]);
|
||||
if ($this->API->peerDatabase->get($id)['min'] ?? true) {
|
||||
$this->db[$id] = $pending;
|
||||
$lock = $this->localMutex->acquire((string) $id);
|
||||
try {
|
||||
if (!isset($this->pendingDb[$id])) {
|
||||
return;
|
||||
}
|
||||
if ($this->API->peerDatabase->get($id)['min'] ?? true) {
|
||||
$this->db[$id] = $this->pendingDb[$id];
|
||||
}
|
||||
} finally {
|
||||
unset($this->pendingDb[$id]);
|
||||
$lock->release();
|
||||
}
|
||||
}
|
||||
public function populateFrom(array $object)
|
||||
|
@ -20,6 +20,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace danog\MadelineProto\MTProtoTools;
|
||||
|
||||
use Amp\Sync\LocalKeyedMutex;
|
||||
use Amp\Sync\LocalMutex;
|
||||
use AssertionError;
|
||||
use danog\MadelineProto\Db\DbArray;
|
||||
@ -92,9 +93,11 @@ final class PeerDatabase implements TLCallback
|
||||
];
|
||||
|
||||
private LocalMutex $decacheMutex;
|
||||
private LocalKeyedMutex $mutex;
|
||||
public function __construct(private MTProto $API)
|
||||
{
|
||||
$this->decacheMutex = new LocalMutex;
|
||||
$this->mutex = new LocalKeyedMutex;
|
||||
}
|
||||
public function __sleep()
|
||||
{
|
||||
@ -103,6 +106,7 @@ final class PeerDatabase implements TLCallback
|
||||
public function __wakeup(): void
|
||||
{
|
||||
$this->decacheMutex = new LocalMutex;
|
||||
$this->mutex = new LocalKeyedMutex;
|
||||
}
|
||||
public function init(): void
|
||||
{
|
||||
@ -182,7 +186,12 @@ final class PeerDatabase implements TLCallback
|
||||
}
|
||||
public function clear(int $id): void
|
||||
{
|
||||
unset($this->pendingDb[$id], $this->db[$id]);
|
||||
if ($id < 0) {
|
||||
$this->processChat($id);
|
||||
} else {
|
||||
$this->processUser($id);
|
||||
}
|
||||
unset($this->db[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,56 +378,63 @@ final class PeerDatabase implements TLCallback
|
||||
return;
|
||||
}
|
||||
$user = $this->pendingDb[$id];
|
||||
unset($this->pendingDb[$id]);
|
||||
|
||||
$existingChat = $this->db[$user['id']];
|
||||
if (!isset($user['access_hash']) && !($user['min'] ?? false)) {
|
||||
if (isset($existingChat['access_hash'])) {
|
||||
$this->API->logger->logger("No access hash with user {$user['id']}, using backup");
|
||||
$user['access_hash'] = $existingChat['access_hash'];
|
||||
$user['min'] = false;
|
||||
} else {
|
||||
Assert::null($existingChat);
|
||||
try {
|
||||
$this->API->methodCallAsyncRead('users.getUsers', ['id' => [[
|
||||
'_' => 'inputUser',
|
||||
'user_id' => $user['id'],
|
||||
'access_hash' => 0,
|
||||
]]]);
|
||||
return;
|
||||
} catch (RPCErrorException $e) {
|
||||
$this->API->logger->logger("An error occurred while trying to fetch the missing access_hash for user {$user['id']}: {$e->getMessage()}", Logger::FATAL_ERROR);
|
||||
}
|
||||
foreach (self::getUsernames($user) as $username) {
|
||||
if (($this->resolveUsername($username)) === $user['id']) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$lock = $this->mutex->acquire((string) $id);
|
||||
try {
|
||||
if (!isset($this->pendingDb[$id])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($existingChat !== $user) {
|
||||
$this->API->logger->logger("Updated user {$user['id']}", Logger::ULTRA_VERBOSE);
|
||||
if (($user['min'] ?? false) && !($existingChat['min'] ?? false)) {
|
||||
$this->API->logger->logger("{$user['id']} is min, filling missing fields", Logger::ULTRA_VERBOSE);
|
||||
$existingChat = $this->db[$user['id']];
|
||||
if (!isset($user['access_hash']) && !($user['min'] ?? false)) {
|
||||
if (isset($existingChat['access_hash'])) {
|
||||
$user['min'] = false;
|
||||
$this->API->logger->logger("No access hash with user {$user['id']}, using backup");
|
||||
$user['access_hash'] = $existingChat['access_hash'];
|
||||
$user['min'] = false;
|
||||
} else {
|
||||
Assert::null($existingChat);
|
||||
try {
|
||||
$this->API->methodCallAsyncRead('users.getUsers', ['id' => [[
|
||||
'_' => 'inputUser',
|
||||
'user_id' => $user['id'],
|
||||
'access_hash' => 0,
|
||||
]]]);
|
||||
return;
|
||||
} catch (RPCErrorException $e) {
|
||||
$this->API->logger->logger("An error occurred while trying to fetch the missing access_hash for user {$user['id']}: {$e->getMessage()}", Logger::FATAL_ERROR);
|
||||
}
|
||||
foreach (self::getUsernames($user) as $username) {
|
||||
if (($this->resolveUsername($username)) === $user['id']) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->recacheChatUsername($user['id'], $existingChat, $user);
|
||||
if (!$this->API->settings->getDb()->getEnablePeerInfoDb()) {
|
||||
$user = [
|
||||
'_' => $user['_'],
|
||||
'id' => $user['id'],
|
||||
'access_hash' => $user['access_hash'] ?? null,
|
||||
'min' => $user['min'] ?? false,
|
||||
];
|
||||
}
|
||||
$this->db[$user['id']] = $user;
|
||||
if ($existingChat && ($existingChat['min'] ?? false) && !($user['min'] ?? false)) {
|
||||
$this->API->minDatabase->clearPeer($user['id']);
|
||||
if ($existingChat !== $user) {
|
||||
$this->API->logger->logger("Updated user {$user['id']}", Logger::ULTRA_VERBOSE);
|
||||
if (($user['min'] ?? false) && !($existingChat['min'] ?? false)) {
|
||||
$this->API->logger->logger("{$user['id']} is min, filling missing fields", Logger::ULTRA_VERBOSE);
|
||||
if (isset($existingChat['access_hash'])) {
|
||||
$user['min'] = false;
|
||||
$user['access_hash'] = $existingChat['access_hash'];
|
||||
}
|
||||
}
|
||||
$this->recacheChatUsername($user['id'], $existingChat, $user);
|
||||
if (!$this->API->settings->getDb()->getEnablePeerInfoDb()) {
|
||||
$user = [
|
||||
'_' => $user['_'],
|
||||
'id' => $user['id'],
|
||||
'access_hash' => $user['access_hash'] ?? null,
|
||||
'min' => $user['min'] ?? false,
|
||||
];
|
||||
}
|
||||
$this->db[$user['id']] = $user;
|
||||
if ($existingChat && ($existingChat['min'] ?? false) && !($user['min'] ?? false)) {
|
||||
$this->API->minDatabase->clearPeer($user['id']);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
unset($this->pendingDb[$id]);
|
||||
$lock->release();
|
||||
}
|
||||
}
|
||||
public function addChatBlocking(int $chat): void
|
||||
@ -462,15 +478,73 @@ final class PeerDatabase implements TLCallback
|
||||
if (!isset($this->pendingDb[$id])) {
|
||||
return;
|
||||
}
|
||||
$chat = $this->pendingDb[$id];
|
||||
unset($this->pendingDb[$id]);
|
||||
if ($chat['_'] === 'chat'
|
||||
|| $chat['_'] === 'chatEmpty'
|
||||
|| $chat['_'] === 'chatForbidden'
|
||||
) {
|
||||
$existingChat = $this->db[-$chat['id']];
|
||||
if (!$existingChat || $existingChat !== $chat) {
|
||||
$this->API->logger->logger("Updated chat -{$chat['id']}", Logger::ULTRA_VERBOSE);
|
||||
$lock = $this->mutex->acquire((string) $id);
|
||||
try {
|
||||
$chat = $this->pendingDb[$id];
|
||||
if ($chat['_'] === 'chat'
|
||||
|| $chat['_'] === 'chatEmpty'
|
||||
|| $chat['_'] === 'chatForbidden'
|
||||
) {
|
||||
$existingChat = $this->db[-$chat['id']];
|
||||
if (!$existingChat || $existingChat !== $chat) {
|
||||
$this->API->logger->logger("Updated chat -{$chat['id']}", Logger::ULTRA_VERBOSE);
|
||||
if (!$this->API->settings->getDb()->getEnablePeerInfoDb()) {
|
||||
$chat = [
|
||||
'_' => $chat['_'],
|
||||
'id' => $chat['id'],
|
||||
'access_hash' => $chat['access_hash'] ?? null,
|
||||
'min' => $chat['min'] ?? false,
|
||||
];
|
||||
}
|
||||
$this->db[-$chat['id']] = $chat;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ($chat['_'] === 'channelEmpty') {
|
||||
return;
|
||||
}
|
||||
if ($chat['_'] !== 'channel' && $chat['_'] !== 'channelForbidden') {
|
||||
throw new InvalidArgumentException('Invalid chat type '.$chat['_']);
|
||||
}
|
||||
$bot_api_id = MTProto::toSupergroup($chat['id']);
|
||||
$existingChat = $this->db[$bot_api_id];
|
||||
if (!isset($chat['access_hash']) && !($chat['min'] ?? false)) {
|
||||
if (isset($existingChat['access_hash'])) {
|
||||
$this->API->logger->logger("No access hash with channel {$bot_api_id}, using backup");
|
||||
$chat['access_hash'] = $existingChat['access_hash'];
|
||||
} else {
|
||||
Assert::null($existingChat);
|
||||
try {
|
||||
$this->API->methodCallAsyncRead('channels.getChannels', ['id' => [[
|
||||
'_' => 'inputChannel',
|
||||
'channel_id' => $chat['id'],
|
||||
'access_hash' => 0,
|
||||
]]]);
|
||||
return;
|
||||
} catch (RPCErrorException $e) {
|
||||
$this->API->logger->logger("An error occurred while trying to fetch the missing access_hash for channel {$bot_api_id}: {$e->getMessage()}", Logger::FATAL_ERROR);
|
||||
}
|
||||
foreach (self::getUsernames($chat) as $username) {
|
||||
if (($this->resolveUsername($username)) === $bot_api_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($existingChat !== $chat) {
|
||||
$this->recacheChatUsername($bot_api_id, $existingChat, $chat);
|
||||
$this->API->logger->logger("Updated chat {$bot_api_id}", Logger::ULTRA_VERBOSE);
|
||||
if (($chat['min'] ?? false) && $existingChat && !($existingChat['min'] ?? false)) {
|
||||
$this->API->logger->logger("{$bot_api_id} is min, filling missing fields", Logger::ULTRA_VERBOSE);
|
||||
$newchat = $existingChat;
|
||||
foreach (['title', 'username', 'usernames', 'photo', 'banned_rights', 'megagroup', 'verified'] as $field) {
|
||||
if (isset($chat[$field])) {
|
||||
$newchat[$field] = $chat[$field];
|
||||
}
|
||||
}
|
||||
$chat = $newchat;
|
||||
}
|
||||
if (!$this->API->settings->getDb()->getEnablePeerInfoDb()) {
|
||||
$chat = [
|
||||
'_' => $chat['_'],
|
||||
@ -479,67 +553,14 @@ final class PeerDatabase implements TLCallback
|
||||
'min' => $chat['min'] ?? false,
|
||||
];
|
||||
}
|
||||
$this->db[-$chat['id']] = $chat;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ($chat['_'] === 'channelEmpty') {
|
||||
return;
|
||||
}
|
||||
if ($chat['_'] !== 'channel' && $chat['_'] !== 'channelForbidden') {
|
||||
throw new InvalidArgumentException('Invalid chat type '.$chat['_']);
|
||||
}
|
||||
$bot_api_id = MTProto::toSupergroup($chat['id']);
|
||||
$existingChat = $this->db[$bot_api_id];
|
||||
if (!isset($chat['access_hash']) && !($chat['min'] ?? false)) {
|
||||
if (isset($existingChat['access_hash'])) {
|
||||
$this->API->logger->logger("No access hash with channel {$bot_api_id}, using backup");
|
||||
$chat['access_hash'] = $existingChat['access_hash'];
|
||||
} else {
|
||||
Assert::null($existingChat);
|
||||
try {
|
||||
$this->API->methodCallAsyncRead('channels.getChannels', ['id' => [[
|
||||
'_' => 'inputChannel',
|
||||
'channel_id' => $chat['id'],
|
||||
'access_hash' => 0,
|
||||
]]]);
|
||||
return;
|
||||
} catch (RPCErrorException $e) {
|
||||
$this->API->logger->logger("An error occurred while trying to fetch the missing access_hash for channel {$bot_api_id}: {$e->getMessage()}", Logger::FATAL_ERROR);
|
||||
$this->db[$bot_api_id] = $chat;
|
||||
if ($existingChat && ($existingChat['min'] ?? false) && !($chat['min'] ?? false)) {
|
||||
$this->API->minDatabase->clearPeer($bot_api_id);
|
||||
}
|
||||
foreach (self::getUsernames($chat) as $username) {
|
||||
if (($this->resolveUsername($username)) === $bot_api_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($existingChat !== $chat) {
|
||||
$this->recacheChatUsername($bot_api_id, $existingChat, $chat);
|
||||
$this->API->logger->logger("Updated chat {$bot_api_id}", Logger::ULTRA_VERBOSE);
|
||||
if (($chat['min'] ?? false) && $existingChat && !($existingChat['min'] ?? false)) {
|
||||
$this->API->logger->logger("{$bot_api_id} is min, filling missing fields", Logger::ULTRA_VERBOSE);
|
||||
$newchat = $existingChat;
|
||||
foreach (['title', 'username', 'usernames', 'photo', 'banned_rights', 'megagroup', 'verified'] as $field) {
|
||||
if (isset($chat[$field])) {
|
||||
$newchat[$field] = $chat[$field];
|
||||
}
|
||||
}
|
||||
$chat = $newchat;
|
||||
}
|
||||
if (!$this->API->settings->getDb()->getEnablePeerInfoDb()) {
|
||||
$chat = [
|
||||
'_' => $chat['_'],
|
||||
'id' => $chat['id'],
|
||||
'access_hash' => $chat['access_hash'] ?? null,
|
||||
'min' => $chat['min'] ?? false,
|
||||
];
|
||||
}
|
||||
$this->db[$bot_api_id] = $chat;
|
||||
if ($existingChat && ($existingChat['min'] ?? false) && !($chat['min'] ?? false)) {
|
||||
$this->API->minDatabase->clearPeer($bot_api_id);
|
||||
}
|
||||
} finally {
|
||||
unset($this->pendingDb[$id]);
|
||||
$lock->release();
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -252,8 +252,6 @@ if (!getenv('GITHUB_SHA') && stripos(($MadelineProto->readline('Do you want to m
|
||||
if (!getenv('TEST_USERNAME')) {
|
||||
throw new Exception('No TEST_USERNAME environment variable was provided!');
|
||||
}
|
||||
/*$MadelineProto->refreshPeerCache(\getenv('TEST_USERNAME'));
|
||||
$MadelineProto->refreshFullPeerCache(\getenv('TEST_USERNAME'));*/
|
||||
$mention = $MadelineProto->getInfo(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id
|
||||
$mention = $mention['user_id']; // Selects only the numeric user id
|
||||
$media = [];
|
||||
|
Loading…
Reference in New Issue
Block a user