Пример #1
0
 def on_user_command(self, event, username=None):
     """
     Last.fm Get basic stats from last.fm account.
     If no argument is passed, this command will return the basic info of the author's set Last.FM account.
     Otherwise, this command accepts either a Discord user ID, nickname or @user as a single argument.
     Returns the basic info of the target user's Last.FM account.
     """
     if username is None:
         username = event.author.id
     fm_embed, username = self.generic_user_data(
         username,
         guild=(event.channel.is_dm or event.guild.id),
         footer_text="Requested by {}".format(event.author),
         footer_img=event.author.get_avatar_url(size=32),
         timestamp=event.msg.timestamp.isoformat(),
     )
     url = "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={}&api_key={}&format=json&limit=3".format(
         username,
         self.last_key,
     )
     self.get_fm_secondary(
         embed=fm_embed,
         url=url,
         name="Recent tracks",
         primary_index="recenttracks",
         secondary_index="track",
         artists=True,
         artist_name="#text",
         entry_format="ago",
         cool_down=30,
         seperator="\n",
         limit=3,
     )
     api_loop(event.channel.send_message, embed=fm_embed)
Пример #2
0
 def on_join(self, event):
     """
     Voice Make me join a voice channel.
     Accepts no arguments.
     """
     self.pre_check(event)
     state = event.guild.get_member(event.author).get_voice_state()
     if not state:
         return api_loop(
             event.channel.send_message,
             "You must be in a voice channel to use that command.",
         )
     if event.guild.id not in self.guilds:
         try:
             client = state.channel.connect(mute=False)
         except VoiceException as e:
             return api_loop(
                 event.channel.send_message,
                 "Failed to connect to voice: `{}`".format(e),
             )
         else:
             self.guilds[event.guild.id] = psuedo_queue(
                 self,
                 player=Player(client),
                 guild_id=event.guild.id,
             )
         return
Пример #3
0
 def on_queue_next_command(self, event, index):
     """
     Voice Move an item that's already queued to the front of the queue by index.
     Only accepts a single integer argument (the index of the target queue item).
     """
     self.pre_check(event)
     self.same_channel_check(event)
     if 1 < index <= len(self.get_player(event.guild.id).queue):
         index -= 1
         self.get_player(event.guild.id).queue.insert(
             0,
             self.get_player(event.guild.id).queue.pop(index),
         )
         ytdata = self.get_ytdl_values(
             self.get_player(event.guild.id).queue[0].metadata, )
         api_loop(
             event.channel.send_message,
             "Moved ``{}`` to the front of the queue.".format(
                 ytdata["title"],
                 ytdata["uploader"],
                 ytdata["time_formated"],
                 ytdata["source"],
             ),
         )
     else:
         api_loop(event.channel.send_message, "Invalid index input.")
Пример #4
0
 def on_playing_command(self, event):
     """
     Voice Get information about currently playing song.
     Accepts no arguments.
     """
     self.pre_check(event)
     now_playing = self.get_player(event.guild.id).player.now_playing
     if now_playing is None:
         api_loop(
             event.channel.send_message,
             "Not currently playing anything",
         )
     else:
         ytdata = self.get_ytdl_values(
             self.get_player(event.guild.id).player.now_playing.metadata, )
         api_loop(
             event.channel.send_message,
             "Currently playing ``{}`` by ``{}`` with length ``{}`` minutes using ``{}``."
             .format(
                 ytdata["title"],
                 ytdata["uploader"],
                 ytdata["time_formated"],
                 ytdata["source"],
             ),
         )
Пример #5
0
 def on_shuffle(self, event):
     """
     Voice Shuffle the playing queue.
     Accepts no arguments.
     """
     self.pre_check(event)
     shuffle(self.get_player(event.guild.id).queue)
     api_loop(event.channel.send_message, "Queue shuffled.")
Пример #6
0
 def on_queue_clear_command(self, event):
     """
     Voice Clear the current player's queue.
     Accepts no arguments.
     """
     self.pre_check(event)
     self.same_channel_check(event)
     if self.get_player(event.guild.id).queue:
         self.get_player(event.guild.id).queue.clear()
         api_loop(event.channel.send_message, "The queue has been cleared.")
     else:
         api_loop(event.channel.send_message, "The queue is already empty.")
