diff --git a/compiler/error/source/400_BAD_REQUEST.tsv b/compiler/error/source/400_BAD_REQUEST.tsv index f01439f5..1caec874 100644 --- a/compiler/error/source/400_BAD_REQUEST.tsv +++ b/compiler/error/source/400_BAD_REQUEST.tsv @@ -84,4 +84,5 @@ PHONE_NUMBER_FLOOD This number has tried to login too many times TAKEOUT_INVALID The takeout id is invalid TAKEOUT_REQUIRED The method must be invoked inside a takeout session MESSAGE_POLL_CLOSED You can't interact with a closed poll -MEDIA_INVALID The media is invalid \ No newline at end of file +MEDIA_INVALID The media is invalid +BOT_SCORE_NOT_MODIFIED The bot score was not modified \ No newline at end of file diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 0d49068a..9a1b0509 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -138,6 +138,9 @@ Bots send_inline_bot_result answer_callback_query request_callback_answer + send_game + set_game_score + get_game_high_scores .. autoclass:: pyrogram.Client diff --git a/docs/source/pyrogram/Types.rst b/docs/source/pyrogram/Types.rst index bf1bf937..6e0a14db 100644 --- a/docs/source/pyrogram/Types.rst +++ b/docs/source/pyrogram/Types.rst @@ -57,6 +57,7 @@ Bots InlineKeyboardButton ForceReply CallbackQuery + Game Input Media ----------- @@ -182,6 +183,15 @@ Input Media .. autoclass:: CallbackQuery :members: +.. autoclass:: Game + :members: + +.. autoclass:: GameHighScore + :members: + +.. autoclass:: GameHighScores + :members: + .. Input Media ----------- diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index 06f784f7..41b14b58 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -40,7 +40,7 @@ from .client.types import ( Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus, UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, - Poll, PollOption, ChatPreview, StopPropagation, Game + Poll, PollOption, ChatPreview, StopPropagation, Game, CallbackGame, GameHighScore, GameHighScores ) from .client import ( Client, ChatAction, ParseMode, Emoji, diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 01ffe434..77492c6a 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -172,8 +172,8 @@ class Filters: pinned_message = create("PinnedMessage", lambda _, m: bool(m.pinned_message)) """Filter service messages for pinned messages.""" - game_score = create("GameScore", lambda _, m: bool(m.game_score)) - """Filter service messages for game scores.""" + game_high_score = create("GameHighScore", lambda _, m: bool(m.game_high_score)) + """Filter service messages for game high scores.""" reply_keyboard = create("ReplyKeyboard", lambda _, m: isinstance(m.reply_markup, ReplyKeyboardMarkup)) """Filter messages containing reply keyboard markups""" diff --git a/pyrogram/client/methods/bots/__init__.py b/pyrogram/client/methods/bots/__init__.py index b0430efe..65d132a0 100644 --- a/pyrogram/client/methods/bots/__init__.py +++ b/pyrogram/client/methods/bots/__init__.py @@ -17,15 +17,21 @@ # along with Pyrogram. If not, see . from .answer_callback_query import AnswerCallbackQuery +from .get_game_high_scores import GetGameHighScores from .get_inline_bot_results import GetInlineBotResults from .request_callback_answer import RequestCallbackAnswer +from .send_game import SendGame from .send_inline_bot_result import SendInlineBotResult +from .set_game_score import SetGameScore class Bots( AnswerCallbackQuery, GetInlineBotResults, RequestCallbackAnswer, - SendInlineBotResult + SendInlineBotResult, + SendGame, + SetGameScore, + GetGameHighScores ): pass diff --git a/pyrogram/client/methods/bots/get_game_high_scores.py b/pyrogram/client/methods/bots/get_game_high_scores.py new file mode 100644 index 00000000..ad4f8b4a --- /dev/null +++ b/pyrogram/client/methods/bots/get_game_high_scores.py @@ -0,0 +1,66 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union + +import pyrogram +from pyrogram.api import functions +from pyrogram.client.ext import BaseClient + + +class GetGameHighScores(BaseClient): + def get_game_high_scores(self, + user_id: Union[int, str], + chat_id: Union[int, str], + message_id: int = None): + """Use this method to get data for high score tables. + + Args: + user_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + chat_id (``int`` | ``str``, *optional*): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + Required if inline_message_id is not specified. + + message_id (``int``, *optional*): + Identifier of the sent message. + Required if inline_message_id is not specified. + + Returns: + On success, a :obj:`GameHighScores ` object is returned. + + Raises: + :class:`Error ` in case of a Telegram RPC error. + """ + # TODO: inline_message_id + + return pyrogram.GameHighScores._parse( + self, + self.send( + functions.messages.GetGameHighScores( + peer=self.resolve_peer(chat_id), + id=message_id, + user_id=self.resolve_peer(user_id) + ) + ) + ) diff --git a/pyrogram/client/methods/bots/send_game.py b/pyrogram/client/methods/bots/send_game.py new file mode 100644 index 00000000..401a5aa6 --- /dev/null +++ b/pyrogram/client/methods/bots/send_game.py @@ -0,0 +1,87 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union + +import pyrogram +from pyrogram.api import functions, types +from pyrogram.client.ext import BaseClient + + +class SendGame(BaseClient): + def send_game(self, + chat_id: Union[int, str], + game_short_name: str, + disable_notification: bool = None, + reply_to_message_id: int = None, + reply_markup: Union["pyrogram.InlineKeyboardMarkup", + "pyrogram.ReplyKeyboardMarkup", + "pyrogram.ReplyKeyboardRemove", + "pyrogram.ForceReply"] = None) -> "pyrogram.Message": + """Use this method to send a game. + + Args: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + game_short_name (``str``): + Short name of the game, serves as the unique identifier for the game. Set up your games via Botfather. + + disable_notification (``bool``, *optional*): + Sends the message silently. + Users will receive a notification with no sound. + + reply_to_message_id (``int``, *optional*): + If the message is a reply, ID of the original message. + + reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): + An object for an inline keyboard. If empty, one ‘Play game_title’ button will be shown automatically. + If not empty, the first button must launch the game. + + Returns: + On success, the sent :obj:`Message` is returned. + + Raises: + :class:`Error ` in case of a Telegram RPC error. + """ + r = self.send( + functions.messages.SendMedia( + peer=self.resolve_peer(chat_id), + media=types.InputMediaGame( + id=types.InputGameShortName( + bot_id=types.InputUserSelf(), + short_name=game_short_name + ), + ), + message="", + silent=disable_notification or None, + reply_to_msg_id=reply_to_message_id, + random_id=self.rnd_id(), + reply_markup=reply_markup.write() if reply_markup else None + ) + ) + + for i in r.updates: + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + return pyrogram.Message._parse( + self, i.message, + {i.id: i for i in r.users}, + {i.id: i for i in r.chats} + ) diff --git a/pyrogram/client/methods/bots/set_game_score.py b/pyrogram/client/methods/bots/set_game_score.py new file mode 100644 index 00000000..e9d20844 --- /dev/null +++ b/pyrogram/client/methods/bots/set_game_score.py @@ -0,0 +1,90 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union + +import pyrogram +from pyrogram.api import functions, types +from pyrogram.client.ext import BaseClient + + +class SetGameScore(BaseClient): + def set_game_score(self, + user_id: Union[int, str], + score: int, + force: bool = None, + disable_edit_message: bool = None, + chat_id: Union[int, str] = None, + message_id: int = None): + # inline_message_id: str = None): TODO Add inline_message_id + """Use this method to set the score of the specified user in a game. + + Args: + user_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + score (``int``): + New score, must be non-negative. + + force (``bool``, *optional*): + Pass True, if the high score is allowed to decrease. + This can be useful when fixing mistakes or banning cheaters. + + disable_edit_message (``bool``, *optional*): + Pass True, if the game message should not be automatically edited to include the current scoreboard. + + chat_id (``int`` | ``str``, *optional*): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + Required if inline_message_id is not specified. + + message_id (``int``, *optional*): + Identifier of the sent message. + Required if inline_message_id is not specified. + + Returns: + On success, if the message was sent by the bot, returns the edited :obj:`Message `, + otherwise returns True. + + Raises: + :class:`Error ` in case of a Telegram RPC error. + :class:`BotScoreNotModified` if the new score is not greater than the user's current score in the chat and force is False. + """ + r = self.send( + functions.messages.SetGameScore( + peer=self.resolve_peer(chat_id), + score=score, + id=message_id, + user_id=self.resolve_peer(user_id), + force=force or None, + edit_message=not disable_edit_message or None + ) + ) + + for i in r.updates: + if isinstance(i, (types.UpdateEditMessage, types.UpdateEditChannelMessage)): + return pyrogram.Message._parse( + self, i.message, + {i.id: i for i in r.users}, + {i.id: i for i in r.chats} + ) + + return True diff --git a/pyrogram/client/methods/chats/iter_chat_members.py b/pyrogram/client/methods/chats/iter_chat_members.py index a86e5935..c37e9785 100644 --- a/pyrogram/client/methods/chats/iter_chat_members.py +++ b/pyrogram/client/methods/chats/iter_chat_members.py @@ -61,7 +61,7 @@ class IterChatMembers(BaseClient): query (``str``, *optional*): Query string to filter members based on their display names and usernames. - Defaults to "" (empty string) [2]_. + Defaults to "" (empty string). filter (``str``, *optional*): Filter used to select the kind of members you want to retrieve. Only applicable for supergroups @@ -74,11 +74,6 @@ class IterChatMembers(BaseClient): *"administrators"* - chat administrators only. Defaults to *"all"*. - .. [1] Server limit: on supergroups, you can get up to 10,000 members for a single query and up to 200 members - on channels. - - .. [2] A query string is applicable only for *"all"*, *"kicked"* and *"restricted"* filters only. - Returns: A generator yielding :obj:`ChatMember ` objects. diff --git a/pyrogram/client/types/__init__.py b/pyrogram/client/types/__init__.py index 65a9165a..ca332a22 100644 --- a/pyrogram/client/types/__init__.py +++ b/pyrogram/client/types/__init__.py @@ -18,11 +18,8 @@ from .bots import ( CallbackQuery, ForceReply, InlineKeyboardButton, InlineKeyboardMarkup, - KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove -) -from .bots import ( - ForceReply, InlineKeyboardButton, InlineKeyboardMarkup, - KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove + KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, CallbackGame, + GameHighScore, GameHighScores ) from .input_media import ( InputMediaAudio, InputPhoneContact, InputMediaVideo, InputMediaPhoto, @@ -33,8 +30,8 @@ from .messages_and_media import ( Sticker, Venue, Video, VideoNote, Voice, UserProfilePhotos, Message, Messages, MessageEntity, Poll, PollOption, Game ) +from .update import StopPropagation from .user_and_chats import ( Chat, ChatMember, ChatMembers, ChatPhoto, Dialog, Dialogs, User, UserStatus, ChatPreview ) -from .update import StopPropagation diff --git a/pyrogram/client/types/bots/__init__.py b/pyrogram/client/types/bots/__init__.py index 804701dd..81767945 100644 --- a/pyrogram/client/types/bots/__init__.py +++ b/pyrogram/client/types/bots/__init__.py @@ -16,11 +16,13 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . +from .callback_game import CallbackGame from .callback_query import CallbackQuery from .force_reply import ForceReply +from .game_high_score import GameHighScore +from .game_high_scores import GameHighScores from .inline_keyboard_button import InlineKeyboardButton from .inline_keyboard_markup import InlineKeyboardMarkup from .keyboard_button import KeyboardButton from .reply_keyboard_markup import ReplyKeyboardMarkup from .reply_keyboard_remove import ReplyKeyboardRemove -from .callback_game import CallbackGame \ No newline at end of file diff --git a/pyrogram/client/types/bots/game_high_score.py b/pyrogram/client/types/bots/game_high_score.py new file mode 100644 index 00000000..0541c18c --- /dev/null +++ b/pyrogram/client/types/bots/game_high_score.py @@ -0,0 +1,69 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram + +from pyrogram.api import types +from pyrogram.client.types.pyrogram_type import PyrogramType +from pyrogram.client.types.user_and_chats import User + + +class GameHighScore(PyrogramType): + """This object represents one row of the high scores table for a game. + + Args: + user (:obj:`User`): + User. + + score (``int``): + Score. + + position (``position``, *optional*): + Position in high score table for the game. + """ + + def __init__(self, + *, + client: "pyrogram.client.ext.BaseClient", + user: User, + score: int, + position: int = None): + super().__init__(client) + + self.user = user + self.score = score + self.position = position + + @staticmethod + def _parse(client, game_high_score: types.HighScore, users: dict) -> "GameHighScore": + users = {i.id: i for i in users} + + return GameHighScore( + user=User._parse(client, users[game_high_score.user_id]), + score=game_high_score.score, + position=game_high_score.pos, + client=client + ) + + @staticmethod + def _parse_action(client, service: types.MessageService, users: dict): + return GameHighScore( + user=User._parse(client, users[service.from_id]), + score=service.action.score, + client=client + ) diff --git a/pyrogram/client/types/bots/game_high_scores.py b/pyrogram/client/types/bots/game_high_scores.py new file mode 100644 index 00000000..1717effa --- /dev/null +++ b/pyrogram/client/types/bots/game_high_scores.py @@ -0,0 +1,56 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import List + +import pyrogram +from pyrogram.api import types +from pyrogram.client.types.pyrogram_type import PyrogramType +from .game_high_score import GameHighScore + + +class GameHighScores(PyrogramType): + """This object represents the high scores table for a game. + + Args: + total_count (``int``): + Total number of scores the target game has. + + game_high_scores (List of :obj:`GameHighScore `): + Game scores. + """ + + def __init__(self, + *, + client: "pyrogram.client.ext.BaseClient", + total_count: int, + game_high_scores: List[GameHighScore]): + super().__init__(client) + + self.total_count = total_count + self.game_high_scores = game_high_scores + + @staticmethod + def _parse(client, game_high_scores: types.messages.HighScores) -> "GameHighScores": + return GameHighScores( + total_count=len(game_high_scores.scores), + game_high_scores=[ + GameHighScore._parse(client, score, game_high_scores.users) + for score in game_high_scores.scores], + client=client + ) diff --git a/pyrogram/client/types/messages_and_media/__init__.py b/pyrogram/client/types/messages_and_media/__init__.py index 3c0b3c98..604b68b9 100644 --- a/pyrogram/client/types/messages_and_media/__init__.py +++ b/pyrogram/client/types/messages_and_media/__init__.py @@ -20,6 +20,7 @@ from .animation import Animation from .audio import Audio from .contact import Contact from .document import Document +from .game import Game from .location import Location from .message import Message from .message_entity import MessageEntity @@ -34,4 +35,3 @@ from .venue import Venue from .video import Video from .video_note import VideoNote from .voice import Voice -from .game import Game diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index ec057503..77281425 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -202,7 +202,7 @@ class Message(PyrogramType, Update): Note that the Message object in this field will not contain further reply_to_message fields even if it is itself a reply. - game_score (``int``, *optional*): + game_high_score (:obj:`GameHighScore `, *optional*): The game score for a user. The reply_to_message field will contain the game Message. @@ -283,7 +283,7 @@ class Message(PyrogramType, Update): migrate_to_chat_id: int = None, migrate_from_chat_id: int = None, pinned_message: "Message" = None, - game_score: int = None, + game_high_score: int = None, views: int = None, via_bot: User = None, outgoing: bool = None, @@ -341,7 +341,7 @@ class Message(PyrogramType, Update): self.migrate_to_chat_id = migrate_to_chat_id self.migrate_from_chat_id = migrate_from_chat_id self.pinned_message = pinned_message - self.game_score = game_score + self.game_high_score = game_high_score self.views = views self.via_bot = via_bot self.outgoing = outgoing @@ -419,7 +419,7 @@ class Message(PyrogramType, Update): pass if isinstance(action, types.MessageActionGameScore): - parsed_message.game_score = action.score + parsed_message.game_high_score = pyrogram.GameHighScore._parse_action(client, message, users) if message.reply_to_msg_id and replies: try: