Example #1
0
    def __init__(self, interface: ChannelTimerInterface):

        # The interface that connects this timer to the channel where it's
        # running
        self._interface = interface

        # The
        self.step = config.get_config().get_int('timer.time_step')

        # The different periods the timer has been setup with.
        self.periods = []

        # The period the timer is currently at.
        self._current_period = -1
        # The current time within the period.
        self.curr_time = 0

        # The current timer's status. This should not be edited directly,
        # as it is intended that with each change, an event is triggered.
        # See `get_state` and `set_state`
        self._state = None
        self.set_state(State.STOPPED)
        # The action the timer should react to on the next iteration of the loop
        self.action = Action.NONE

        # Whether the period list should loop or not.
        self.repeat = True
        # Whether the timer should count from 0 and show the "elapsed" time,
        # or count back from the period's time and show the remaining time.
        self.countdown = True
Example #2
0
    async def on_member_join(self, member):
        server = member.server

        url = "http://i.imgur.com/jKhEXp6.jpg"
        embed = discord.Embed(url=url).set_image(url=url)

        await self.bot.send_message(member.server, embed=embed)

        welcome = "Welcome, {}!".format(member.mention)

        await self.bot.safe_send(server, welcome)

        channels = config.get_config().get_section('bot.new_member_channels.' +
                                                   server.id)

        if not channels:
            return

        await self.bot.safe_send(server.get_channel(channels['log']), welcome)

        instructions = "\nPlease read and follow the instructions on {}, " \
                       "as well as introducing yourself in {} :smiley:"\
            .format(server.get_channel(channels['info']).mention,
                    server.get_channel(channels['directory']).mention)

        await self.bot.safe_send(server, instructions)
Example #3
0
    async def aboot(self):
        """ Information about me!
        """

        await self.bot.say("Current version: {}\nSource: {}".format(
            config.get_config().get_str('version'),
            config.get_config().get_str('source')),
                           delete_after=self.bot.ans_lifespan * 4)

        await self.bot.say("Questions, suggestions, bug to report?\n" +
                           "Open an issue on the Github page, " +
                           "or send me a message on Discord! " +
                           config.get_config().get_str('author_name'),
                           delete_after=self.bot.ans_lifespan * 4)

        await self.bot.say(
            "Please consider donating at: https://goo.gl/sSiaX3",
            delete_after=self.bot.ans_lifespan * 4)
Example #4
0
    async def on_ready(self):
        """ A listener for the event in which the bot is ready to work.
        """

        lib.log("")
        lib.log("Using discord.py version: " + discord.__version__)
        lib.log("Logged in as :")
        lib.log("\t" + self.bot.user.name)
        lib.log("\t" + self.bot.user.id)
        lib.log("")

        await self.bot.update_status()

        message = "**[{}]** {}"\
            .format(config.get_config().get_str('version'),
                    config.get_config().get_str('startup_msg'))
        for server in self.bot.servers:
            await self.bot.send_message(server, message)
Example #5
0
    async def _translate_keyword(self, keyword: str, server_id: str,
                                 channel_id: str):
        if keyword == "help":
            example_periods = ', '.join(
                str(period.time)
                for period in PomodoroTimer.parse_format(SAFE_DEFAULT_FMT))
            await self.bot.say(
                ("**Example:**\n\t {}setup {}\n\t"
                 "_This will give you a sequence of {}_").format(
                     self.bot.command_prefix, SAFE_DEFAULT_FMT,
                     example_periods),
                delete_after=self.bot.ans_lifespan * 2)

            return None

        if keyword == 'default':
            # fetch default setup string from config,
            # or fallback to "Safe Default"
            translation = config.get_config().get_str(
                'timer.channel_whitelist.' + server_id + '.' + channel_id)
            if translation is None:
                lib.log("No setup configured for this channel. Using the " +
                        "safe default option",
                        channel_id=channel_id)
                translation = SAFE_DEFAULT_FMT

            return translation
        if keyword == 'blank':
            pass

        keys = keyword.split(':', 1)
        if len(keys) < 2:
            return keyword
        if keys[0] == 'typical':
            durations = keys[1].split(',', 2)
            return "(2xStudy/Work:{x},Break:{y}),Study/Work:{x},Long_Break:{z}"\
                .format(x=durations[0], y=durations[1], z=durations[2])

        if keys[0] == 'saved':
            translation = config.get_config().get_str('timer.saved_formats.' +
                                                      keys[1])
            return translation
        return keyword
Example #6
0
    async def admin_reloadcfg(self):
        """ Reloads the configuration.
            Requires elevated permissions.
        """

        self.bot.reload_config(config.get_config().reload())

        await self.bot.say("Successfully reloaded configuration.",
                           delete_after=self.bot.ans_lifespan)
        lib.log("Reloaded configuration.")
Example #7
0
    async def on_member_remove(self, member):
        server = member.server

        channels = config.get_config().get_section('bot.new_member_channels.' +
                                                   server.id)
        if not channels:
            return

        await self.bot.safe_send(
            server.get_channel(channels['log']),
            "{} has left the server, farewell!".format(member.mention))