Пример #7
0
def generic_react(self,
                  client,
                  message_id,
                  channel_id,
                  reactor,
                  index,
                  data,
                  edit_message,
                  amount=1,
                  limit=100,
                  **kwargs):
    remainder = (len(data) % amount)
    if reactor == "\N{black rightwards arrow}":
        index = right_shift(
            index,
            len(data),
            amount=amount,
            limit=limit,
            remainder=remainder,
        )
    elif reactor == "\N{Cross Mark}":
        try:
            api_loop(
                client.client.api.channels_messages_delete,
                channel_id,
                message_id,
            )
        except APIException as e:
            if e.code == 10008:
                pass
            else:
                raise e
        return None
    elif reactor == "\N{leftwards black arrow}":
        index = left_shift(
            index,
            len(data),
            amount=amount,
            limit=limit,
            remainder=remainder,
        )
    else:
        return
    content, embed = edit_message(data=data, index=index, kwargs=kwargs)
    api_loop(
        client.client.api.channels_messages_modify,
        channel_id,
        message_id,
        content=content,
        embed=embed,
    )
    return index
Пример #8
0
 def on_remove_command(self, event, index):
     """
     Voice Remove a song from the queue by it's index.
     Accepts no arguments.
     """
     self.pre_check(event)
     self.same_channel_check(event)
     if not self.get_player(event.guild.id).queue:
         api_loop(
             event.channel.send_message,
             "There aren't any songs queued right now.",
         )
     elif str(index).lower() == "all":
         self.get_player(event.guild.id).queue = list()
         api_loop(event.channel.send_message, "Cleared playing queue.")
     elif (str(index).isdigit() and 0 <=
           (int(index) - 1) <= len(self.get_player(event.guild.id).queue)):
         yt_dl_object = self.get_player(event.guild.id).pop(int(index) - 1)
         ytdata = self.get_ytdl_values(yt_dl_object.metadata)
         api_loop(
             event.channel.send_message,
             "Removed index ``{}`` at index ``{}``.".format(
                 ytdata["title"],
                 index,
             ),
         )
     else:
         api_loop(event.channel.send_message, "Invalid index input.")
Пример #9
0
 def on_kill(self, event):
     if event.channel.is_dm:
         return api_loop(
             event.channel.send_message,
             "Voice commands aren't allowed in the forbidden lands.",
         )
     self.get_player(event.guild.id).client.ws.sock.shutdown()
Пример #10
0
 def on_ping_command(self, event):
     """
     Miscellaneous Test delay command.
     Accepts no arguments.
     """
     bot_message = api_loop(
         event.channel.send_message,
         "***RADIO STATIC***",
     )
     message_time = bot_message.timestamp.timestamp()
     event_time = event.msg.timestamp.timestamp()
     api_loop(
         bot_message.edit,
         "Pong! {} ms".format(
             round(Decimal((message_time - event_time) * 1000)), ),
     )
Пример #11
0
 def on_artist_command(self, event, artist):
     """
     Last.fm Get an artist's info on Last.fm.
     """
     artist_info = self.get_artist(artist)
     inline = {
         "Listeners": artist_info["stats"]["listeners"],
         "Play Count": artist_info["stats"]["playcount"],
         "On-Tour": str(bool(artist_info["ontour"])),
     }
     artist_embed = bot.generic_embed_values(
         title=artist_info["name"],
         url=artist_info["url"],
         thumbnail=artist_info["image"][len(artist_info["image"]) -
                                        1]["#text"],
         inlines=inline,
         skip_inlines="N/A",
     )
     api_loop(event.channel.send_message, embed=artist_embed)
Пример #12
0
 def on_move(self, event):
     # """
     # Voice Move me to another voice channel (this currently clears play queue).
     # Accepts no arguments.
     # """
     raise CommandError("NotImplemented")
     self.pre_check(event)
     if event.guild.id != 152559372126519296:
         return api_loop(
             event.channel.send_message,
             "This command is currently B R O K E and crippingly out of date.",
         )
     self.get_player(event.guild.id).thread.isAlive()
     state = event.guild.get_member(event.author).get_voice_state()
     if not state:
         return api_loop(
             event.channel.send_message,
             "You must be in a voice channel to use that command.",
         )
Пример #13
0
 def on_friends_command(self, event):
     """
     Last.fm Get a list of what your friends have recently listened to.
     Accepts no arguments.
     """
     data = handle_sql(
         db_session.query(friends).filter_by(
             master_id=event.author.id, ).all)
     if not data:
         api_loop(
             event.channel.send_message,
             "You don't have any friends, use ``fm.friends add @`` to get some.",
         )
     else:
         data = [x.slave_id for x in data]
         content, embed = self.friends_search(
             data,
             0,
             author=event.author.id,
             title="{} friends.".format(event.author),
             thumbnail=event.author.avatar_url,
         )
         reply = api_loop(event.channel.send_message, embed=embed)
         if len(data) > 5 and not event.channel.is_dm:
             bot.reactor.init_event(
                 message=reply,
                 timing=30,
                 author=event.author.id,
                 data=data,
                 index=0,
                 amount=5,
                 edit_message=self.friends_search,
             )
             bot.reactor.add_reactors(
                 self,
                 reply,
                 generic_react,
                 event.author.id,
                 "\N{leftwards black arrow}",
                 "\N{Cross Mark}",
                 "\N{black rightwards arrow}",
             )
