Пример #1
0
 async def _delrole(message, command, silent=False):
     """Unassign a role from the user
 Usage: !delrole @user role_name"""
     if not await Util.check_args_count(message, command, silent, min=3):
         return
     user = command[1]
     role_name = ' '.join(command[2:])
     role = discord.utils.get(message.guild.roles, name=role_name)
     if role is None:
         return null(await
                     Msg.response(message,
                                  f"Role '{role_name}' does not exist",
                                  silent))
     member = await message.guild.fetch_member(message.mentions[0].id)
     if member is None:
         return null(await
                     Msg.response(message, f"User '{user}' does not exist",
                                  silent))
     try:
         await member.remove_roles(role)
     except discord.HTTPException as e:
         return await null(
             Msg.response(
                 message,
                 f"Role '{role_name}' could not be assigned to user '{user}'. ERROR: '{e}'",
                 silent))
     await Msg.response(
         message,
         f"Successfully assigned role '{role_name}' to user '{user}'",
         silent)
Пример #2
0
 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())
Пример #3
0
 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())
Пример #4
0
 async def _getmarkovword(message, command, silent=False):
     """Get particular word from Markov model by regex
 Examples:
     !getmarkovword hello -a <- get amount of found words
     !getmarkovword hello 0 <- get word by index"""
     if not await Util.check_args_count(
             message, command, silent, min=3, max=3):
         return
     regex = command[1]
     try:
         found = bc.markov.find_words(regex)
     except re.error as e:
         return null(await Msg.response(message,
                                        f"Invalid regular expression: {e}",
                                        silent))
     amount = len(found)
     if command[2] == '-a':
         result = str(amount)
         await Msg.response(message, result, silent)
         return result
     index = await Util.parse_int(
         message, command[2],
         f"Third parameter '{command[2]}' should be a valid index", silent)
     if index is None:
         return
     if not 0 <= index < amount:
         return null(await Msg.response(
             message,
             f"Wrong index in list '{command[2]}' (should be in range [0..{amount-1}])",
             silent))
     result = found[index]
     await Msg.response(message, result, silent)
     return result
Пример #5
0
 async def _eqstrs(message, command, silent=False):
     """Check if two strings separated by ';' are equal or not
 Example: !eqstrs a;b"""
     if not await Util.check_args_count(message, command, silent, min=2):
         return
     options = ' '.join(command[1:]).split(';')
     if len(options) < 2:
         return null(await Msg.response(message, "Too few options to compare", silent))
     if len(options) > 2:
         return null(await Msg.response(message, "Too many options to compare", silent))
     result = "true" if options[0] == options[1] else "false"
     await Msg.response(message, result, silent)
     return result
Пример #6
0
    async def _vqpush(message, command, silent=False):
        """Push YT video or playlist to queue in voice channel
    Usage: !vqpush <youtube_url>"""
        if not await Util.check_args_count(message, command, silent, min=2):
            return
        for i in range(1, len(command)):
            yt_url = command[i]
            r = const.YT_VIDEO_REGEX.match(
                yt_url) or const.YT_PLAYLIST_REGEX.match(yt_url)
            if r is None:
                return null(await Msg.response(message,
                                               "🔊 Please, provide YT link",
                                               silent))

            # Parse YT url
            parse_url = urllib.parse.urlparse(yt_url)
            params = urllib.parse.parse_qs(parse_url.query)

            if parse_url.path == '/playlist' and 'list' in params.keys(
            ) and params['list']:
                # Process YT playlist
                ydl_opts = {
                    'dump_single_json': True,
                    'extract_flat': True,
                }
                try:
                    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
                        yt_playlist_data = ydl.extract_info(yt_url,
                                                            download=False)
                except Exception as e:
                    return null(await Msg.response(
                        message,
                        f"🔊 ERROR: Fetching YT playlist data failed: {e}",
                        silent))
                yt_video_ids = [
                    entry["id"] for entry in yt_playlist_data["entries"]
                ]
                download_promises = []
                for yt_video_id in yt_video_ids:
                    download_promises.append(
                        _VoiceInternals.push_video(
                            message, f"https://youtu.be/{yt_video_id}",
                            silent))
                await asyncio.gather(*download_promises)
                await Msg.response(
                    message,
                    f"Downloading playlist '{params['list'][0]}' is finished",
                    silent)
            else:
                # Process YT video
                await _VoiceInternals.push_video(message, yt_url, silent)
