Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TelegramTypes ChatMember updates #154

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/Telegram/Methods/GetChatMember.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

declare(strict_types = 1);
declare(strict_types=1);

namespace unreal4u\TelegramAPI\Telegram\Methods;

Expand All @@ -11,9 +11,8 @@
use unreal4u\TelegramAPI\Telegram\Types\ChatMember;

/**
* Use this method to get information about a member of a chat. Returns a ChatMember object on success
*
* Objects defined as-is july 2016
* Use this method to get information about a member of a chat. The method is only guaranteed to work for other users
* if the bot is an administrator in the chat. Returns a ChatMember object on success.
*
* @see https://core.telegram.org/bots/api#getchatmember
*/
Expand All @@ -22,7 +21,7 @@ class GetChatMember extends TelegramMethods
/**
* Unique identifier for the target chat or username of the target supergroup or channel (in the format
* @channelusername)
* @var string
* @var int|string
*/
public $chat_id = '';

Expand All @@ -34,7 +33,7 @@ class GetChatMember extends TelegramMethods

public static function bindToObject(TelegramResponse $data, LoggerInterface $logger): TelegramTypes
{
return new ChatMember($data->getResult(), $logger);
return ChatMember::create($data->getResult(), $logger);
}

public function getMandatoryFields(): array
Expand Down
5 changes: 5 additions & 0 deletions src/Telegram/Types/Chat.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
*/
class Chat extends TelegramTypes
{
public const TYPE_PRIVATE = 'private';
public const TYPE_GROUP = 'group';
public const TYPE_SUPERGROUP = 'supergroup';
public const TYPE_CHANNEL = 'channel';

/**
* Unique identifier for this chat. This number may be greater than 32 bits and some programming languages may have
* difficulty/silent defects in interpreting it. But it smaller than 52 bits, so a signed 64 bit integer or
Expand Down
159 changes: 44 additions & 115 deletions src/Telegram/Types/ChatMember.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
<?php

declare(strict_types = 1);
declare(strict_types=1);

namespace unreal4u\TelegramAPI\Telegram\Types;

use Psr\Log\LoggerInterface;
use unreal4u\TelegramAPI\Abstracts\TelegramTypes;
use unreal4u\TelegramAPI\Telegram\Types\ChatMember\ChatMemberAdministrator;
use unreal4u\TelegramAPI\Telegram\Types\ChatMember\ChatMemberBanned;
use unreal4u\TelegramAPI\Telegram\Types\ChatMember\ChatMemberLeft;
use unreal4u\TelegramAPI\Telegram\Types\ChatMember\ChatMemberMember;
use unreal4u\TelegramAPI\Telegram\Types\ChatMember\ChatMemberOwner;
use unreal4u\TelegramAPI\Telegram\Types\ChatMember\ChatMemberRestricted;

/**
* This object contains information about one member of the chat
Expand All @@ -15,131 +22,27 @@
*/
class ChatMember extends TelegramTypes
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be defined as an abstract method since a ChatMember will always be of a certain type.

{
private const CHILD_CLASS_REFERENCES = [
ChatMemberOwner::class,
ChatMemberAdministrator::class,
ChatMemberMember::class,
ChatMemberRestricted::class,
ChatMemberLeft::class,
ChatMemberBanned::class,
];
Comment on lines +25 to +32
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like for the actual Telegram classes to remain as clean as possible from 'external' code for two reasons:

  • If Telegram decides to create a field called created it won't clash with the defined function.
  • It will prevent our users from actually depending on this code, people do crazy stuff and any changes to this will be BC.

I'm thinking that a better option would be to perhaps create a TelegramAPI\Telegram\Custom\ChatMemberFactory factory and make the bindToObject in GetChatMember (and others that return a ChatMemer type) call that dedicated factory instead.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One eternity later

Ok, I would need to take a closer look, but I believe the function mapSubObjects was created for this purpose.


/**
* Information about the user
* @var User
*/
public $user;

/**
* The member's status in the chat. Can be "creator", "administrator", "member", "restricted", "left" or "kicked"
* The member's status in the chat. See childs of this class or API documentation for possible values.
* @var string
*/
public $status = '';

/**
* Optional. Owner and administrators only. Custom title for this user
* @var string
*/
public $custom_title = '';

/**
* Optional. Owner and administrators only. True, if the user's presence in the chat is hidden
* @var bool
*/
public $is_anonymous = false;

/**
* Optional. Restricted and kicked only. Date when restrictions will be lifted for this user, unix time
* @var int
*/
public $until_date = 0;

/**
* Optional. Administrators only. True, if the bot is allowed to edit administrator privileges of that user
* @var bool
*/
public $can_be_edited = false;

/**
* Optional. Administrators only. True, if the administrator can post in the channel, channels only
* @var bool
*/
public $can_post_messages = false;

/**
* Optional. Administrators only. True, if the administrator can edit messages of other users, channels only
* @var bool
*/
public $can_edit_messages = false;

/**
* Optional. Administrators only. True, if the administrator can delete messages of other users
* @var bool
*/
public $can_delete_messages = false;

/**
* Optional. Administrators only. True, if the administrator can restrict, ban or unban chat members
* @var bool
*/
public $can_restrict_members = false;

/**
* Optional. Administrators only. True, if the administrator can add new administrators with a subset of his own
* privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators
* that were appointed by the user)
* @var bool
*/
public $can_promote_members = false;

/**
* Optional. Administrators only. True, if the administrator can change the chat title, photo and other settings
* @var bool
*/
public $can_change_info = false;

/**
* Optional. Administrators only. True, if the administrator can invite new users to the chat
* @var bool
*/
public $can_invite_users = false;

/**
* Optional. Administrators only. True, if the administrator can pin messages, supergroups only
* @var bool
*/
public $can_pin_messages = false;

/**
* Optional. Restricted only. True, if the user is a member of the chat at the moment of the request
* @var bool
*/
public $is_member = false;

/**
* Optional. Restricted only. True, if the user can send text messages, contacts, locations and venues
* @var bool
*/
public $can_send_messages = false;

/**
* Optional. Restricted only. True, if the user can send audios, documents, photos, videos, video notes and voice
* notes, implies can_send_messages
* @var bool
*/
public $can_send_media_messages = false;

/**
* Optional. Restricted only. True, if the user is allowed to send polls
* @var bool
*/
public $can_send_polls = false;

/**
* Optional. Restricted only. True, if the user can send animations, games, stickers and use inline bots, implies
* can_send_media_messages
* @var bool
*/
public $can_send_other_messages = false;

/**
* Optional. Restricted only. True, if user may add web page previews to his messages, implies
* can_send_media_messages
* @var bool
*/
public $can_add_web_page_previews = false;

public function mapSubObjects(string $key, array $data): TelegramTypes
{
switch ($key) {
Expand All @@ -149,4 +52,30 @@ public function mapSubObjects(string $key, array $data): TelegramTypes

return parent::mapSubObjects($key, $data);
}

/**
* Create specific ChatMember class based on 'status'. If there is no match,
*/
public static function create(array $data, LoggerInterface $logger): ChatMember
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go into a factory and not in the Telegram class type.

{
$status = $data['status'] ?? null;

foreach (self::CHILD_CLASS_REFERENCES as $childClassReference) {
if ($status === $childClassReference::STATUS) {
return new $childClassReference($data, $logger);
}
}
Comment on lines +63 to +67
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this is pleasant to look at, I much prefer dropping the constant within each type in order to keep those objects as clean as possible, and make the factory call the child classes directly.

I'm not a big fan of this, but I believe that's the best way, very much as we do here: https://github.com/unreal4u/telegram-api/blob/master/src/Telegram/Types/Message.php#L501-L566 (Yes, I hate that part of the code but it was the only way I could think of at the time).

$logger->error(sprintf(
'Unable to detect correct "%s" class based on status = "%s"! Maybe a recent Telegram Bot ' .
'API update? In any way, please submit an issue (bug report) at %s with this complete log line',
self::class,
$status ?? 'null',
'https://github.com/unreal4u/telegram-api/issues'
), [
'object' => self::class,
'data' => $data,
]);

return new ChatMember($data, $logger);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok to throw an exception here. I would not support creating an object that is invalid to begin with.

}
}
135 changes: 135 additions & 0 deletions src/Telegram/Types/ChatMember/ChatMemberAdministrator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

declare(strict_types=1);

namespace unreal4u\TelegramAPI\Telegram\Types\ChatMember;

use unreal4u\TelegramAPI\Telegram\Types\ChatMember;

/**
* Represents a chat member that has some additional privileges.
*
* @see https://core.telegram.org/bots/api#chatmemberadministrator
*/
class ChatMemberAdministrator extends ChatMember
{
public const STATUS = 'administrator';

/**
* The member's status in the chat, always “administrator”
* @var string
*/
public $status = self::STATUS;

/**
* True, if the bot is allowed to edit administrator privileges of that user
* @var bool
*/
public $can_be_edited = false;

/**
* True, if the user's presence in the chat is hidden
* @var bool
*/
public $is_anonymous = false;

/**
* True, if the administrator can access the chat event log, chat statistics, message statistics in channels, see
* channel members, see anonymous administrators in supergroups and ignore slow mode.
* Implied by any other administrator privilege
* @var bool
*/
public $can_manage_chat = false;

/**
* True, if the administrator can delete messages of other users
* @var bool
*/
public $can_delete_messages = false;

/**
* True, if the administrator can manage video chats
* @var bool
*/
public $can_manage_video_chats = false;

/**
* @deprecated Use can_manage_video_chats instead (April 16, 2022 Bot API 6.0 https://core.telegram.org/bots/api-changelog#april-16-2022)
* @var bool
*/
public $can_manage_voice_chats = false;

/**
* True, if the administrator can restrict, ban or unban chat members
* @var bool
*/
public $can_restrict_members = false;

/**
* True, if the administrator can add new administrators with a subset of their own privileges or demote
* administrators that they have promoted, directly or indirectly (promoted by administrators that were appointed
* by the user)
* @var bool
*/
public $can_promote_members = false;

/**
* True, if the user is allowed to change the chat title, photo and other settings
* @var bool
*/
public $can_change_info = false;

/**
* True, if the user is allowed to invite new users to the chat
* @var bool
*/
public $can_invite_users = false;

/**
* Optional. True, if the administrator can post in the channel; channels only
* @var bool
*/
public $can_post_messages = false;

/**
* Optional. True, if the administrator can edit messages of other users and can pin messages; channels only
* @var bool
*/
public $can_edit_messages = false;

/**
* Optional. True, if the user is allowed to pin messages; groups and supergroups only
* @var bool
*/
public $can_pin_messages = false;

/**
* Optional. True, if the administrator can post stories in the channel; channels only
* @var bool
*/
public $can_post_stories = false;

/**
* Optional. True, if the administrator can edit stories posted by other users; channels only
* @var bool
*/
public $can_edit_stories = false;

/**
* Optional. True, if the administrator can delete stories posted by other users; channels only
* @var bool
*/
public $can_delete_stories = false;

/**
* Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only
* @var bool
*/
public $can_manage_topics = false;

/**
* Optional. Custom title for this user
* @var string
*/
public $custom_title;
}
Loading