Пример #14
0
 def on_lyrics_command(self, event, content):
     """
     Api Return lyrics for a song.
     """
     self.pre_check("google_key", "google_cse_engine_ID")
     first_message = api_loop(
         event.channel.send_message,
         "Searching for lyrics...",
     )
     title, lyrics = get_lyrics(
         self.google_key,
         self.google_cse_engine_ID,
     ).get_lyrics(quote_plus(content))
     if len(lyrics) > 46300:
         return first_message.edit("I doubt that's a song.")
     if not lyrics:
         return first_message.edit("No Lyrics found for ``{}``".format(
             sanitize(
                 content,
                 escape_codeblocks=True,
             )
         ))
     lyrics_embed = bot.generic_embed_values(
         title=title,
         footer_text="Requested by {}".format(event.author),
         footer_img=event.author.get_avatar_url(size=32),
         timestamp=event.msg.timestamp.isoformat(),
     )
     first_message.delete()
     responses = 1
     while lyrics and responses < 4:
         lyrics_embed.description = lyrics[:2048]
         lyrics = lyrics[2048:]
         if lyrics:
             tmp_to_shift = lyrics_embed.description.splitlines()[-1]
             lyrics = tmp_to_shift + lyrics
             lyrics_embed.description = lyrics_embed.description[
                 :-len(tmp_to_shift)
             ]
         api_loop(event.channel.send_message, embed=lyrics_embed)
         responses += 1
Пример #15
0
 def on_username_command(self, event, username: str = None):
     """
     Last.fm Set user default last.fm account.
     This command accepts a username that fits Last.FM's username format as of 2019/04/11 and will assign that as the author's Last.FM account.
     If no arguments are passed, it will return the author's assigned Last.FM username.
     """
     if username is not None:
         username = self.get_last_account(username)["user"]["name"]
         handle_sql(
             db_session.query(users).filter_by(
                 user_id=event.author.id, ).update,
             {"last_username": username},
         )
         handle_sql(db_session.flush)
         api_loop(
             event.channel.send_message,
             "Username for ``{}`` changed to ``{}``.".format(
                 event.author, username),
         )
     else:
         try:
             current_username = self.get_user_info(
                 event.author.id)["username"]
         except CommandError:
             api_loop(
                 event.channel.send_message,
                 "Username not set for ``{}``".format(event.author),
             )
         else:
             api_loop(
                 event.channel.send_message,
                 "Username for ``{}`` currently set to ``{}``.".format(
                     event.author,
                     current_username,
                 ))
Пример #16
0
 def on_top_tracks_command(self, event, username=None):
     """
     Last.fm Get an account's top tracks.
     If no argument is passed, this command will return the top tracks of the author's set Last.FM account.
     Otherwise, this command accepts either a Discord user ID, nickname or @user as a single argument.
     Returns the top tracks of the target user's Last.FM account.
     """
     limit = 5
     if username is None:
         username = event.author.id
     period = self.get_user_info(event.author.id)["period"]
     fm_embed, lastname = self.generic_user_data(
         username,
         guild=(event.channel.is_dm or event.guild.id),
         title_template=("Top tracks for {} over" +
                         (" " + period).replace(" over", "")),
         footer_text="Requested by {}".format(event.author),
         footer_img=event.author.get_avatar_url(size=32),
         timestamp=event.msg.timestamp.isoformat(),
     )
     url = "https://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user={}&api_key={}&format=json&limit={}&period={}".format(
         lastname,
         self.last_key,
         limit,
         period,
     )
     self.get_fm_secondary(
         embed=fm_embed,
         url=url,
         name="Track #{}",
         primary_index="toptracks",
         secondary_index="track",
         artists=True,
         entry_format="amount",
         limit=limit,
         inline=False,
     )
     api_loop(event.channel.send_message, embed=fm_embed)