Пример #7
0
 async def _findmarkov(message, command, silent=False):
     """Match words in Markov model using regex
 Examples:
     !findmarkov hello
     !findmarkov hello -f"""
     if not await Util.check_args_count(
             message, command, silent, min=2, max=3):
         return
     regex = command[1]
     try:
         found = bc.markov.find_words(regex)
     except re.error as e:
         return null(await Msg.response(message,
                                        f"Invalid regular expression: {e}",
                                        silent))
     amount = len(found)
     if not (len(command) > 2 and command[2] == '-f'
             and bc.config.users[message.author.id].permission_level >=
             const.Permission.MOD.value):
         found = found[:100]
     await Msg.response(
         message, f"Found {amount} words in model: {found}"
         f"{f' and {amount - len(found)} more...' if amount - len(found) > 0 else ''}",
         silent,
         suppress_embeds=True)
Пример #8
0
 async def _setreminderchannel(message, command, silent=False):
     """Set channel where reminder will be sent
 Example: !setreminderchannel 1 <channel_id>"""
     if not await Util.check_args_count(
             message, command, silent, min=3, max=3):
         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))
     rem = bc.config.reminders[index]
     channel_id = await Util.parse_int(
         message, command[2],
         f"Third parameter for '{command[0]}' should be channel id", silent)
     if channel_id is None:
         return
     rem.channel_id = channel_id
     await Msg.response(
         message, f"Set channel id {channel_id} for reminder {index}",
         silent)
Пример #9
0
 async def _updresponse(message, command, silent=False):
     """Update bot response
 Example: !updresponse index regex;text"""
     if not await Util.check_args_count(message, command, silent, min=3):
         return
     index = await Util.parse_int(
         message, command[1],
         f"Second parameter for '{command[0]}' should an index (integer)",
         silent)
     if index is None:
         return
     if index in bc.config.responses.keys():
         parts = ' '.join(command[2:]).split(';', 1)
         if len(parts) < 2:
             return null(await Msg.response(
                 message,
                 "You need to provide regex and text that are separated by semicolon (;)",
                 silent))
         regex, text = parts
         bc.config.responses[index] = Response(regex, text)
         await Msg.response(
             message,
             f"Response '{text}' on '{regex}' successfully updated", silent)
     else:
         await Msg.response(message, "Incorrect index of response!", silent)
Пример #10
0
 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())
Пример #11
0
 async def _autostartplugin(message, command, silent=False):
     """Check if plugin automatically starts when bot loads up and set autostart flag for plugin
 Usage:
     !autostartplugin <plugin_name>          <- check if autostart is enabled
     !autostartplugin <plugin_name> enable   <- enable autostart for plugin
     !autostartplugin <plugin_name> disable  <- disable autostart for plugin"""
     if not await Util.check_args_count(message, command, silent, min=2, max=3):
         return
     plugin_name = command[1]
     if len(command) == 2:
         if plugin_name not in bc.config.plugins.keys():
             return null(await Msg.response(message, f"Could not find plugin '{plugin_name}'", silent))
         is_enabled = bc.config.plugins[plugin_name]["autostart"]
         await Msg.response(
             message, f"Autostart for plugin '{plugin_name}' is '{'enabled' if is_enabled else 'disabled'}'",
             silent)
     else:  # len == 3
         cmd = command[2]
         if cmd == "enable":
             bc.config.plugins[plugin_name]["autostart"] = True
             await Msg.response(message, f"Autostart for plugin '{plugin_name}' has been enabled", silent)
         elif cmd == "disable":
             bc.config.plugins[plugin_name]["autostart"] = False
             await Msg.response(message, f"Autostart for plugin '{plugin_name}' has been disabled", silent)
         else:
             await Msg.response(message, f"Unknown subcommand '{cmd}' for plugin autostart manipulation", silent)
Пример #12
0
 async def _timeuntilreminder(message, command, silent=False):
     """Show time until particular reminder
 Example: !timeuntilreminder 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))
     rem = bc.config.reminders[index]
     rem_time = datetime.datetime.strptime(
         rem.time,
         const.REMINDER_DATETIME_FORMAT) - datetime.datetime.now()
     if rem_time < datetime.timedelta(days=1):
         rem_time = "0 days, " + str(rem_time)
     result = f"Time until reminder {index} ('{rem.message}') is {rem_time}"
     await Msg.response(message, result, silent)
     return result
Пример #13
0
 async def _unloadplugin(message, command, silent=False):
     """Unload plugin by its name
 Usage:
     !unloadplugin <plugin_name>"""
     if not await Util.check_args_count(message, command, silent, min=2, max=2):
         return
     plugin_name = command[1]
     if plugin_name not in bc.plugin_manager.get_plugins_list():
         return null(await Msg.response(message, f"Could not find plugin '{plugin_name}'", silent))
     await bc.plugin_manager.send_command(plugin_name, "close")
     await Msg.response(message, f"Plugin '{plugin_name}' has been unloaded", silent)
Пример #14
0
 async def _setprereminders(message, command, silent=False):
     """Set pre reminders notifying that reminder will be sent in particular time.
     For example, send pre reminder 10 minutes before actual event (to prepare or something)
 Usage: !setprereminders <reminder_id> [<time_before_reminder_in_minutes> ...]
 Examples:
     !setprereminders 1 10
     !setprereminders 2 5 10 15"""
     if not await Util.check_args_count(message, command, silent, min=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))
     rem = bc.config.reminders[index]
     prereminders_list = []
     for i in range(2, len(command)):
         time_before_reminder = await Util.parse_int(
             message, command[i],
             f"Parameter #{i} for '{command[0]}' should be time in minutes",
             silent)
         if time_before_reminder is None:
             return
         prereminders_list.append(time_before_reminder)
         if time_before_reminder <= 0:
             return null(await Msg.response(
                 message, "Pre reminder time should be more than 0 minutes",
                 silent))
         if time_before_reminder > 24 * 60:
             return null(await Msg.response(
                 message, "Pre reminder time should be less than 1 day",
                 silent))
     rem.prereminders_list = prereminders_list
     rem.used_prereminders_list = [False] * len(prereminders_list)
     result = f"Set prereminders list for reminder {index}: {', '.join([str(x) for x in rem.prereminders_list])}"
     await Msg.response(message, result, silent)
Пример #15
0
 async def _delmarkov(message, command, silent=False):
     """Delete all words in Markov model by regex
 Example: !delmarkov hello"""
     if not await Util.check_args_count(message, command, silent, min=2):
         return
     regex = ' '.join(command[1:])
     try:
         removed = bc.markov.del_words(regex)
     except re.error as e:
         return null(await Msg.response(message, f"Invalid regular expression: {e}", silent))
     await Msg.response(
         message, f"Deleted {len(removed)} words from model: {removed}", silent, suppress_embeds=True)
Пример #16
0
 async def _stoptimer(message, command, silent=False):
     """Stop timer
 Usage: !stoptimer 1"""
     if not await Util.check_args_count(message, command, silent, min=2, max=2):
         return
     id_ = await Util.parse_int(
         message, command[1], f"Second parameter for '{command[0]}' should be an integer", silent)
     if id_ is None:
         return
     if id_ not in bc.timers.keys():
         return null(await Msg.response(message, f"⏰ Unknown timer id: {id_}", silent))
     bc.timers[id_] = False
     await Msg.response(message, f"⏰ Timer #{id_} is stopped!", silent)
Пример #17
0
    async def _updreminder(message, command, silent=False):
        """Update reminder by index
    Examples:
        !updreminder 0 2020-01-01 00:00 Happy new year!
        !updreminder 0 2020-01-01 00:00 Happy new year!
        !updreminder 0 today 08:00 Wake up
        !updreminder 0 tomorrow 08:00 Wake up
        !updreminder 0 monday 09:00 Time to work
        !updreminder 0 sat 11:00 Time to chill
        !updreminder 0 2d 08:00 Wake up <- 2 days
        !updreminder 0 1w 08:00 Wake up <- 1 week
        !addreminder 0 1m Monthly event
        !addreminder 0 1y Annual event
        !updreminder 0 in 1w5d10h5m Test reminder
        !updreminder 0 in 1w Test reminder 2
        !updreminder 0 in 5h10m Test reminder 3
