async def on_command_error(ctx: Context, error: Exception): log.debug('Event "on_command_error" registered') if isinstance(error, CommandNotFound): if in_production(): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Command not found', description=f'There is no command named `{ctx.message.content[1:].split(" ")[0]}`.' f' Check available commands with `>help`.' )) else: log.info(f'Undefined action "{ctx.message.content}"') elif isinstance(error, MissingPermissions): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Missing permissions', description=f'You do not have those permissions:```\n{", ".join(error.missing_perms).upper()}\n```' )) elif isinstance(error, BotMissingPermissions): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Missing permissions', description=f'Bot does not have those permissions:```\n{", ".join(error.missing_perms).upper()}\n```' )) elif isinstance(error, UserNotFound): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: User not found', description='Please make sure that you have passed right name or ID.\n' 'If you are looking for a server member, it is better to use @mention.' )) elif isinstance(error, CommandOnCooldown): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Command is on cooldown', description='Please try again in a minute.' )) elif isinstance(error, DisabledCommand): if in_production(): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Command is disabled' )) else: await debug_log(ctx=ctx, e=error, member=ctx.author) raise error
class GameSeeker(Cog): def __init__(self, bot): self.bot = bot @command( name='host', brief='Hosts game', description='Creates your\'s event in provided game.', help= 'Bot sends info to all guilds with set game hosting, allowing other people too get in touch with you and' ' other gamers.', usage='<game name> [additional info]', enabled=not in_production()) async def host(self, ctx: Context, game: str = None, description: str = None): await ctx.send(embed=DevelopmentEmbed( author=ctx.author).add_field(name='GAME', value=game).add_field( name='DESCRIPTION', value=str(description)))
class Utilities(Cog): def __init__(self, bot): self.bot = bot # noinspection SpellCheckingInspection @cooldown(3, 60, BucketType.user) @command( name='spotify', brief='Spotify lurker', description='Searching Spotify for a specified object and sends YouTube version (single track only).', help='Available Spotify types:\n' '\u2003- `track`,\n' '\u2003- `album`,\n' '\u2003- `artist`,\n' '\u2003- `playlist`.\n' 'For example:```\n>spotify 3cfOd4CMv2snFaKAnMdnvK track\n```\n' 'If you pass a valid link, bot is able to recognize type. Like:```\n' '>spotify https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC\n```', usage='<Spotify link|ID> [type]', enabled=in_production() ) async def spotify(self, ctx: Context, url: str = None, type_: str = None): if not url: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Missing Spotify link or ID' )) elif not type_: try: type_ = url.split('&')[0].split('?')[0].split('/')[3] except IndexError: pass if type_ == 'user': return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: User profiles are not supported', description='...yet?' )) elif type_ not in ['track', 'album', 'artist', 'playlist']: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: What is this?', description='Is it `track`, `album`, `artist` or `playlist`?' )) if url.startswith(('http://open.spotify.com', 'https://open.spotify.com')): url = url.split('?')[0].split('/')[-1] type_ = type_.lower() try: sp = Spotify(auth_manager=SpotifyClientCredentials( client_id=spotify_client_id(), client_secret=spotify_client_secret() )) except SpotifyOauthError: sp = None if not sp: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Unable to connect to Spotify!' )) result = error_code = None em = SuccessEmbed( author=ctx.author ).set_author( name=f'{ctx.author.display_name} shared a{"n" if type_[0] == "a" else ""} {type_}:', icon_url=ctx.author.avatar_url ) if type_ == 'track': try: result = sp.track(url) except SpotifyException as e: error_code = int(e.http_status) elif type_ == 'album': try: result = sp.album(url) except SpotifyException as e: error_code = int(e.http_status) elif type_ == 'playlist': try: result = sp.playlist(url) except SpotifyException as e: error_code = int(e.http_status) elif type_ == 'artist': try: result = sp.artist(url) except SpotifyException as e: error_code = int(e.http_status) else: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Unknown object type', description='Check `>help` for valid object types.' )) if error_code: if error_code == 400: d = 'Invalid ID or URL.' elif error_code == 429: d = 'Unable to do that now, please try again in 5 minutes.' elif str(error_code).startswith('5'): d = 'Spotify is not responding.' else: d = 'Unknown error. Please try again in a few minutes and please make sure URL or ID is valid.' return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: An error occurred!', description=d )) elif not result: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Unable to find anything on Spotify', description='Probably URL/ID is wrong.' )) title = result['name'] # Artists if type_ not in ['artist', 'playlist']: artists = list(map(lambda x: [x['name'], x['external_urls']['spotify']], result['artists'])) elif type_ in ['playlist']: artists = [[result['owner']['display_name'], result['owner']['external_urls']['spotify']]] else: artists = None # Released if type_ == 'track': released = result['album']['release_date'] elif type_ == 'album': released = result['release_date'] else: released = None # Genres if type_ in ['artist', 'album']: genres = ', '.join(result['genres']) or 'Not specified' else: genres = None ex_url = result['external_urls']['spotify'] thumbnail = result['album']['images'][0]['url'] if type_ == 'track' else result['images'][0]['url'] # Title if title: em.add_field( name='Name' if type_ in ['artist'] else 'Title', value=title ) # Author / Artist(s) if artists: em.add_field( name='Author' if type_ == 'playlist' else 'Artist' if len(artists) == 1 else 'Artists', value=', '.join(map(lambda x: f'[{x[0]}]({x[1]} "Check it on Spotify")', artists)) ) # Followers if type_ in ['artist', 'playlist']: em.add_field( name='Followers', value=result['followers']['total'] ) # Album if type_ == 'track': em.add_field( name='Album', value=f'[{result["name"]}]({result["album"]["external_urls"]["spotify"]} "Check it on Spotify")' ) # Released if released: em.add_field( name='Released', value=released ) # Tracks if type_ in ['playlist', 'album']: em.add_field( name='Tracks', value=str(result['tracks']['total']) ) # Genres if genres: em.add_field( name='Genres', value=genres ) # Popularity if type_ in ['track', 'artist', 'album']: em.add_field( name='Popularity', value=str(result['popularity']) ) # Label elif type_ == 'album': em.add_field( name='Label', value=result['label'] ) # Spotify link if ex_url: em.add_field( name='Spotify', value=ex_url, inline=False ) # YouTube link if type_ == 'track': # Lookup YouTube query = '{} {}'.format(result['name'], ' '.join(map(lambda x: x['name'], result['artists']))) yt = SearchVideos( query, mode='dict', max_results=1 ).result() # noinspection PyTypeChecker yt = yt['search_result'][0]['link'] if yt else None em.add_field( name='YouTube', value=yt, inline=False ) # Thumbnail if thumbnail: em.set_thumbnail( url=thumbnail ) await ctx.send(embed=em) try: await ctx.message.delete() except Forbidden or NotFound or HTTPException: pass
class Profiles(Cog): def __init__(self, bot): self.bot = bot @command( name='profile', brief='Shows user\'s profile', description='Show user\'s profile from database (XP, cash, etc.)', usage='[user]', aliases=['prof'], enabled=in_production() ) async def profile(self, ctx: Context, user: User = None): if not user: user = ctx.author if user.bot is True: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Bots do not have profiles' )) else: msg = await ctx.send(embed=PleaseWaitEmbed(author=ctx.author)) result_user = get_single_user(user.id if user else ctx.author.id) await msg.edit(embed=SuccessEmbed( author=ctx.author, title=':card_box: User\'s data', description='```py\n' '{0.display_name}#{0.discriminator}\n' '```'.format(ctx.guild.get_member(result_user.user_id)) ).add_field( name='XP', value=str(result_user.user_xp) ).add_field( name='Cash', value=f_btc(result_user.user_cash) )) @command( name='daily', brief='Collect daily cash bonus', help='Cooldown resets on 00:00.', enabled=in_production() ) async def daily(self, ctx: Context): base_cash = 200 user = get_single_user(ctx.author.id) now = d.now() able = False time_travel = False if user.last_daily.year == now.year: if user.last_daily.month == now.month: if user.last_daily.day == now.day: pass elif user.last_daily.day < now.day: able = True else: time_travel = True elif user.last_daily.month < now.month: able = True else: time_travel = True elif user.last_daily.year < now.year: able = True else: time_travel = True if time_travel: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Hello time traveler', description='Anyway, there\'s no cash for you.' )) elif able: new_user = user_get_cash(ctx.author.id, base_cash) await ctx.send(embed=SuccessEmbed( author=ctx.author, title=':moneybag: Daily bonus gained!', description=f'You\'ve earned **{f_btc(base_cash)}**,' f' so now you have **{f_btc(new_user.user_cash)}**.' )) else: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: You\'ve already collected your daily cash', description='Please come back tomorrow.' )) @command( name='reputation', brief='[ WIP ] Gives someone reputation', help='Available once a day, resets on 00:00.', usage='<user>', aliases=['rep'], enabled=not in_production() ) async def reputation(self, ctx: Context, user: User): # TODO - Reputation await ctx.send(embed=DevelopmentEmbed( author=ctx.author ).add_field( name='USER', value=str(user) )) @command( name='manage', brief='Manages users\' data', description='Only true Anonymous can use this command', help='Available options:\n' '- xp\n' '- cash', usage='<user> <option> <value>', enabled=in_production(), hidden=True ) async def manage(self, ctx: Context, user: User = None, option: str = None, value: int = None): if ctx.author.id != self.bot.owner_id: st = ':x: You\'re not authorized' elif not user: st = ':x: No user provided' elif user.bot is True: st = ':x: Bots do not have profiles' elif not option: st = ':x: No option specified' elif option not in ['xp', 'cash']: st = ':x: Invalid option' elif value is None: st = ':x: No amount provided' else: st = None msg = await ctx.send(embed=PleaseWaitEmbed(author=ctx.author)) managed_user = get_single_user(user.id) if not managed_user: await msg.edit(embed=ErrorEmbed( author=ctx.author, title=':x: User do not exists in database' )) else: if option == 'xp': updated_user = update_profile(user.id, xp=value) elif option == 'cash': updated_user = update_profile(user.id, cash=value) else: raise text = '```py\n{0.display_name}#{0.discriminator}\n'.format(ctx.guild.get_member(updated_user.user_id)) if option == 'xp': text += f'XP: {value}\n' elif option == 'cash': text += f'Cash: {f_btc(value)}\n' text += '```' await msg.edit(embed=SuccessEmbed( author=ctx.author, title=':incoming_envelope: Profile has been updated', description=text )) if st: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=st )) @command( name='avatar', brief='Shows user\'s avatar', description='No arg will return your\'s avatar and adding user ID or mention will show other user\'s avatar', usage='[user]', aliases=['avk'], enabled=in_production() ) async def avatar(self, ctx: Context, user: User = None): if not user: user = ctx.author await ctx.send(embed=SuccessEmbed( author=ctx.author, title=f':bust_in_silhouette: {user} avatar', description=f'As you wish, {ctx.author.mention}.' ).set_image( url=user.avatar_url )) @command( name='whois', brief='Short info about user', usage='<user>', enabled=in_production() ) async def whois(self, ctx: Context, user: User = None): if not user: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: No user specified' )) else: await ctx.send(embed=InfoEmbed( author=ctx.author, title=f':face_with_monocle: Who is {user.display_name}' ).add_field( name='Original name', value='{0.name}#{0.discriminator}'.format(user), inline=False ).add_field( name='User ID', value=str(user.id), inline=False ).add_field( name='Joined Discord at', value=str(user.created_at)[:19], inline=False ).add_field( name='Bot account', value=str(user.bot), inline=False ).add_field( name='Public flags', value=', '.join(map(lambda z: f'`{z.upper()}`' if z else None, list(filter( lambda y: y is not None, map(lambda x: x[0] if x[1] else None, user.public_flags) )))) or 'None' ).set_thumbnail( url=user.avatar_url )) @command( name='notes', brief='Manages your notes', description='Every user can save upto 3 notes.', help='Available options:' '- create <note content>' '- delete <note UID>' '- edit <note UID>', usage='<option [...]>', enabled=not in_production() ) async def notes(self, ctx: Context, option: str = None, arg: Union[int, str] = None): # TODO - Notes await ctx.send(embed=DevelopmentEmbed( author=ctx.author ).add_field( name='OPTION', value=option ).add_field( name='ARG', value=f'{str(arg)} ({type(arg).__class__.__name__})' ))
class Basics(Cog): def __init__(self, bot): self.bot = bot @command(name='help', brief='Shows this message', usage='[category|command]', enabled=in_production()) async def help(self, ctx: Context, arg: str = None): help_em = InfoEmbed(author=ctx.author, title=':grey_question: Help') help_category = 'You can also type `>help <category>` for more info on a category.' help_command = 'Type `>help <command>` for more info on a command.' if arg is None: help_em.description = f'{help_category}\n{help_command}' for cog in self.bot.cogs: help_em.add_field(name=str(cog), value=', '.join( map(lambda x: f'`{x.name}`', self.bot.cogs[cog].get_commands())), inline=False) else: cmd: Command = self.bot.get_command(arg) if not cmd: cog: Cog = self.bot.get_cog(arg.capitalize()) if not cog: help_em.description = f'No command or category called `{arg}` found.' # Cog found else: help_em.description = help_command help_em.add_field(name='Category', value=f'```\n{cog.qualified_name}\n```', inline=False) for cmd in cog.get_commands(): try: if await cmd.can_run(ctx): help_em.add_field(name=f'`{cmd}`', value=cmd.brief or '\u200b') except CommandError: pass # Command found else: help_em.description = help_category help_em.add_field(name='Command', value=f'```\n{cmd.name}\n```', inline=False) if cmd.description: help_em.add_field(name='Description', value=cmd.description, inline=False) if cmd.aliases: help_em.add_field(name='Aliases', value=', '.join( map(lambda x: f'`{x}`', cmd.aliases)), inline=False) if cmd.usage: help_em.add_field( name='Usage', value=f'```\n>{cmd.name} {cmd.usage}\n```', inline=False) if cmd.help: help_em.add_field(name='Additional help', value=cmd.help, inline=False) if cmd.aliases or cmd.usage: base = cmd.name if not cmd.aliases else f'[{"|".join([cmd.name, *cmd.aliases])}]' tail = cmd.usage or '' if f'{cmd.name} {cmd.usage}' != f'{base} {tail}': help_em.add_field(name='Classic representation', value=f'```\n>{base} {tail}\n```') await ctx.send(embed=help_em) @command( name='ping', brief='Checks bot latency', description= 'Counts time difference between command execution time and bot\'s response', enabled=in_production()) async def ping(self, ctx: Context): elapsed_time: timedelta = datetime.utcnow() - ctx.message.created_at m, s = divmod(elapsed_time.total_seconds(), 60) ping = int(round((m * 60 + s) * 1000)) await ctx.send(embed=SuccessEmbed( author=ctx.author, title=':ping_pong: Pong!').add_field( name='Latency', value=f'{round(self.bot.latency * 1000)}ms'). add_field(name='Ping', value=f'{ping}ms')) @command(name='invite', brief='Sends bot\'s invite link', enabled=in_production()) async def invite(self, ctx: Context): await ctx.send(embed=InfoEmbed( author=ctx.author, title=':mailbox_with_mail: Check at top.gg', description= '**\u00bb [Click me!](https://top.gg/bot/678357487560425555) \u00ab**' ).add_field( name='Important info', value= 'Remember, that you need **manage users** permission to add me to the server.' )) @command( name='info', brief='Sends short bot\'s info', description= 'Sends info about bot itself and its author. This is NOT help command.', aliases=['about', 'github', 'code'], enabled=in_production()) async def info(self, ctx: Context): await ctx.send(embed=InfoEmbed( author=ctx.author, title=':desktop: Source code', description='This bot is made on open source, GNU GPL v3.0 license.' ).add_field( name='Links', value= '\u00b7 [GitHub homepage](https://github.com/AnonymousX86/Enigma-Bot)\n' '\u00b7 [Changelog](https://github.com/AnonymousX86/Enigma-Bot/' 'blob/master/docs/CHANGELOG.md#enigma-bot-changelog)\n', inline=False ).add_field( name='Support', value= 'If you\'d like to help to develop this bot please check GitHub. (Link above)\n' 'And if **you** need support please check' ' [official support server](https://discord.gg/SRdmrPpf2z "3N1GMA Support Server").', inline=False).add_field( name='More about bot', value=f'Version: `{self.bot.version}`.\n' f'Author: `{str(self.bot.get_user(self.bot.owner_id))}`.', inline=False)) @cooldown(1, 120, BucketType.user) @command(name='suggest', brief='Suggest a change', description='Ask dev(s) for a functionality or give a feedback.', help='Keep your message between 25 and 120 characters.', usage='<message>', aliases=['change', 'feedback'], enabled=in_production()) async def change(self, ctx: Context, *, message: str = None): if not message: await ctx.send( embed=ErrorEmbed(author=ctx.author, title=':x: Whoops!', description='You forget to add a message.')) elif len(message) < 25: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Whoops!', description='Suggestion is too short. Write more, please.')) elif len(message) > 120: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Whoops!', description='Suggestion is too long. Write less, please.')) else: channel: TextChannel = self.bot.get_channel( suggestions_channel_id()) msg = await channel.send( embed=SuggestionEmbed(author=ctx.author, message=message)) await ctx.send(embed=SuccessEmbed( author=ctx.author, title=':thumbsup: Thanks for suggestion!', description= f'Check your suggestion here: {channel.mention} or click' f' [here]({msg.jump_url} "Direct message link").')) await msg.add_reaction(emoji='👍') await msg.add_reaction(emoji='👎') @cooldown(1, 60, BucketType.guild) @command(name='servers', brief='List of guilds bot is in', aliases=['guilds', 'serverlist', 'guildlist', 'slist'], enabled=not in_production(), hidden=True) async def servers(self, ctx: Context): if ctx.author.id != self.bot.owner_id: raise MissingPermissions(missing_perms=['bot_owner']) em = InfoEmbed(author=ctx.author, title=':passport_control: Bot\'s servers list', description='Last 10 (or less) servers') for g, num in zip( self.bot.guilds[:10], 'one,two,three,four,five,six,seven,eight,nine,one::zero'.split( ',')): em.add_field(name=f':{num}: - {g.name}', value=f'```py\n' f'Created at: {str(g.created_at)[:10]}\n' f'Joined at: {str(g.me.joined_at)[:10]}\n' f'Member count: {g.member_count}\n' f'Owner: {str(g.owner)}\n' f'Premium tier: {g.premium_tier}\n' f'Features: {", ".join(g.features) or "-"}\n' f'```', inline=False) await ctx.send(embed=em)
class Fun(Cog): def __init__(self, bot): self.bot = bot # How to send images from imigur # https://stackoverflow.com/questions/57043797/discord-py-getting-random-imgur-images @has_permissions(manage_guild=True) @cooldown(1, 30, BucketType.guild) @command( name='giveaway', brief='Initiates a giveaway', help='Available options:\n' '- create, start, new;' ' with argument <channel>\n' '- delete, stop, end;' ' with argument <message ID>\n' ' Message ID could be found under the giveaway message.\n' 'Maximum item\'s length is 30 characters and maximum amount is 25.', usage='<option> <additional argument> [group result by]', aliases=['ga'], enabled=in_production() ) async def giveaway(self, ctx: Context, option: str = '', arg1: Union[TextChannel, int] = None): if not option: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Please specify an option' )) else: def check(m): return m.channel == ctx.channel and m.author == ctx.author if option in ['create', 'start', 'new']: if not arg1: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Missing channel' )) elif type(arg1) is not TextChannel: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Bad channel format' )) else: perms = arg1.permissions_for(ctx.guild.get_member(self.bot.user.id)) if not perms.read_messages: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: I can\'s see that channel' )) elif not perms.send_messages: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: I can\'s send messages to that channel' )) else: msg = await ctx.send(embed=InfoEmbed( author=ctx.author, title=':shopping_bags: Create giveaway', description=f'Final message will be sent to {arg1.mention}.' )) things: List[List[str, str]] = [] index = 0 info = await ctx.send(embed=InfoEmbed( author=ctx.author, title='Preparing...' )) # Getting items for giveaway while True: index += 1 await info.edit(embed=InfoEmbed( author=ctx.author, title=f':name_badge: {index}{number_suffix(index)} item name...', )) try: # Get item's name response_1 = await self.bot.wait_for('message', check=check, timeout=30) except WaitTimeout: return await info.edit(embed=TimeoutEmbed(author=ctx.author)) else: # Ended before adding at least one item if response_1.content.lower() in ['stop', 'end', 'x']: try: await response_1.delete() except Forbidden: pass if len(things) == 0: return await info.edit(embed=ErrorEmbed( author=ctx.author, title=':x: Too few things' )) break elif len(response_1.content) > 30: try: await response_1.delete() except Forbidden: pass await info.edit(embed=ErrorEmbed( author=ctx.author, title=':x: Name\'s too long', description='Keep it under 30 characters.' )) return await info.edit(embed=InfoEmbed( author=ctx.author, title=f':1234: {index}{number_suffix(index)} item quantity...' )) try: # Get item's quantity response_2 = await self.bot.wait_for('message', check=check, timeout=10) except WaitTimeout: await info.edit(embed=TimeoutEmbed(author=ctx.author)) try: await response_1.delete() except Forbidden: pass return else: # Checking if quantity is a number try: q = int(response_2.content) if q < 1: raise ValueError except ValueError: await info.edit(embed=ErrorEmbed( author=ctx.author, title=':x: Bad format, quantity must be a number and higher than 0' )) try: await response_1.delete() await response_2.delete() except Forbidden: pass return if int(response_2.content) > 25: try: await response_1.delete() except Forbidden: pass await info.edit(embed=ErrorEmbed( author=ctx.author, title=':x: Too much', description='Keep quantity under 25.' )) return await info.edit(embed=PleaseWaitEmbed(author=ctx.author)) things.append([response_1.content, response_2.content]) await msg.edit(embed=msg.embeds[0].add_field( name=things[-1][1], value=things[-1][0] )) try: await response_1.delete() await response_2.delete() except Forbidden: pass await info.delete() final_em = SuccessEmbed( author=ctx.author, title=':white_check_mark: Done!' ).set_footer( text=f'Created by {ctx.author.display_name}' ) for thing in things: final_em.add_field( name=f'x{thing[1]}', value=thing[0] ) await msg.edit(embed=final_em) # Preparing final giveaway message final_em.title = ':gift: Giveaway!' final_em.add_field( name='\u200b', value='React with `📝` to participate!', inline=False ) # Sending final giveaway message try: new_g = await arg1.send(embed=final_em) except Forbidden: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=f':x: I have no permissions to send message in {arg1.mention}' )) else: # Adding message ID to footer await new_g.edit(embed=new_g.embeds[0].add_field(name='\u200b', value=f'{new_g.id}')) try: await new_g.add_reaction(emoji='📝') except Forbidden: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=f':x: I can\'t add emoji to the message in {arg1.mention}' )) else: create_giveaway(new_g.id, ctx.guild.id, data=str(things)) elif option in ['delete', 'stop', 'end']: # Discord ID has 18 digits if len(str(arg1)) != 18: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Bad ID format' )) else: giveaway = get_giveaway_from_message(arg1) # Giveaway message ID do not exists in database if giveaway is None: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Giveaway do not exists' )) # Users shouldn't end giveaway from another guild elif giveaway.guild_id != ctx.guild.id: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: This giveaway do not belongs to this guild' )) else: info = await ctx.send(embed=PleaseWaitEmbed(author=ctx.author)) # Finding giveaway's message giveaway_message: Optional[Message] = None for channel in ctx.guild.text_channels: try: giveaway_message = await channel.fetch_message(arg1) except NotFound: pass else: break # Message do not exists but giveaway do if giveaway_message is None: await info.edit(embed=ErrorEmbed( author=ctx.author, title=':x: Message not found', description='Giveaway exists but its message was probably removed,' ' so I\'m removing the giveaway.' )) if not delete_giveaway(message_id=arg1): await self.bot.debug_log( ctx=ctx, e=DatabaseError(f'Unable to delete giveaway with message ID {arg1}') ) else: # Claiming giveaway's reactions participants = [] for reaction in giveaway_message.reactions: if reaction.emoji == '📝': async for user in reaction.users(): if not user.bot: participants.append(user) break await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Giveaway reaction not found', description='Deleting giveaway without winners.' )) await giveaway_message.edit( embed=giveaway_message.embeds[0].add_field( name='\u200b', value=f'Ended on {d.now()[:16]}' ) ) if not delete_giveaway(message_id=arg1): await self.bot.debug_log( ctx=ctx, e=DatabaseError(f'Unable to delete giveaway with message ID {arg1}') ) # No one added reaction to giveaway if not participants: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: No participants found', description='Deleting giveaway without winners.' )) if not delete_giveaway(message_id=arg1): await self.bot.debug_log( ctx=ctx, e=DatabaseError(f'Unable to delete giveaway with message ID {arg1}') ) else: # Prepare giveaway's data giveaway_data: List[List[str, str]] = literal_eval(giveaway.data) winners = {} for item in giveaway_data: possibles = participants.copy() item_winners = [] for quantity in range(int(item[1])): if len(possibles) == 0: possibles = participants.copy() random_winner = choice(possibles) item_winners.append(random_winner) possibles.remove(random_winner) winners[item[0]] = item_winners # noinspection SpellCheckingInspection win_em = SuccessEmbed( author=ctx.author, title=':tada: Winners' ) await info.edit(embed=InfoEmbed( author=ctx.author, title='How you\'d like to group result?', description='Please type `item` or `user`.' )) try: response: Message = await self.bot.wait_for('message', check=check, timeout=10) except WaitTimeout: await info.edit(embed=TimeoutEmbed(author=ctx.author)) return r = response.content.lower() u = ['u', 'user', 'users'] i = ['i', 'item', 'items'] if r in [*u, *i]: try: await response.delete() except Forbidden: pass # Group by users if r in u: all_users = set() for item in winners: for users in winners[item]: all_users.add(users) user_items = {} for user in all_users: prizes = [] checked = [] for prize in winners: for winner_user in winners[prize]: if winner_user.id == user.id: prizes.append(prize) n_prizes = [] for prize in prizes: if prize not in checked: n_prizes.append(f'{prize} x{prizes.count(prize)}') checked.append(prize) user_items[user] = n_prizes for user in user_items: win_em.add_field( name=user.display_name, value='- ' + '\n- '.join(user_items[user]) ) # Group by items elif r in i: for item in winners: winners_f = {} for w in [el for i, el in enumerate(winners[item], 1) if el not in winners[item][i:]]: winners_f[w] = winners[item].count(w) win_em.add_field( name=item, value='- ' + '\n- '.join(map( lambda x: x.mention + str( ((" *x" + str(winners_f[x])) + "*") if winners_f[x] > 1 else "" ), set(sorted(winners[item], key=lambda x: x.display_name)) )) ) else: await info.edit(embed=ErrorEmbed( author=ctx.author, title=f':x: Unknown option `{r}`' )) return await ctx.send(embed=win_em) try: await ctx.message.delete() except Forbidden: pass await giveaway_message.edit( embed=giveaway_message.embeds[0].set_footer(text=f'Ended on {str(d.now())[:16]}') ) if not delete_giveaway(message_id=arg1): await self.bot.debug_log( ctx=ctx, e=DatabaseError(f'Unable to delete giveaway with message ID {arg1}') ) await info.delete() else: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Invalid option' )) @giveaway.error async def giveaway_error(self, ctx: Context, error: Exception): if isinstance(error, CommandInvokeError): await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: There was a problem with the giveaway', description='Probably, there are too many items in the giveaway.' )) else: raise CommandError(error) @cooldown(2, 5, BucketType.guild) @command( name='iq', brief='Check your IQ', usage='[user]', enabled=in_production() ) async def iq(self, ctx: Context, user: User = None): if not user: user = ctx.author if user.id == self.bot.user.id: iq = 200 elif user.bot is True: iq = 0 else: iq = int(user.id) % int(user.discriminator) % 115 + 5 description = '' if iq == 0: # noinspection SpellCheckingInspection description = 'Bots are stuuupiiid.' elif iq < 10: description = 'Oh my... I didn\'t think it\'s possible to be that stupid.' \ ' *(You\'d be great friends with Paimon)*' elif iq < 25: description = 'It\'s sickness, you know?' elif iq < 40: description = 'Some potatoes are smarter than you.' elif iq < 60: description = 'Roomba is smarter than you LMFAO.' elif iq == 69: description = 'Nice.' elif iq < 70: description = 'In terms of law - you\'re retarded.\n' \ '> Intellectual disability (ID), also known as general learning disability and mental' \ ' retardation (MR), is a generalized neurodevelopmental disorder characterized by' \ ' significantly impaired intellectual and adaptive functioning. It is defined by an IQ' \ ' under 70, in addition to deficits in two or more adaptive behaviors that affect everyday,' \ ' general living.' elif iq < 90: description = 'It\'s okay, but still not so smart.' elif iq < 110: description = 'You\'re normal, ***b o r i n g***.' elif iq <= 120: description = 'Okay, your\'e smart and it\'s maximum value. Cheater...' elif iq == 200: description = 'Oh my... It\'s super duper smart!!1!' safe_name = str(user.display_name). \ replace('*', '\\*'). \ replace('_', '\\_'). \ replace('~', '\\~'). \ replace('>', '\\>') await ctx.send(embed=SuccessEmbed( author=ctx.author, title=f':abacus: {safe_name}\'s IQ is {iq}', description=description )) @cooldown(1, 6, BucketType.guild) @command( name='meme', brief='Send a meme', description='Sends meme from r/dankmemes.', enabled=in_production() ) async def meme(self, ctx: Context): reddit = Reddit( client_id=reddit_client_id(), client_secret=reddit_client_secret(), user_agent=reddit_user_agent() ) posts = [] # noinspection SpellCheckingInspection for submission in reddit.subreddit('dankmemes').hot(limit=20): if not submission.archived: if submission.score > 50: if not submission.is_self: if not submission.over_18: posts.append(submission) if posts: await ctx.send(embed=SuccessEmbed( author=ctx.author, title=':black_joker: Meme found' ).set_image( url=choice(posts).url )) else: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Meme not found', description='Just try again' )) # noinspection SpellCheckingInspection @command( name='randomnumber', brief='Sends random number', description='You can provide maximun and minimum number to choose.', usage='[max] [min]', aliases=['randomnum', 'randnumber', 'randnum'], enabled=in_production() ) async def randomnumber(self, ctx: Context, max_: int = 10, min_: int = 1): nums = list(range(min_, max_ + 1)) if len(nums) == 0: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Invalid argument(s)', description='Please remember, that first argument is `max` and the second is `min`.' )) else: num = choice(nums) url = f'https://numbersapi.p.rapidapi.com/{num}/math' headers = { 'x-rapidapi-host': 'numbersapi.p.rapidapi.com', 'x-rapidapi-key': rapid_api_key() } querystring = {"fragment": "false", "json": "false"} response = request("GET", url, headers=headers, params=querystring) result: Optional[dict] = json_loads(response.text) if response.status_code == 200 else None em = SuccessEmbed( author=ctx.author, title=f':1234: I\'ve chosen {num}' ) if result and result['found']: em.add_field( name='Funfact', value=f'{result["text"].capitalize()}.' ) await ctx.send(embed=em) @command( name='choice', brief='Helps with choosing', usage='<thing1> <thing2> [thingN]', enabled=in_production() ) async def choice(self, ctx: Context, *, things: str): breakpoint() em = ErrorEmbed if not things: title = ':x: No items specified' elif len(things) < 2: title = ':x: Too few thing specified' else: title = f':abcd: I\'ve chosen {choice(things)}' em = SuccessEmbed await ctx.send(embed=em( author=ctx.author, title=title )) @command( name='coin', brief='Tosses a coin', descriptiom='O Valley of Plenty...', aliases=['toss'], enabled=in_production() ) async def coin(self, ctx: Context): await ctx.send(embed=SuccessEmbed( author=ctx.author, title=':small_red_triangle_down: Tails' if randint(1, 2) == 1 else ':small_red_triangle: Heads' ))
class Admin(Cog): def __init__(self, bot): self.bot = bot @command(name='ban', brief='Bans user', usage='<user> [reason]', enabled=in_production()) @has_permissions(ban_members=True) @bot_has_permissions(ban_members=True) async def ban(self, ctx: Context, member: Member = None, *, reason: str = None): # No user provided if not member: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':face_with_raised_eyebrow: Who do I need to ban?', description='You\'ve not provided a victim', )) else: # User is trying to ban yourself if member.id == ctx.message.author.id: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':clown: You can\'t ban yourself', description= 'Ask someone to help you commit sepuku or something...', )) # User is trying to ban guild owner elif member.id == ctx.guild.owner.id: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':crown: You can\'t ban guild owner', description='He\'s the almighty one, sorry')) # User is trying to ban the bot elif member.id == self.bot.user.id: await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':zany_face: I can\'t ban myself', description='Even if I would I can\'t, sorry')) # No errors else: await ctx.send(embed=SuccessEmbed( author=ctx.author, title= f':hammer: Banning {get(ctx.guild.members, id=member.id)}' ).add_field(name='REASON', value=str(reason))) await member.ban(reason=reason) @has_permissions(ban_members=True) @bot_has_permissions(ban_members=True) @command( name='unban', brief='Unbans user', help= 'Because user of course isn\'t in server, provide user\'s name or ID.', uasge='<user> [reason]', enabled=not in_production()) async def unban(self, ctx: Context, user: User = None, *, reason: str = None): if not user: await ctx.send( embed=ErrorEmbed(author=ctx.author, title=':x: User not found') ) else: try: await ctx.guild.unban(user, reason=reason) except HTTPException as e: await ctx.send(embed=ErrorEmbed(author=ctx.author, title=':x: Can\'t unban user')) await self.bot.debug_log(ctx=ctx, e=e, user=user) else: await ctx.send(embed=SuccessEmbed( author=ctx.author, title=':white_check_mark: User unbanned', description= f'**{user.display_name}** now can join back to **{ctx.guild.name}**.' ).add_field(name='REASON', value=str(reason))) @command(name='kick', brief='Kicks user', description='You can provide user ID or mention someone', usage='<user> [reason]', enabled=in_production()) @has_permissions(kick_members=True) @bot_has_permissions(kick_members=True) async def kick(self, ctx: Context, member: Member = None, *, reason: str = None): # No user provided if not member: st = (':cowboy: Who do I need to kick round the clock?', 'You\'ve not provided a victim') # User is trying to ban yourself elif member.id == ctx.author.id: st = ( ':man_facepalming: No... That\'s not how mafia works', 'If you want to leave, do this, but don\'t try to kick yourself, that\'s stupid' ) # User is trying to ban guild owner elif member.id == ctx.guild.owner.id: st = (':oncoming_police_car: Wait, that\'s illegal', 'You can\'t kick the police officer') # User is trying to ban the bot elif member.id == self.bot.user.id: st = (':face_with_symbols_over_mouth: NO', 'I won\'t leave this guild even if you want to') # No errors else: await ctx.send(embed=SuccessEmbed( author=ctx.author, title= f':boot: I\'m kicking {get(ctx.guild.members, id=member.id)} out' ).add_field(name='REASON', value=str(reason))) await member.kick(reason=reason) return await ctx.send( embed=ErrorEmbed(author=ctx.author, title=st[0], description=st[1]) ) @has_permissions(manage_messages=True) @bot_has_permissions(manage_messages=True, read_message_history=True) @cooldown(1, 30, BucketType.guild) @command(name='prune', biref='Clears messages', descriptions='Clears last X messages in current channel', help='You can delete 20 messages at once.', usage='[amount]', enabled=in_production()) async def prune(self, ctx: Context, amount: int = 0): if amount < 1: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Argument error', description='Please provide proper amount of messages to prune.' )) elif amount > 20: return await ctx.send(embed=ErrorEmbed( author=ctx.author, title=':x: Too many messages', description='Please provide amount less than 20.')) deleted = 0 msg = await ctx.send(embed=PleaseWaitEmbed(author=ctx.author)) await ctx.message.delete() async for m in ctx.channel.history(limit=amount + 1): if m.id == msg.id: continue try: await m.delete() except NotFound or HTTPException: pass else: deleted += 1 if deleted < 1: await msg.edit(embed=ErrorEmbed(author=ctx.author, title=':x: Deleting failed')) await msg.edit(embed=SuccessEmbed( author=ctx.author, title= f':wastebasket: Successfully deleted {deleted} message{"s" if deleted > 1 else ""}.' )) await msg.delete(delay=3.0)
def __init__(self, author: User, **kwargs): super().__init__(**kwargs) self.timestamp = datetime.utcnow() self.set_footer(text=str(author) + (' \u2615' if not in_production() else ''), icon_url=author.avatar_url)