Пример #17
0
 def on_help_command(self, event, command=None):
     """
     Miscellaneous Get a list of the commands in a module.
     If arg is passed, will try to return the info for the relevant command.
     Otherwise, it will just return a list of all the enabled commands.
     """
     if not event.channel.is_dm:
         channel = api_loop(event.author.open_dm)
     else:
         channel = event.channel
     if command is None:
         for help_embed in bot.help_embeds.values():
             dm_default_send(event, channel, embed=help_embed)
     else:
         command_obj = bot.commands_dict.get(command, None)
         if command_obj:
             if command_obj.raw_args is not None:
                 args = " " + command_obj.raw_args + ";"
             else:
                 args = str()
             docstring = command_obj.get_docstring().replace("    ",
                                                             "").strip("\n")
             embed = bot.generic_embed_values(
                 title="{}{}{} a command in the {} module.".format(
                     self.command_prefix,
                     str(command_obj.triggers).replace("[", "(").replace(
                         "'", "**").replace(",", " |").replace("]", ")") +
                     ":", args,
                     docstring.split(" ", 1)[0]),
                 url=bot.local.embed_values.url,
                 description=docstring.split(" ", 1)[1],
             )
             dm_default_send(event, channel, embed=embed)
         else:
             dm_default_send(
                 event,
                 channel,
                 content="``{}`` command not found.".format(command),
             )
     user_info = handle_sql(
         db_session.query(users).filter_by(user_id=event.author.id).first, )
     if user_info is None or user_info.last_username is None:
         dm_default_send(
             event,
             channel,
             content=
             "To get started with this bot, you can set your default last.fm username using the command ``{}username <username>``."
             .format(self.command_prefix),
         )
Пример #18
0
 def on_search_track_command(self, event, track):
     """
     Last.fm Search for a track on Last.fm.
     """
     track_data = self.get_cached(
         "http://ws.audioscrobbler.com/2.0/?method=track.search&track={}&api_key={}&format=json&limit=30"
         .format(
             quote_plus(track.lower()),
             self.last_key,
         ),
         cool_down=3600,
     )
     track_data = track_data["results"]["trackmatches"]["track"]
     if track_data:
         content, embed = self.search_track_react(track_data, 0)
         reply = api_loop(event.channel.send_message, embed=embed)
         if len(track_data) > 5 and not event.channel.is_dm:
             bot.reactor.init_event(
                 message=reply,
                 timing=30,
                 data=track_data,
                 index=0,
                 amount=5,
                 edit_message=self.search_track_react,
             )
             bot.reactor.add_reactors(
                 self,
                 reply,
                 generic_react,
                 event.author.id,
                 "\N{leftwards black arrow}",
                 "\N{Cross Mark}",
                 "\N{black rightwards arrow}",
             )
     else:
         api_loop(event.channel.send_message, "No tracks found.")
Пример #19
0
 def on_friends_add_command(self, event, friend):
     """
     Last.fm Add another user to your friends list.
     This command will either add the user if they're not in your friend's list or remove them otherwise
     and won't target users that haven't setup a last.fm username.
     This command accepts either a Discord user ID or @user
     """
     # friend = AT_to_id(friend)
     # username = self.get_user_info(friend, event.guild.id)["username"]
     friend = self.get_user_info(friend, event.guild.id)["user_id"]
     user = self.state.users.get(int(friend))
     if user is not None:
         user = str(user)
     else:
         user = friend
     friendship = handle_sql(
         db_session.query(friends).filter_by(
             master_id=event.author.id,
             slave_id=friend,
         ).first)
     if friendship is None:
         friendship = friends(master_id=event.author.id, slave_id=friend)
         handle_sql(db_session.add, friendship)
         api_loop(
             event.channel.send_message,
             "Added user ``{}`` to friends list.".format(friend),
         )
     else:
         handle_sql(
             db_session.query(friends).filter_by(master_id=event.author.id,
                                                 slave_id=friend).delete)
         api_loop(
             event.channel.send_message,
             "Removed user ``{}`` from friends list.".format(friend),
         )
     handle_sql(db_session.flush)
Пример #20
0
 def on_alias_list_command(self, event, target=None):
     """
     Last.fm Used to get a list of a user's aliases in a guild.
     When no arguments are given, this will return the author's aliases.
     Otherwise, this accepts one argument (a target user's @, ID or alias) and will return a list of the target's alises.
     """
     if event.channel.is_dm:
         api_loop(
             event.channel.send_message,
             "Alias commands are guild specific.",
         )
     else:
         if target is None:
             target = event.author.id
         else:
             try:
                 target = AT_to_id(target)
             except CommandError as e:
                 data = handle_sql(
                     db_session.query(aliases).filter(
                         aliases.guild_id == event.guild.id,
                         aliases.alias.like(target),
                     ).first)
                 if data is None:
                     raise CommandError(
                         "User alias not found in this guild.")
                 else:
                     target = data.user_id
         data = handle_sql(
             db_session.query(aliases).filter_by(
                 user_id=target,
                 guild_id=event.guild.id,
             ).all)
         user = self.client.api.guilds_members_get(event.guild.id, target)
         if data:
             inline = {
                 str(index + 1): alias.alias
                 for index, alias in enumerate(data)
             }
             embed = bot.generic_embed_values(
                 title="{}'s aliases in {}".format(
                     user.name,
                     event.guild.name,
                 ),
                 non_inlines=inline,
             )
             api_loop(
                 event.channel.send_message,
                 embed=embed,
             )
         else:
             api_loop(
                 event.channel.send_message,
                 "User doesn't have any aliases set in this guild.",
             )