"""
        if not await Util.check_args_count(message, command, silent, min=5):
            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 in bc.config.reminders.keys():
            text = ' '.join(command[4:])
            if command[2] == "in":
                time = await _ReminderInternals.parse_reminder_args_in(
                    message, command[3], silent)
            else:
                time = await _ReminderInternals.parse_reminder_args(
                    message, command[2], command[3], silent)
            if time is None:
                return
            if datetime.datetime.strptime(
                    str(time),
                    const.REMINDER_DATETIME_FORMAT) < datetime.datetime.now():
                return null(await Msg.response(
                    message, "Reminder timestamp is earlier than now", silent))
            bc.config.reminders[index] = Reminder(
                str(time), text, message.channel.id,
                bc.config.reminders[index].author,
                datetime.datetime.now().strftime(
                    const.REMINDER_DATETIME_FORMAT))
            await Msg.response(
                message,
                f"Successfully updated reminder {index}: '{text}' at {time}",
                silent)
        else:
            await Msg.response(message, "Invalid index of reminder!", silent)
Пример #18
0
 async def _skipreminder(message, command, silent=False):
     """Skip next instance of recurring (repeating) reminder
 Example: !skipreminder 1
 Note: only recurring (repeating) reminders are affected by this command"""
     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))
     if bc.config.reminders[index].repeat_after == 0:
         return null(await Msg.response(message,
                                        "This reminder is not recurring!",
                                        silent))
     rem = bc.config.reminders[index]
     new_time = datetime.datetime.strftime(
         datetime.datetime.strptime(rem.time,
                                    const.REMINDER_DATETIME_FORMAT) +
         rem.get_next_event_delta(), const.REMINDER_DATETIME_FORMAT)
     id_ = bc.config.ids["reminder"]
     bc.config.reminders[id_] = Reminder(
         str(new_time), rem.message, message.channel.id,
         bc.config.reminders[index].author,
         datetime.datetime.now().strftime(const.REMINDER_DATETIME_FORMAT))
     bc.config.reminders[id_].repeat_after = rem.repeat_after
     bc.config.ids["reminder"] += 1
     bc.config.reminders.pop(index)
     await Msg.response(
         message, f"Skipped reminder {index} at {rem.time}, "
         f"next reminder {id_} will be at {bc.config.reminders[id_].time}",
         silent)
Пример #19
0
 async def _timer(message, command, silent=False):
     """Set timer
 Usage: !timer 10"""
     if not await Util.check_args_count(message, command, silent, min=2, max=2):
         return
     start = datetime.datetime.now()
     duration = await Util.parse_int(
         message, command[1], f"Second parameter for '{command[0]}' should be duration in seconds", silent)
     if duration is None:
         return
     if duration < 0:
         return null(await Msg.response(message, "Timer duration should be more than 0 seconds", silent))
     if duration > const.MAX_TIMER_DURATION_IN_SECONDS:
         return null(await Msg.response(message, "Timer duration should be less than 24 hours", silent))
     finish = datetime.datetime.now() + datetime.timedelta(seconds=duration)
     id_ = bc.config.ids["timer"]
     bc.config.ids["timer"] += 1
     timer_msg = await Msg.response(message, f"⏰ Timer #{id_}: {finish - start}", silent)
     bc.do_not_update[DoNotUpdateFlag.TIMER] += 1
     bc.timers[id_] = True
     print_counter = 0
     while True:
         current = datetime.datetime.now()
         if not bc.timers[id_]:
             await timer_msg.edit(content=f"⏰ Timer #{id_}: {finish - current}! (stopped)")
             bc.do_not_update[DoNotUpdateFlag.TIMER] -= 1
             break
         if current >= finish:
             await timer_msg.edit(content=f"⏰ Timer #{id_}: 0:00:00.000000!")
             await Msg.response(message, f"⏰ Timer #{id_}: Time is up!", silent)
             bc.do_not_update[DoNotUpdateFlag.TIMER] -= 1
             break
         print_counter += 1
         if print_counter >= 10 * bc.do_not_update[DoNotUpdateFlag.TIMER]:
             await timer_msg.edit(content=f"⏰ Timer #{id_}: {finish - current}")
             print_counter = 0
         await asyncio.sleep(0.1)
Пример #20
0
 async def parse_reminder_args_in(message, time, silent):
     r = const.REMINDER_IN_REGEX.match(time)
     if r is None:
         return null(await Msg.response(
             message, ("Provide relative time in the following format: "
                       "<weeks>w<days>d<hours>h<minutes>m. "
                       "All parts except one are optional"), silent))
     weeks = int(r.group(2)) if r.group(2) is not None else 0
     days = int(r.group(4)) if r.group(4) is not None else 0
     hours = int(r.group(6)) if r.group(6) is not None else 0
     minutes = int(r.group(8)) if r.group(8) is not None else 0
     time = (datetime.datetime.now() + datetime.timedelta(
         weeks=weeks, days=days, hours=hours, minutes=minutes)).strftime(
             const.REMINDER_DATETIME_FORMAT)
     return time
Пример #21
0
 async def _calc(message, command, silent=False):
     """Calculate mathematical expression
 Examples:
     !calc 2+2*2
     !calc 4/2-1"""
     if not await Util.check_args_count(message, command, silent, min=2):
         return
     expr = ' '.join(command[1:])
     try:
         result = str(MathExprEvaluator().evaluate(expr))
     except Exception as e:
         return null(await
                     Msg.response(message,
                                  f"Expression evaluation failed: {e}",
                                  silent))
     await Msg.response(message, result, silent)
     return result
Пример #22
0
 async def _addresponse(message, command, silent=False):
     """Add bot response on message that contains particular regex
 Example: !addresponse regex;text"""
     if not await Util.check_args_count(message, command, silent, min=2):
         return
     parts = ' '.join(command[1:]).split(';', 1)
     if len(parts) < 2:
         return null(await Msg.response(
             message,
             "You need to provide regex and text that are separated by semicolon (;)",
             silent))
     regex, text = parts
     bc.config.responses[bc.config.ids["response"]] = Response(regex, text)
     bc.config.ids["response"] += 1
     await Msg.response(
         message, f"Response '{text}' on '{regex}' successfully added",
         silent)
Пример #23
0
    async def _addreminder(message, command, silent=False):
        """Print message at particular time
    Examples:
        !addreminder 2020-01-01 00:00 Happy new year!
        !addreminder today 08:00 Wake up
        !addreminder tomorrow 08:00 Wake up
        !addreminder monday 09:00 Time to work
        !addreminder sat 11:00 Time to chill
        !addreminder 2d 08:00 Wake up <- 2 days
        !addreminder 1w 08:00 Wake up <- 1 week
        !addreminder 1m Monthly event
        !addreminder 1y Annual event
        !addreminder in 1w5d10h5m Test reminder
        !addreminder in 1w Test reminder 2
        !addreminder in 5h10m Test reminder 3
