async def ad_view(self, ctx, *args): if not args: user = ctx.message.author.id else: user, *remains = args user = users.parse_mention(user) user, uuid = users.get_uuid(self.DB, user) if uuid is None: await ctx.bot.reply(t("admin.no_uuid_found")) return point = users.get_point(self.DB, uuid) _fake_ctx = Context(prefix="\0", message=Message(reactions=[], author={"id": user})) valid = checks.is_valid(self.DB, False)(_fake_ctx) await ctx.bot.reply(t("admin.view_point") \ .format( _target=user, _dsid=user, _uuid=uuid, _active=valid, _point=point ) )
async def on_reaction_add(reaction, user): message = reaction.message mentions = message.mentions receiver = None if type(reaction.emoji) is str: # nobody cares about your basic emoji, discord. return if reaction_tipped_already(message, user): print("no duplicate amplifications / user already joined in") return if reaction.emoji.name == config['tip_amp_emoji']: # only tip with the right emoji (:tip: custom emoji by default) if not message.content.startswith("{}tip".format(config['prefix'])): # only tip on tip commands return if len(mentions) == 0 or message.author == user: print("no mentions / self double-tip / re-initial tip") # don't double-tip. return if EMOJI_MONEYBAGS not in [r.emoji for r in message.reactions]: # only amplify tip when the bot confirms with moneybags emoji return try: # extract the tip amount # .tip {amount} {tipees} message_amount = message.content.split(' ')[1] amount = float( message_amount ) # multiply by coin units in the actual tip command except: print("invalid tip message format ({})".format(message.content)) return print("user {} joined tip!".format(user)) await client.send_message( user, "You joined in the {} {} tip!".format(message_amount, config['symbol'])) elif reaction.emoji.name == config['tip_any_emoji']: # tipping any message a static amount. amount = config['tip_any_amount'] receiver = message.author else: # terminate, a custom emoji that we don't care about. return fake_ctx = Context(message=reaction.message, prefix=config['prefix']) success = await _tip(fake_ctx, amount, user, receiver) if success: # add user + message combo to tip cache. reaction_tip_register(message, user)
async def on_message(self, message: Message): prefix = self.options.prefix if prefix: content = message.content if isinstance(content, str): if content.startswith(prefix) and len(content) > len(prefix): ctx = Context(message=message, prefix=prefix) name = content[len(prefix):] await self.show_faq(ctx, name)
async def test_card_image_not_found(bot, swcardsearch): user = User(id=2, bot=False) msg = Message(author=user, content="xxx", channel="destiny", server=server) ctx = Context(message=msg, bot=bot, prefix="!", view=view.StringView(msg.content)) await swcardsearch.card_image.invoke(ctx) bot.say.assert_called_once_with("Card not found :(")
async def test_card_image_returns_correct_image(bot, swcardsearch): user = User(id=2, bot=False) msg = Message(author=user, content="captain phasma", channel="destiny", server=server) ctx = Context(message=msg, bot=bot, prefix="!", view=view.StringView(msg.content)) await swcardsearch.card_image.invoke(ctx) embed = ImageMatcher(card) bot.say.assert_called_once_with(embed=embed)
async def get_context(client: Client, msg: Message) -> Context: view = StringView(msg.content) ctx = Context(prefix=None, view=view, bot=client, message=msg) if client._skip_check(msg.author.id, client.user.id): return ctx prefix = await client._get_prefix(msg) invoked_prefix = prefix if isinstance(prefix, str): if not view.skip_string(prefix): return ctx else: invoked_prefix = discord.utils.find(view.skip_string, prefix) if invoked_prefix is None: return ctx invoker = view.get_word() ctx.invoked_with = invoker ctx.prefix = invoked_prefix ctx.command = client.all_commands.get(invoker) return ctx
async def interpret(self, guild_id=None, content=None, message_id=None, added_reactions=(), removed_reactions=(), allowed_commands=(), silent=False, **k): sends = [] reactions = [] edit = False self.fake_messages.setdefault(guild_id, {}) resp_id = secrets.randbits(24) | 1 if content: # search for builtin commands command = None args = content.split() possible_commands = [ cmd for cmd in self.bot.commands if cmd.name in allowed_commands ] for cmd in possible_commands: if args[0][1:] in cmd.aliases + [cmd.name]: command = cmd break mock_message = MockMessage(self.bot, message_id, sends, reactions, guild_id, content=content, resp_id=resp_id) self.fake_messages[guild_id][message_id] = mock_message self.bot.user_commands.setdefault(int(guild_id), []) if command: # found builtin command, creating fake context ctx = Context( **{ 'message': mock_message, 'bot': self.bot, 'args': args[1:], 'prefix': content[0], 'command': command, 'invoked_with': args[0] }) ctx.send = lambda content: sends.append(content) await ctx.invoke(command, *args[1:]) elif args[0][1:] == 'help': help_text = '' for cmd in possible_commands: try: if args[1] in cmd.aliases or args[1] == cmd.name: help_text += f'```{args[1]} - {cmd.help}```' break except IndexError: help_text += '```{}: {:>5}```\n'.format( cmd.name, cmd.help) sends.append(help_text) else: # check for user set commands in this "guild" for command in self.bot.user_commands[mock_message.guild.id]: if (command.triggered(mock_message.content)): await command.execute(mock_message, self.bot.session) break # Prevent response sending for silent requests if silent or not sends: sends = () resp_id = None else: mock_message = MockMessage(self.bot, resp_id, sends, reactions, guild_id, content='\n'.join(sends)) self.fake_messages[guild_id][resp_id] = mock_message elif added_reactions: edit = True resp_id = added_reactions[0][0] for react in added_reactions: fkmsg = self.fake_messages[guild_id][react[0]] fkmsg.sends = sends react = await fkmsg.add_reaction(react[1], bot=False) await self.bot.get_cog("EventCog").on_reaction_add( react, MockMember()) elif removed_reactions: edit = True resp_id = removed_reactions[0][0] for react in removed_reactions: fkmsg = self.fake_messages[guild_id][react[0]] fkmsg.sends = sends react = await fkmsg.remove_reaction(react[1]) await self.bot.get_cog("EventCog").on_reaction_remove( react, MockMember()) resp = { '_module': 'interpret', 'content': '\n'.join(sends), 'added_reactions': [(r[0], r[1]) for r in reactions], 'message_id': resp_id, 'edit': edit, 'guild_id': guild_id, } if resp['content']: print(resp) return resp
'edited_timestamp': '2019-10-14T15:33:48+00:00', 'type': 'message', 'pinned': False, 'mention_everyone': False, 'tts': None, 'content': 'content', 'nonce': None, } state = unittest.mock.MagicMock() channel = unittest.mock.MagicMock() message_instance = discord.Message(state=state, channel=channel, data=message_data) # Create a Context instance to get a realistic MagicMock of `discord.ext.commands.Context` context_instance = Context(message=unittest.mock.MagicMock(), prefix=unittest.mock.MagicMock()) class MockContext(CustomMockMixin, unittest.mock.MagicMock): """ A MagicMock subclass to mock Context objects. Instances of this class will follow the specifications of `discord.ext.commands.Context` instances. For more information, see the `MockGuild` docstring. """ spec_set = context_instance def __init__(self, **kwargs) -> None: super().__init__(**kwargs) self.bot = kwargs.get('bot', MockBot()) self.guild = kwargs.get('guild', MockGuild())
} guild_instance = discord.Guild(data=guild_data, state=MagicMock()) member_data = {"user": "******", "roles": [1]} state_mock = MagicMock() member_instance = discord.Member(data=member_data, guild=guild_instance, state=state_mock) role_data = {"name": "role", "id": 1} role_instance = discord.Role(guild=guild_instance, state=MagicMock(), data=role_data) context_instance = Context(message=MagicMock(), prefix=MagicMock()) message_data = { "id": 1, "webhook_id": 431341013479718912, "attachments": [], "embeds": [], "application": "Python Discord", "activity": "mocking", "channel": MagicMock(), "edited_timestamp": "2019-10-14T15:33:48+00:00", "type": "message", "pinned": False, "mention_everyone": False, "tts": None, "content": "content",
'type': 'message', 'pinned': False, 'mention_everyone': False, 'tts': None, 'content': 'content', 'nonce': None, } state = unittest.mock.MagicMock() channel = unittest.mock.MagicMock() message_instance = discord.Message(state=state, channel=channel, data=message_data) # Create a Context instance to get a realistic MagicMock of `discord.ext.commands.Context` context_instance = Context(message=unittest.mock.MagicMock(), prefix="$", bot=MockBot(), view=None) context_instance.invoked_from_error_handler = None class MockContext(CustomMockMixin, unittest.mock.MagicMock): """ A MagicMock subclass to mock Context objects. Instances of this class will follow the specifications of `discord.ext.commands.Context` instances. For more information, see the `MockGuild` docstring. """ spec_set = context_instance def __init__(self, **kwargs) -> None: super().__init__(**kwargs)
async def handle_mock_user_action(self, action: int = None, messageId: int = None, guildId: int = None, content: str = None, allowedCommands: List[str] = (), emoji: str = None, silent: bool = False): message_id = messageId guild_id = guildId allowed_commands = allowedCommands # this is very scuffed. guilds under this number won't have their responses added to the db assert guild_id < FAKE_GUILD_IDS if action is None or message_id is None or guild_id is None: return {'message': "missing arguments"}, sc.BAD_REQUEST_400 sends = [] reactions = [] self.fake_messages.setdefault(guild_id, {}) resp_id = secrets.randbits(24) | 1 if action == LogActions.MESSAGE_SEND: args = content.split() # intersection of commands that exist and commands they're allowed to see all_allowed = ['poll', 'xpoll', 'schedule', 'set', 'remove'] possible_commands = [ cmd for cmd in self.bot.commands if cmd.name in allowed_commands and cmd.name in all_allowed ] # check if they triggered help command if args[0][1:] == 'help': help_text = '' for cmd in possible_commands: try: if args[1] in cmd.aliases or args[1] == cmd.name: help_text += f'```{args[1]} - {cmd.help}```' break except IndexError: help_text += f'```{cmd.name}: {cmd.help:>5}```\n' sends.append(help_text) else: # check if they triggered a builtin command triggered_command = None for cmd in possible_commands: if args[0][1:] in cmd.aliases + [cmd.name]: triggered_command = cmd break mock_message = MockMessage(self.bot, message_id, sends, reactions, guild_id, content=content, resp_id=resp_id) self.fake_messages[guild_id][message_id] = mock_message responses = self.bot.get_cog("Auto Responses").responses responses.setdefault( guild_id, GuildAutoResponses(self.bot, MockGuild(guild_id), no_db=int(guild_id) < FAKE_GUILD_IDS)) if triggered_command: # found builtin command, creating fake context ctx = Context( **{ 'message': mock_message, 'bot': self.bot, 'args': args[1:], 'prefix': content[0], 'command': triggered_command, 'invoked_with': args[0] }) # override send, so ctx sends go to our list async def ctx_send(content): sends.append(content) ctx.send = ctx_send await ctx.invoke(triggered_command, *args[1:]) else: # no builtin, check for user set commands in this "guild" for resp in responses[guild_id].auto_responses: resp_msg, r = await responses[guild_id].execute( mock_message) if r is not None: break # Prevent response sending for silent requests if silent or not sends: sends = () resp_id = None else: mock_message = MockMessage(self.bot, resp_id, sends, reactions, guild_id, content='\n'.join(sends)) self.fake_messages[guild_id][resp_id] = mock_message resp = { 'guildId': guild_id, 'actions': [{ 'action': LogActions.MESSAGE_SEND, 'content': '\n'.join(sends), 'messageId': resp_id, }] } resp['actions'] += [{ 'action': LogActions.REACTION_ADD, 'emoji': r[1], 'messageId': resp_id, } for r in reactions] elif action == LogActions.MESSAGE_DELETE: pass elif action == LogActions.REACTION_ADD: resp_id = message_id fkmsg = self.fake_messages[guild_id][resp_id] fkmsg.sends = sends react = await fkmsg.add_reaction(emoji, bot=False) await self.bot.cogs["Events"].on_reaction_add(react, MockMember()) resp = { 'guildId': guild_id, 'actions': ({ 'action': LogActions.MESSAGE_EDIT, 'content': '\n'.join(sends), 'messageId': resp_id, }, ) } elif action == LogActions.REACTION_REMOVE: resp_id = message_id fkmsg = self.fake_messages[guild_id][resp_id] fkmsg.sends = [fkmsg.content] react = await fkmsg.remove_reaction(emoji) await self.bot.cogs["Events"].on_reaction_remove( react, MockMember()) resp = { 'guildId': guild_id, 'actions': ({ 'action': LogActions.MESSAGE_EDIT, 'content': '\n'.join(sends), 'messageId': resp_id, }, ) } return resp, sc.OK_200
async def on_message(self, message: Message): if message.content.lower().strip() == self.client.config.universal_prefix: await self.help_menu(Context(message=message, guild=message.guild, prefix=self.client.prefix(message)))
async def storm(ctx): msg = await ctx.send('playing...', delete_after=3) await play(Context(message=msg, prefix='--'), "Леван Горозия Шторм", channel=bot.get_channel(699697856851738688))