Example #8
0
    async def on_member_update(self, before, after):
        if before.nick == after.nick:
            return

        server = after.server
        channels = config.get_config().get_section('bot.new_member_channels.' +
                                                   server.id)
        if not channels:
            return

        old_name = before.name if before.nick is None else before.nick
        new_name = after.name if after.nick is None else after.nick
        await self.bot.safe_send(
            server.get_channel(channels['log']),
            "{} is now {}. Why tho...".format(old_name, new_name))
Example #9
0
def whitelisted(ctx: commands.Context) -> bool:
    """ Checks if a channel is allowed to have a timer on it.

    :param ctx: The context to check the command in
    :type ctx: commands.Context

    :return: True if the command succeeds, else False.
    """

    whitelist = config.get_config().get_section('timer.channel_whitelist')
    server_id = lib.get_server_id(ctx)

    return whitelist is not None and server_id is not None and \
        server_id in whitelist.keys() and \
        isinstance(ctx.bot, PomodoroBot) and \
        isinstance(whitelist[server_id], dict) and \
        ctx.bot.spoof(ctx.message.author, lib.get_channel(ctx)).id in \
        whitelist[server_id].keys()
Example #10
0
    async def setup(self,
                    ctx: commands.Context,
                    timer_format="default",
                    repeat=None,
                    count_back=None):
        """ Sets up a timer for the channel in which this command was executed.
            Only allows timers in white-listed channels (Specified in the
            configuration).

            :param timer_format: The string containing the periods and
                their names, in a format similar to that of a dictionary.
                Ex.: PeriodA:10,PeriodB:5,PeriodC:15
                     This will create 3 periods of 10, 5 and 15 minutes.

                It also accepts segments with the format (nxName1:t1,Name2:t2),
                which creates n iterations of Name1:t1,Name2:t2 periods (Where
                Name1 and Name2 are the period names and t1, t2 the respective
                times).
                Ex.: (3xPeriodA:10,PeriodB:5),PeriodC:15
                    This will create 7 periods of times 10,5,10,5,10,5 and 15.
            :type timer_format: str

            :param repeat: (boolean) Whether the timer should go back to
                period 1 after going through the complete list (True)
                or not (False). Defaults to True.

            :param count_back: (boolean) Whether the timer should show
                remaining (True) or elapsed (False) time. Defaults to True.
        """

        channel = self.bot.spoof(ctx.message.author, lib.get_channel(ctx))

        timer_format = await self._translate_keyword(timer_format,
                                                     lib.get_server_id(ctx),
                                                     channel.id)
        if timer_format is None:
            return

        # Parse the countdown and looping arguments with the custom function.
        try:
            loop = config.get_config().get_boolean('timer.looping_default') if \
                repeat is None else lib.to_boolean(repeat)

            countdown = config.get_config() \
                .get_boolean('timer.countdown_default') if count_back is None \
                else lib.to_boolean(count_back)

        except TypeError:
            lib.log(
                "Could not parse boolean arguments '{!s}' and '{!s}'".format(
                    repeat, count_back),
                channel_id=channel.id)
            await self.bot.say("Invalid arguments received, please try again.",
                               delete_after=self.bot.ans_lifespan)
            return

        interface = self.bot.get_interface(channel)
        if interface.timer is None:
            interface.timer = PomodoroTimer(interface)
            times = interface.timer.setup(timer_format, loop, countdown)

            if times is not None:
                log = ("Correctly set up timer config: {}."
                       "\nLooping is **{}**\nCountdown is **{}**") \
                    .format(times, "ON" if loop else "OFF",
                            "ON" if countdown else "OFF")
                send = log
            else:
                interface.timer = None
                log = ("Could not set the periods correctly, "
                       "command 'setup' failed.")
                send = ("I did not understand what you wanted, "
                        "please try again!")

        else:  # channel_id is in p_timers.keys()
            log = ("Rejecting setup command, there is a period set already "
                   "established.")
            send = ("I'm already set and ready to go, please use the reset "
                    "command if you want to change the timer configuration.")

        lib.log(log, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan)
Example #11
0
    if len(sys.argv) < 2:
        print("Not enough arguments received!\nUsage: " + sys.argv[0] +
              " <token>")
        exit(-1)

    elif len(sys.argv) == 2:
        TOKEN = sys.argv[1]

    else:
        exit(-2)

    # Config
    config.load('bot.yml')

    # Logging
    sys.stdout = sys.__stdout__ = io.TextIOWrapper(sys.stdout.detach(),
                                                   encoding='utf8',
                                                   errors='backslashreplace',
                                                   line_buffering=True)
    lib.init_logger()

    # Bot init
    bot.reload_config(config.get_config())
    bot.load_extension('pomodorobot.ext.timercommands')
    bot.load_extension('pomodorobot.ext.events')
    bot.load_extension('pomodorobot.ext.other')
    bot.load_extension('pomodorobot.ext.admin')
    bot.load_extension('pomodorobot.ext.registry')

    bot.run(TOKEN)