Пример #21
0
 def on_top_period_command(self, event, period=None):
     """
     Last.fm Used to set the default period for the 'top' group of commands.
     Accepts a string argument with the supported arguments being displayed allow.
         Overall
         7 days
         1 months
         3 months
         6 months
         12 months
     The argument isn't case sensative (capital letters don't matter) and spaces are ignored.
     If no arguments are passed, the command will respond with the author's current default period.
     """
     if period is not None:
         period = period.replace(" ", "").strip("s").lower()
         if period in periods.values():
             data = self.get_user_info(event.author.id)
             handle_sql(
                 db_session.query(users).filter_by(
                     user_id=event.author.id, ).update,
                 {
                     "period": {y: x
                                for x, y in periods.items()}[period],
                 },
             )
             handle_sql(db_session.flush)
             api_loop(
                 event.channel.send_message,
                 "Default period for 'top' commands updated to ``{}``.".
                 format(period),
             )
         else:
             api_loop(
                 event.channel.send_message,
                 "Invalid argument, see ``fm.help top period`` for more details.",
             )
     else:
         data = self.get_user_info(event.author.id)
         api_loop(
             event.channel.send_message,
             "Your default 'top' period is currently set to ``{}``".format(
                 data["period"]),
         )
Пример #22
0
 def on_alias_set_command(self, event, alias):
     """
     Last.fm Used to add or remove a user alias in a guild.
     Users are limited to 5 alises in a guild.
     Alises are limited to 20 characters and cannot contain Discord's reserved special characters (e.g. '@', '#').
     """
     if event.channel.is_dm:
         api_loop(event.channel.send_message,
                  "Alias commands are guild specific.")
     else:
         if len(alias) > 20 or sanitize(alias) != alias:
             api_loop(
                 event.channel.send_message,
                 "Aliasas are limited to 20 characters and cannot contain Discord's reserved special characters.",
             )
         else:
             data = handle_sql(
                 db_session.query(aliases).filter(
                     aliases.user_id == event.author.id,
                     aliases.guild_id == event.guild.id,
                     aliases.alias.like(alias),
                 ).first)
             if data is None:
                 if (handle_sql(
                         db_session.query(aliases).filter_by(
                             user_id=event.author.id,
                             guild_id=event.guild.id,
                         ).count) < 5):
                     payload = aliases(
                         user_id=event.author.id,
                         guild_id=event.guild.id,
                         alias=alias,
                     )
                     handle_sql(db_session.add, payload)
                     handle_sql(db_session.flush)
                     api_loop(
                         event.channel.send_message,
                         "Added alias ``{}``.".format(alias),
                     )
                 else:
                     api_loop(
                         event.channel.send_message,
                         "You've reached the 5 alias limit for this guild.".
                         format(data.alias, ),
                     )
             else:
                 if data.user_id == event.author.id:
                     handle_sql(
                         db_session.query(aliases).filter_by(
                             user_id=event.author.id,
                             guild_id=event.guild.id,
                             alias=data.alias,
                         ).delete)
                     handle_sql(db_session.flush)
                     api_loop(
                         event.channel.send_message,
                         "Removed alias ``{}``.".format(data.alias),
                     )
                 else:
                     api_loop(
                         event.channel.send_message,
                         "Alias ``{}`` is already taken in this guild.".
                         format(data.alias),
                     )
