async def _vq(message, command, silent=False): """List voice channel queue Usage: !vq""" if not await Util.check_args_count( message, command, silent, min=1, max=1): return if not bc.voice_client_queue: e = DiscordEmbed() e.title("🔊 Voice queue 🔊") e.color(0xcc1818) e.description("<empty>") return null(await Msg.response(message, None, silent, embed=e.get())) voice_client_queue = list(bc.voice_client_queue) pos = 0 for voice_queue_chunk in Msg.split_by_chunks( voice_client_queue, const.DISCORD_MAX_EMBED_FILEDS_COUNT): e = DiscordEmbed() e.title("🔊 Voice queue 🔊") e.color(0xcc1818) for entry in voice_queue_chunk: pos += 1 e.add_field( f"{entry.title}", f"Position {pos} (YT: {entry.id}) requested by {entry.requested_by}" ) await Msg.response(message, None, silent, embed=e.get())
async def _quote(message, command, silent=False): """Print some quote from quotes database Examples: !quote !quote 1""" if not await Util.check_args_count(message, command, silent, min=1, max=2): return if not bc.config.quotes: return null(await Msg.response(message, "<Quotes database is empty>", silent)) if len(command) == 2: index = await Util.parse_int( message, command[1], f"Second parameter for '{command[0]}' should be an index of quote", silent) if index is None: return else: index = random.choice(list(bc.config.quotes.keys())) if index not in bc.config.quotes.keys(): return null(await Msg.response(message, "Invalid index of quote!", silent)) quote = bc.config.quotes[index] e = DiscordEmbed() e.title("Quote") e.description(quote.message) e.color(random.randint(0x000000, 0xffffff)) e.timestamp(datetime.datetime.strptime(str(quote.timestamp), const.TIMESTAMP_DATETIME_FORMAT)) e.add_field("Index", str(index), True) e.add_field("Author", quote.author if quote.author else "<unknown>", True) e.add_field("Added by", quote.added_by, True) await Msg.response(message, None, silent, embed=e.get())
async def print_yt_info(message, video_url, silent, full_description=False): """Print YT video info in embed""" r = const.YT_VIDEO_REGEX.match(video_url) if r is None: return null(await Msg.response(message, "Please, provide valid YT link", silent)) ydl_opts = {} try: with youtube_dl.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(video_url, download=False) except Exception as e: return null(await Msg.response( message, f"ERROR: Getting YT video info failed: {e}", silent)) ud = info['upload_date'] e = DiscordEmbed() e.title(info['title']) e.title_url(info['webpage_url']) e.description(info['description'][:2048] if full_description else '') e.color(0xcc1818) e.thumbnail(info['thumbnail']) e.add_field("Views", str(info['view_count']), True) e.add_field("Likes", str(info['like_count']), True) e.add_field("Channel", f"[{info['uploader']}]({info['uploader_url']})", True) e.add_field( "Uploaded", f"{datetime.date(int(ud[0:4]), int(ud[4:6]), int(ud[6:8]))}", True) e.add_field("Duration", f"{datetime.timedelta(seconds=info['duration'])}", True) await Msg.response(message, None, silent, embed=e.get())
async def _listplugin(message, command, silent=False): """Print list of plugins Usage: !listplugin""" if not await Util.check_args_count(message, command, silent, min=1, max=1): return plugin_names = bc.plugin_manager.get_plugins_list() e = DiscordEmbed() e.title("List of plugins") for plugin_name in plugin_names: is_enabled = await bc.plugin_manager.send_command(plugin_name, "is_enabled") e.add_field(plugin_name, "enabled" if is_enabled else "disabled", True) await Msg.response(message, None, silent, embed=e.get())
async def _reminder(message, command, silent=False): """Print information about reminder Example: !reminder 1""" if not await Util.check_args_count( message, command, silent, min=2, max=2): return index = await Util.parse_int( message, command[1], f"Second parameter for '{command[0]}' should be an index of reminder", silent) if index is None: return if index not in bc.config.reminders.keys(): return null(await Msg.response(message, "Invalid index of reminder!", silent)) reminder = bc.config.reminders[index] e = DiscordEmbed() e.title("Reminder info") e.description(reminder.message) e.footer( f"{reminder.author} • {datetime.datetime.strptime(reminder.time, const.REMINDER_DATETIME_FORMAT)}" ) e.add_field("Index", str(index), True) e.add_field("Channel", f"<#{reminder.channel_id}>", True) if reminder.repeat_after: e.add_field( "Repeats every", f"{reminder.repeat_after} {reminder.repeat_interval_measure}", True) e.add_field("Created", reminder.time_created, True) if reminder.prereminders_list: e.add_field( "Pre reminders (in minutes)", ', '.join([str(x) for x in reminder.prereminders_list]), True) if reminder.notes: e.add_field("Notes", reminder.notes, True) await Msg.response(message, None, silent, embed=e.get())
async def _listreminder(message, command, silent=False): """Print list of reminders Examples: !listreminder !listreminder 5 <- prints only first 5 reminders""" if not await Util.check_args_count( message, command, silent, min=1, max=2): return if len(command) == 2: count = await Util.parse_int( message, command[1], f"Second parameter for '{command[0]}' should be amount of reminders to print", silent) if count is None: return reminders_count = count else: reminders_count = len(bc.config.reminders) reminder_list = [] for index, reminder in bc.config.reminders.items(): rep = f' (repeats every {reminder.repeat_after} {reminder.repeat_interval_measure})' prereminders = f' ({", ".join([str(x) + " min" for x in reminder.prereminders_list])} prereminders enabled)' reminder_list.append(( reminder.time, reminder.message, f"{index} at {reminder.time} " f"{f' in <#{reminder.channel_id}>' if message.channel.id != reminder.channel_id else ''}" f"{rep if reminder.repeat_after else ''}" f"{prereminders if reminder.prereminders_list else ''}")) reminder_list.sort() reminder_list = reminder_list[:reminders_count] embed_color = random.randint(0x000000, 0xffffff) for reminder_chunk in Msg.split_by_chunks( reminder_list, const.DISCORD_MAX_EMBED_FILEDS_COUNT): e = DiscordEmbed() e.title("List of reminders") e.color(embed_color) for rem in reminder_chunk: e.add_field(rem[1], rem[2]) await Msg.response(message, None, silent, embed=e.get())
async def _process_reminders_iteration(self) -> None: log.debug3("Reminder processing iteration has started") now = datetime.datetime.now().replace(second=0).strftime( const.REMINDER_DATETIME_FORMAT) to_remove = [] to_append = [] reminder_do_not_update_flag = False for key, rem in self.config.reminders.items(): for i in range(len(rem.prereminders_list)): prereminder = rem.prereminders_list[i] used_prereminder = rem.used_prereminders_list[i] if prereminder == 0 or used_prereminder: continue prereminder_time = (datetime.datetime.now().replace(second=0) + datetime.timedelta(minutes=prereminder)) if rem == prereminder_time.strftime( const.REMINDER_DATETIME_FORMAT): channel = self.get_channel(rem.channel_id) e = DiscordEmbed() clock_emoji = get_clock_emoji( datetime.datetime.now().strftime("%H:%M")) e.title(f"{prereminder} minutes left until reminder") e.description(rem.message + "\n" + rem.notes) e.color(random.randint(0x000000, 0xffffff)) e.timestamp( datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=prereminder)) e.footer(text=rem.author) await channel.send("", embed=e.get()) rem.used_prereminders_list[i] = True if rem == now: channel = self.get_channel(rem.channel_id) clock_emoji = get_clock_emoji( datetime.datetime.now().strftime("%H:%M")) e = DiscordEmbed() e.title(f"{clock_emoji} You asked to remind") e.description(rem.message + "\n" + rem.notes) e.color(random.randint(0x000000, 0xffffff)) e.timestamp(datetime.datetime.now(datetime.timezone.utc)) e.footer(text=rem.author) await channel.send( ' '.join(rem.ping_users if rem.ping_users else ""), embed=e.get()) for user_id in rem.whisper_users: await Msg.send_direct_message( self.get_user(user_id), f"You asked to remind at {now} -> {rem.message}", False) if rem.email_users: mail = Mail(self.secret_config) mail.send( rem.email_users, f"Reminder: {rem.message}", f"You asked to remind at {now} -> {rem.message}") if rem.repeat_after > 0: new_time = datetime.datetime.now().replace( second=0, microsecond=0) + rem.get_next_event_delta() new_time = new_time.strftime( const.REMINDER_DATETIME_FORMAT) to_append.append( Reminder(str(new_time), rem.message, rem.channel_id, rem.author, rem.time_created)) to_append[-1].repeat_after = rem.repeat_after to_append[ -1].repeat_interval_measure = rem.repeat_interval_measure to_append[-1].prereminders_list = rem.prereminders_list to_append[-1].used_prereminders_list = [False] * len( rem.prereminders_list) to_append[-1].notes = rem.notes log.debug2( f"Scheduled renew of recurring reminder - old id: {key}" ) to_remove.append(key) elif rem < now: log.debug2(f"Scheduled reminder with id {key} removal") to_remove.append(key) else: prereminders_delay = 0 if rem.prereminders_list: prereminders_delay = max(rem.prereminders_list) if ((datetime.datetime.strptime( rem.time, const.REMINDER_DATETIME_FORMAT) - datetime.datetime.now()) < datetime.timedelta( minutes=(5 + prereminders_delay / 60))): reminder_do_not_update_flag = True bc.do_not_update[ DoNotUpdateFlag.REMINDER] = reminder_do_not_update_flag for key in to_remove: self.config.reminders.pop(key) for item in to_append: key = self.config.ids["reminder"] self.config.reminders[key] = item self.config.ids["reminder"] += 1 log.debug3("Reminder processing iteration has finished")