"""
        if not await Util.check_args_count(message, command, silent, min=4):
            return
        text = ' '.join(command[3:])
        if command[1] == "in":
            time = await _ReminderInternals.parse_reminder_args_in(
                message, command[2], silent)
        else:
            time = await _ReminderInternals.parse_reminder_args(
                message, command[1], command[2], silent)
        if time is None:
            return
        id_ = bc.config.ids["reminder"]
        if datetime.datetime.strptime(
                str(time),
                const.REMINDER_DATETIME_FORMAT) < datetime.datetime.now():
            return null(await
                        Msg.response(message,
                                     "Reminder timestamp is earlier than now",
                                     silent))
        bc.config.reminders[id_] = Reminder(
            str(time), text, message.channel.id, message.author.name,
            datetime.datetime.now().strftime(const.REMINDER_DATETIME_FORMAT))
        bc.config.ids["reminder"] += 1
        await Msg.response(message,
                           f"Reminder '{text}' with id {id_} added at {time}",
                           silent)
Пример #24
0
 async def _addremindernotes(message, command, silent=False):
     """Add reminder notes
 Example: !addremindernotes 1 Some text"""
     if not await Util.check_args_count(message, command, silent, min=3):
         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))
     rem = bc.config.reminders[index]
     rem.notes = ' '.join(command[2:])
     await Msg.response(message,
                        f"Set notes for reminder {index}: {rem.notes}",
                        silent)
Пример #25
0
 async def push_video(message, yt_video_url, silent):
     """Push video by its URL to voice queue"""
     r = const.YT_VIDEO_REGEX.match(yt_video_url)
     if r is None:
         return
     yt_video_id = r.groups()[0]
     output_file_name = f'{Util.tmp_dir()}/yt_{yt_video_id}.mp3'
     ydl_opts = {
         'format':
         'bestaudio/best',
         'outtmpl':
         output_file_name,
         'postprocessors': [{
             'key': 'FFmpegExtractAudio',
             'preferredcodec': 'mp3',
         }],
     }
     try:
         with youtube_dl.YoutubeDL(ydl_opts) as ydl:
             video_info = ydl.extract_info(yt_video_url, download=False)
             if not os.path.exists(output_file_name):
                 log.debug(f"Downloading YT video {yt_video_url} ...")
                 loop = asyncio.get_event_loop()
                 await loop.run_in_executor(None, ydl.download,
                                            [yt_video_url])
                 log.debug(f"Downloaded {yt_video_url}")
             else:
                 log.debug(f"Found in cache: {yt_video_url}")
     except Exception as e:
         return null(await
                     Msg.response(message,
                                  f"🔊 ERROR: Downloading failed: {e}",
                                  silent))
     bc.voice_client_queue.append(
         VoiceQueueEntry(message.channel, video_info['title'],
                         video_info['id'], output_file_name,
                         message.author.name))
     await Msg.response(
         message,
         f"🔊 Added {video_info['title']} (YT: {video_info['id']}) to the queue "
         f"at position #{len(bc.voice_client_queue)}", silent)
Пример #26
0
 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())
Пример #27
0
 async def _vjoin(message, command, silent=False):
     """Join voice channel
 Usage: !vjoin <voice_channel_id>"""
     if not await Util.check_args_count(
             message, command, silent, min=2, max=2):
         return
     voice_channel_id = await Util.parse_int(
         message, command[1],
         f"Second parameter for '{command[0]}' should be an id of voice channel",
         silent)
     if voice_channel_id is None:
         return
     voice_channels = message.guild.voice_channels
     for v in voice_channels:
         if v.id == voice_channel_id:
             if bc.voice_client is not None:
                 log.debug("Disconnecting from previous voice channel...")
                 await bc.voice_client.disconnect()
                 log.debug("Disconnected from previous voice channel")
                 bc.voice_client = None
             log.debug(
                 f"Connecting to the voice channel {voice_channel_id}...")
             try:
                 bc.voice_client = await v.connect()
             except Exception as e:
                 return null(await
                             Msg.response(message,
                                          f"ERROR: Failed to connect: {e}",
                                          silent))
             log.debug("Connected to the voice channel")
             break
     else:
         await Msg.response(
             message,
             f"🔊 Could not find voice channel with id {voice_channel_id}",
             silent)
Пример #28
0
    async def _if(message, command, silent=False):
        """If expression is true (!= 0) then return first expression otherwise return the second one
    Examples:
        !if 1 It's true;It's false -> It's true
        !if 0 It's true;It's false -> It's false