Пример #23
0
 def on_playlist_command(self, event, to_shuffle, url=""):
     """
     Voice Used to load the music from a youtube playlist link.
     If the first argument is in the list:
     "shuffle" or "Shuffle",
     then the playlist will be shuffled before it's loaded.
     Only accepts links that match youtube's link formats.
     and will load the items of the playlist into the player queue.
     """
     self.pre_check(event)
     if to_shuffle != "shuffle" and to_shuffle != "Shuffle":
         url = "{} {}".format(to_shuffle, url)
         to_shuffle = "no"
     url_not_found = False
     for url_format in ("https://www.youtube.com/playlist?list=",
                        "https://youtube.com/playlist?list=",
                        "https://youtu.be"):
         if url_format in url:
             url_not_found = True
     if not url_not_found:
         return api_loop(
             event.channel.send_message,
             "Invalid youtube playlist link.",
         )
     if event.guild.get_member(event.author).get_voice_state():
         self.on_join(event)
     self.same_channel_check(event)
     if (event.author.id not in self.cool_down["general"]
             or time() - self.cool_down["general"][event.author.id] >= 1):
         if (event.guild.id not in self.cool_down["playlist"]
                 or not self.cool_down["playlist"][event.guild.id]):
             self.cool_down["playlist"][event.guild.id] = True
             self.cool_down["general"][event.author.id] = time()
             videos_added = 0
             many_object = YoutubeDLInput.many(url, command="ffmpeg")
             try:
                 many_object = list(many_object)
             except Exception as e:
                 return api_loop(
                     event.channel.send_message,
                     "Playlist not found: {}".format(e),
                 )
             if to_shuffle == "shuffle" or to_shuffle == "Shuffle":
                 shuffle(many_object)
             message = api_loop(
                 event.channel.send_message,
                 "Adding music from playlist.",
             )
             for youtubedl_object in many_object:
                 try:
                     yt_data = self.get_ytdl_values(youtubedl_object.info)
                 except DownloadError as e:
                     continue
                 if yt_data["is_live"]:
                     continue
                 elif yt_data is None or yt_data["duration"] > 3620:
                     continue
                 try:
                     self.get_player(
                         event.guild.id).append(youtubedl_object)
                 except CommandError as e:
                     self.cool_down["playlist"][event.guild.id] = False
                     raise e
                 videos_added += 1
             message.edit(
                 "Successfully added {} videos to queue from playlist and dropped {} videos."
                 .format(
                     videos_added,
                     len(many_object) - videos_added,
                 ), )
             self.cool_down["playlist"][event.guild.id] = False
         else:
             api_loop(
                 event.channel.send_message,
                 "Still adding previous playlist, please wait.",
             )
     else:
         cool = round(
             Decimal(
                 1 -
                 (time() - self.cool_down["general"][event.author.id]), ), )
         api_loop(
             event.channel.send_message,
             "Cool down: {} seconds left.".format(cool),
         )
Пример #24
0
 def on_queued_command(self, event, index=None):
     """
     Voice Get the information of a certain song in the queue or the amount of songs in the queue.
     If an integer argument is input, then this will return the relevant queue entry.
     If a string is input, then the string will be used to search for queue entry titles.
     Otherwise, if no arguments are passed, this will return the current length of the queue.
     """
     self.pre_check(event)
     if not self.get_player(event.guild.id).queue:
         api_loop(
             event.channel.send_message,
             "There aren't any songs queued right now.",
         )
     elif index is None:
         api_loop(
             event.channel.send_message,
             "There are {} songs queued ({} minutes). To get a specific song's info, just do this command + index."
             .format(
                 len(self.get_player(event.guild.id).queue),
                 self.minutes_format(
                     self.get_player(event.guild.id, ).queue_length),
             ),
         )
     elif (index.replace("-", "").strip(" ").isdigit() and 0 <=
           (int(index.replace("-", "").strip(" ")) - 1) <= len(
               self.get_player(event.guild.id).queue)):
         ytdata = self.get_ytdl_values(
             self.get_player(event.guild.id).queue[
                 int(index.replace("-", "").strip(" ")) - 1].metadata, )
         api_loop(
             event.channel.send_message,
             "The song at index ``{}`` is ``{}`` by ``{}`` with length ``{}`` minutes and is sourced from ``{}``."
             .format(
                 int(index.replace("-", "").strip(" ")),
                 ytdata["title"],
                 ytdata["uploader"],
                 ytdata["time_formated"],
                 ytdata["source"],
             ),
         )
     elif index.replace("-", "").isdigit():
         api_loop(event.channel.send_message, "Invalid index input.")
     else:
         matched_list = dict()
         for item in self.get_player(event.guild.id).queue:
             ratio = partial_ratio(item.metadata["title"], index)
             if ratio >= 70:
                 matched_list["#{} ({}% match)".format(
                     self.get_player(event.guild.id).queue.index(item) + 1,
                     ratio,
                 )] = item.metadata["title"]
         if matched_list:
             embed = bot.generic_embed_values(
                 title="Queue search results",
                 footer_text="Requested by {}".format(event.author),
                 non_inlines={
                     k: matched_list[k]
                     for k in list(matched_list)[-25:]
                 },
                 footer_img=event.author.get_avatar_url(size=32),
                 timestamp=event.msg.timestamp.isoformat(),
             )
             api_loop(event.channel.send_message, embed=embed)
         else:
             api_loop(
                 event.channel.send_message,
                 "No similar items found in queue.",
             )