"""
        if not await Util.check_args_count(message, command, silent, min=3):
            return
        condition = command[1]

        true = ["true"]
        false = ["false"]

        if condition.lower() not in true + false:
            condition = await Util.parse_int(
                message, command[1],
                f"Second parameter should be either number or {', '.join(true + false)}",
                silent)
            if condition is None:
                return
        else:
            # Handle keywords that can be used in conditions
            if condition.lower() in true:
                condition = 1
            elif condition.lower() in false:
                condition = 0

        expressions = ' '.join(command[2:]).split(';')
        if len(expressions) != 2:
            return null(await Msg.response(
                message,
                f"There should be only 2 branches ('then' and 'else') "
                f"separated by ';' in '{command[0]}' command", silent))
        result = expressions[0] if condition != 0 else expressions[1]
        await Msg.response(message, result, silent)
        return result
Пример #29
0
    async def _repeatreminder(message, command, silent=False):
        """Make reminder repeating with particular period
    Examples:
        !repeatreminder 1 1
        !repeatreminder 1 hourly
        !repeatreminder 1 daily
        !repeatreminder 1 weekly
        !repeatreminder 1 monthly
        !repeatreminder 1 annually
        !repeatreminder 1 2h
        !repeatreminder 1 2d
        !repeatreminder 1 2w
        !repeatreminder 1 2m
        !repeatreminder 1 2y
        !repeatreminder 1 0
    Note: number without postfix is translated to minutes. 0 means disabling repetition"""
        if not await Util.check_args_count(
                message, command, silent, min=3, max=3):
            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))

        if command[2] == "hourly":
            command[2] = "1h"
        elif command[2] == "daily":
            command[2] = "1d"
        elif command[2] == "weekly":
            command[2] = "1w"
        elif command[2] == "monthly":
            command[2] = "1m"
        elif command[2] == "annually":
            command[2] = "1y"

        if command[2].endswith("h"):
            duration = command[2][:-1]
            duration = await Util.parse_int(
                message, duration,
                "You need to specify amount of days before 'd'. Example: 3d for 3 days",
                silent)
            if duration is None:
                return
            duration *= 60
        elif command[2].endswith("d"):
            duration = command[2][:-1]
            duration = await Util.parse_int(
                message, duration,
                "You need to specify amount of days before 'd'. Example: 3d for 3 days",
                silent)
            if duration is None:
                return
            duration *= 1440
        elif command[2].endswith("w"):
            duration = command[2][:-1]
            duration = await Util.parse_int(
                message, duration,
                "You need to specify amount of days before 'd'. Example: 3d for 3 days",
                silent)
            if duration is None:
                return
            duration *= 10080
        elif command[2].endswith("m"):
            duration = command[2][:-1]
            duration = await Util.parse_int(
                message, duration,
                "You need to specify amount of days before 'm'. Example: 3m for 3 months",
                silent)
            if duration is None:
                return
            bc.config.reminders[index].repeat_interval_measure = "months"
        elif command[2].endswith("y"):
            duration = command[2][:-1]
            duration = await Util.parse_int(
                message, duration,
                "You need to specify amount of days before 'y'. Example: 3y for 3 years",
                silent)
            if duration is None:
                return
            bc.config.reminders[index].repeat_interval_measure = "years"
        else:
            duration = await Util.parse_int(
                message, command[2],
                f"Third parameter for '{command[0]}' should be duration of period between reminders",
                silent)
            if duration is None:
                return
        if duration < 0:
            return null(await Msg.response(
                message,
                "Duration should be positive or zero (to disable repetition)!",
                silent))
        bc.config.reminders[index].repeat_after = duration
        if duration == 0:
            return null(await Msg.response(
                message, f"Repetition is disabled for reminder {index}",
                silent))
        await Msg.response(
            message, f"Reminder {index} will be repeated every {duration} "
            f"{bc.config.reminders[index].repeat_interval_measure}!", silent)
Пример #30
0
    async def parse_reminder_args(message, date, time, silent):
        WEEK_DAYS_FULL = ("monday", "tuesday", "wednesday", "thursday",
                          "friday", "saturday", "sunday")
        WEEK_DAYS_ABBREV = ("mon", "tue", "wed", "thu", "fri", "sat", "sun")

        if date == "today":
            date = datetime.datetime.strftime(datetime.datetime.now(),
                                              const.REMINDER_DATE_FORMAT)
        elif date == "tomorrow":
            date = datetime.datetime.strftime(
                datetime.datetime.now() + datetime.timedelta(days=1),
                const.REMINDER_DATE_FORMAT)
        elif date.lower() in WEEK_DAYS_FULL or date in WEEK_DAYS_ABBREV:
            if date.lower() in WEEK_DAYS_FULL:
                weekday = WEEK_DAYS_FULL.index(date.lower())
            elif date in WEEK_DAYS_ABBREV:
                weekday = WEEK_DAYS_ABBREV.index(date.lower())
            else:
                return null(await Msg.response(
                    message, "Unexpected error during day of week processing!",
                    silent))
            days_delta = (weekday - datetime.datetime.today().weekday() +
                          7) % 7
            if days_delta == 0:
                days_delta = 7
            date = datetime.datetime.strftime(
                datetime.datetime.now() + datetime.timedelta(days=days_delta),
                const.REMINDER_DATE_FORMAT)
        elif date.endswith("d"):
            days_amount = date[:-1]
            days_amount = await Util.parse_int(
                message, days_amount,
                "You need to specify amount of days before 'd'. Example: 3d for 3 days",
                silent)
            if days_amount is None:
                return
            date = datetime.datetime.strftime(
                datetime.datetime.now() + datetime.timedelta(days=days_amount),
                const.REMINDER_DATE_FORMAT)
        elif date.endswith("d"):
            days_amount = date[:-1]
            days_amount = await Util.parse_int(
                message, days_amount,
                "You need to specify amount of days before 'd'. Example: 3d for 3 days",
                silent)
            if days_amount is None:
                return
            date = datetime.datetime.strftime(
                datetime.datetime.now() + datetime.timedelta(days=days_amount),
                const.REMINDER_DATE_FORMAT)
        elif date.endswith("w"):
            weeks_amount = date[:-1]
            weeks_amount = await Util.parse_int(
                message, weeks_amount,
                "You need to specify amount of weeks before 'w'. Example: 2w for 2 weeks",
                silent)
            if weeks_amount is None:
                return
            date = datetime.datetime.strftime(
                datetime.datetime.now() +
                datetime.timedelta(days=weeks_amount * 7),
                const.REMINDER_DATE_FORMAT)
        elif date.endswith("m"):
            months_amount = date[:-1]
            months_amount = await Util.parse_int(
                message, months_amount,
                "You need to specify amount of months before 'm'. Example: 3m for 3 months",
                silent)
            if months_amount is None:
                return
            date = datetime.datetime.strftime(
                datetime.datetime.now() +
                dateutil.relativedelta.relativedelta(months=months_amount),
                const.REMINDER_DATE_FORMAT)
        elif date.endswith("y"):
            years_amount = date[:-1]
            years_amount = await Util.parse_int(
                message, years_amount,
                "You need to specify amount of years before 'y'. Example: 3y for 3 years",
                silent)
            if years_amount is None:
                return
            date = datetime.datetime.strftime(
                datetime.datetime.now() +
                dateutil.relativedelta.relativedelta(years=years_amount),
                const.REMINDER_DATE_FORMAT)
        time = date + ' ' + time
        try:
            time = datetime.datetime.strptime(
                time, const.REMINDER_DATETIME_FORMAT).strftime(
                    const.REMINDER_DATETIME_FORMAT)
        except ValueError:
            return null(await Msg.response(
                message,
                f"{time} does not match format {const.REMINDER_DATETIME_FORMAT}\n"
                "More information about format: <https://strftime.org/>",
                silent))
        return time