Пример #25
0
 def exception_response(self, event, e, respond: bool = True):
     if respond:
         if not isinstance(e, APIException) or e.code != 50013:
             api_loop(
                 event.channel.send_message,
                 "Oops, looks like we've blown a fuse back here. Our technicians have been alerted and will fix the problem as soon as possible.",
             )
     if (self.exception_dms):
         if event.channel.is_dm:
             footer_text = "DM"
         else:
             footer_text = "{}: {}".format(event.guild.name, event.guild.id)
         embed = bot.generic_embed_values(
             author_name=str(event.author),
             author_icon=event.author.get_avatar_url(size=32),
             author_url="https://discordapp.com/users/{}".format(
                 event.author.id, ),
             title="Exception occured: {}".format(str(e)),
             description=event.message.content,
             footer_text=footer_text,
             timestamp=event.message.timestamp.isoformat(),
         )
         for target in self.exception_dms.copy():
             target_dm = self.client.api.users_me_dms_create(
                 int(self.owners[0]))
             try:
                 api_loop(target_dm.send_message, embed=embed)
             except APIException as e:
                 if e.code == 50013:
                     log.warning(
                         "Unable to exception dm: {}".format(target))
                     self.exception_dms.remove(guild)
                 else:
                     raise e
     if self.exception_channels:
         embed = bot.generic_embed_values(
             title="Exception occured: {}".format(str(e)),
             description=extract_stack(),
             footer_text=event.message.content,
         )
         for guild, channel in self.exception_channels.copy().items():
             guild_obj = self.client.state.guilds(guild, None)
             if guild_obj is not None:
                 channel_obj = guild.channels.get(channel, None)
                 if channel_obj is not None:
                     try:
                         api_loop(
                             channel_obj.send_message,
                             embed=embed,
                         )
                     except APIException as e:
                         if e.code == 50013:
                             log.warning(
                                 "Unable to post in exception channel: {}".
                                 format(channel))
                             del self.exception_channels[guild]
                         else:
                             raise e
                 else:
                     log.warning(
                         "Invalid exception channel: {}".format(channel))
                     del self.exception_channels[guild]
             else:
                 log.warning("Invalid exception guild: {}".format(guild))
                 del self.exception_channels[guild]
     log.exception(e)
Пример #26
0
    def custom_prefix(self, event):
        if not event.author.bot:
            if ((not hasattr(event, "channel") or event.channel is None)
                    and not isinstance(event.guild_id, Unset)):
                guild = getattr(event, "guild", None)
                if guild is None:
                    event.guild = self.client.state.guilds.get(
                        event.guild_id,
                        None,
                    )
                    if event.guild is None:
                        event.guild = self.client.state.guilds[
                            event.guild_id] = api_loop(
                                self.client.api.guilds_get,
                                event.guild_id,
                            )
                event.channel = event.guild.channels.get(
                    event.channel_id, None)
                if event.channel is None:
                    event.channel = api_loop(
                        self.client.api.channels_get,
                        event.channel_id,
                    )
            elif ((not hasattr(event, "channel") or event.channel is None)
                  and isinstance(event.guild_id, Unset)):
                event.channel = api_loop(
                    self.client.api.channels_get,
                    event.message.channel_id,
                )

            if event.channel.is_dm:
                prefix = self.command_prefix
            else:
                prefix = self.prefixes.get(event.guild_id, None)
                if prefix is None:
                    guild = handle_sql(
                        db_session.query(guilds).filter_by(
                            guild_id=event.guild_id, ).first, )
                    if guild is None:
                        prefix = self.command_prefix
                        self.prefixes[event.guild_id] = prefix
                        guild = guilds(
                            guild_id=event.guild_id,
                            last_seen=datetime.now().isoformat(),
                            prefix=prefix,
                        )
                        handle_sql(db_session.add, guild)
                        handle_sql(db_session.flush)
                    else:
                        preifx = guild.prefix
                        self.prefixes[event.guild_id] = guild.prefix

            if event.message.content and event.message.content.startswith(
                    prefix):
                prefix_len = len(prefix)
                if (len(event.message.content) > prefix_len
                        and event.message.content[prefix_len] == " "):
                    prefix_len += 1
                message_dict = event.message.content[prefix_len:].split(" ")
                commands = [message_dict[0]]
                if len(message_dict) > 1:
                    for word in message_dict[1:]:
                        commands.append(commands[-1] + " " + word)
                commands = bot.triggers_set.intersection(commands)
                if commands:
                    command = sorted(commands)[-1]
                    event.args = event.message.content[prefix_len +
                                                       len(command):].split()
                    event.name = command
                    event.msg = event.message
                    try:
                        bot.commands_dict[command].execute(event)
                    except CommandError as e:
                        api_loop(event.channel.send_message, str(e))
                    except Exception as e:
                        self.exception_response(event, e)
Пример #27
0
 def on_shutdown_command(self, event):
     if event.author.id in self.owners:
         message = api_loop(event.channel.send_message, "Shutting down.")
         log.info("Soft shutdown initiated.")
Пример #28
0
 def on_prefix_command(self, event, prefix=None):
     """
     Miscellaneous Set a custom guild bot prefix (Manage Guild).
     This command will default to displaying the current prefix
     and ignore perms if no args are given.
     """
     if not event.channel.is_dm:
         if prefix is None:
             guild = handle_sql(
                 db_session.query(guilds).filter_by(
                     guild_id=event.guild.id, ).first, )
             if guild is None:
                 prefix = self.command_prefix
                 guild = guilds(
                     guild_id=event.guild.id,
                     last_seen=datetime.now().isoformat(),
                     name=event.guild.name,
                 )
                 handle_sql(db_session.add, guild)
                 handle_sql(db_session.flush)
             else:
                 prefix = guild.prefix
             return api_loop(
                 event.channel.send_message,
                 "Current prefix is ``{}``".format(prefix),
             )
         user_perms = event.guild.get_member(
             event.author, ).permissions.to_dict()
         if user_perms["manage_guild"] or user_perms["administrator"]:
             if (event.guild.id not in self.cool_down["prefix"]
                     or self.cool_down["prefix"][event.guild.id] <= time()):
                 if handle_sql(
                         db_session.query(guilds).filter_by(
                             guild_id=event.guild.id).first, ) is None:
                     guild = guilds(
                         guild_id=event.guild.id,
                         last_seen=datetime.now().isoformat(),
                         name=event.guild.name,
                         prefix=prefix,
                     )
                     handle_sql(db_session.add, guild)
                 else:
                     handle_sql(
                         db_session.query(guilds).filter_by(
                             guild_id=event.guild.id).update,
                         {
                             "name": event.guild.name,
                             "prefix": prefix
                         },
                     )
                 handle_sql(db_session.flush)
                 self.prefixes[event.guild.id] = prefix
                 api_loop(
                     event.channel.send_message,
                     "Prefix changed to ``{}``".format(prefix),
                 )
                 self.cool_down["prefix"][event.guild.id] = time() + 60
             else:
                 cooldown = self.cool_down["prefix"][event.guild.id]
                 return api_loop(
                     event.channel.send_message,
                     "Cool down: {} seconds left.".format(
                         round(Decimal(cooldown - time())), ),
                 )
         else:
             api_loop(
                 event.channel.send_message,
                 "You need to have the Guild Manage permission to use this command.",
             )
     else:
         api_loop(
             event.channel.send_message,
             "This command can only be used in guilds.",
         )
Пример #29
0
 def on_user_full_command(self, event, username=None):
     """
     Last.fm Get stats from a last.fm account.
     If no argument is passed, this command will return the stats of the author's set Last.FM account.
     Otherwise, this command accepts either a Discord user ID, nickname or @user as a single argument.
     Returns the stats of the target user's Last.FM account.
     """
     if username is None:
         username = event.author.id
     test = time()
     fm_embed, username = self.generic_user_data(
         username,
         guild=(event.channel.is_dm or event.guild.id),
         footer_text="Requested by {}".format(event.author),
         footer_img=event.author.get_avatar_url(size=32),
         timestamp=event.msg.timestamp.isoformat(),
     )
     message = api_loop(event.channel.send_message, "Searching for user.")
     url = "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={}&api_key={}&format=json&limit=3&period={}".format(
         username,
         self.last_key,
         self.get_user_info(event.author.id)["period"],
     )
     self.get_fm_secondary(
         embed=fm_embed,
         url=url,
         name="Recent tracks",
         primary_index="recenttracks",
         secondary_index="track",
         artists=True,
         artist_name="#text",
         entry_format="ago",
         seperator="\n",
         limit=3,
     )
     url = "https://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user={}&api_key={}&format=json&limit=3&period={}".format(
         username,
         self.last_key,
         self.get_user_info(event.author.id)["period"],
     )
     self.get_fm_secondary(
         embed=fm_embed,
         url=url,
         name="Top tracks",
         primary_index="toptracks",
         secondary_index="track",
         artists=True,
         entry_format="amount",
         seperator="\n",
     )
     url = "https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user={}&api_key={}&format=json&limit=3&period={}".format(
         username,
         self.last_key,
         self.get_user_info(event.author.id)["period"],
     )
     self.get_fm_secondary(
         embed=fm_embed,
         url=url,
         name="Top artists",
         primary_index="topartists",
         secondary_index="artist",
         entry_format="amount",
         seperator="\n",
     )
     url = "https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user={}&api_key={}&format=json&limit=3&period={}".format(
         username,
         self.last_key,
         self.get_user_info(event.author.id)["period"],
     )
     self.get_fm_secondary(
         embed=fm_embed,
         url=url,
         name="Top albums",
         primary_index="topalbums",
         secondary_index="album",
         artists=True,
         entry_format="amount",
         seperator="\n",
     )
     fm_embed.set_footer(text="{} ms".format(
         round(Decimal(time() - test) * 1000)), )
     api_loop(message.edit, " ", embed=fm_embed)
Пример #30
0
 def on_restart_command(self, event):
     if event.author.id in self.owners:
         api_loop(event.channel.send_message, "Restarting")
         log.info("Soft restart initiated.")