Ejemplo n.º 1
0
    async def timer_pause(self, ctx: commands.Context):
        """ Pauses the timer, if it's running. Keeps all settings and current
            period and time.
        """

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

        interface = self.bot.get_interface(channel)
        if len(interface.subbed) == 0:
            if interface.timer.stop():
                send = "No subs detected, timer will instead stop soon."
                await self.bot.say(send, delete_after=interface.timer.step)
            else:
                await self.bot.remove_messages(channel)

                send = "No subs detected, timer has stopped instead."
                await self.bot.say(send, tts=interface.tts)
            log = (
                "Attempted to pause the timer, but due to the lack of subs, "
                "it will be stopped instead")
        elif interface.timer.pause():
            log = "Timer will be paused soon."
            await self.bot.say(log, delete_after=interface.timer.step)

        else:
            log = "Could not pause timer, stopped or already running."
            await self.bot.say("I cannot stop something that isn't moving.",
                               delete_after=self.bot.ans_lifespan)

        lib.log(log, channel_id=channel.id)
Ejemplo n.º 2
0
    async def timer_sub(self, ctx: commands.Context):
        """ Adds you to the list of people currently using the timer.
            If you're in this list, you will receive a private message if the
            timer's period changes or if it starts/pauses/stops.
        """

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

        interface = self.bot.get_interface(channel)
        if author not in interface.subbed:
            interface.add_sub(author, datetime.utcnow())

            interface.restart_inactivity()

            log = (lib.get_author_name(ctx, True) +
                   " has subscribed to this timer.")
            send = "You've successfully subscribed to this timer, {}!" \
                .format(lib.get_author_name(ctx, True))
        else:
            log = (lib.get_author_name(ctx, True) + " tried to subscribe to " +
                   "this timer, but he was already added")
            send = ("You're already subscribed. " +
                    "I'll let you know of any changes!")

        lib.log(log, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan)
Ejemplo n.º 3
0
    async def timer_unsub(self, ctx: commands.Context):
        """ Removes you from the list of people currently using the timer.
        """

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

        result = 0

        interface = self.bot.get_interface(channel)
        if author in interface.subbed:
            result = interface.remove_sub(author)

            log = (lib.get_author_name(ctx, True) +
                   " has un-subscribed to this timer.")
            send = "You've successfully un-subscribed to this timer, {}!" \
                .format(lib.get_author_name(ctx, True))
        else:
            log = (lib.get_author_name(ctx, True) + " tried to un-subscribe " +
                   "to this timer, but he was not in the list")
            send = "You're not subscribed to this timer... "

        lib.log(log, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan)
        if result == -1:
            await self.bot.say("Timer now has no subs. Will stop after {} "
                               "minutes unless someone subscribes!".format(
                                   self.bot.timer_inactivity_allowed),
                               delete_after=self.bot.ans_lifespan)
        elif result == -2:
            await self.bot.remove_messages(channel)
            await self.bot.say("Timer has stopped since it was paused and "
                               "everyone un-subscribed")
Ejemplo n.º 4
0
    async def remove_timer_period(self,
                                  ctx: commands.Context,
                                  index: int,
                                  amount=1):
        """ Removes the period(s) from the given index

        :param index: The index to remove from, counting from `1` to `n`.
        :param amount: The amount of periods to remove.
        """

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

        interface = self.bot.get_interface(channel)
        timer = interface.timer

        if index > len(timer.periods) or index <= 0:
            await self.bot.say("Unable to remove the specified period(s)",
                               delete_after=self.bot.ans_lifespan)
            return

        if timer.remove_periods(index - 1, amount):
            period_str = 'period' if amount == 1 else 'periods'

            if timer.get_state() != State.STOPPED:
                await self.bot.edit_message(interface.list_message,
                                            timer.list_periods())

            await self.bot.say(
                "Successfully removed the {}!".format(period_str),
                delete_after=self.bot.ans_lifespan)
        else:
            await self.bot.say(("If you want to remove all periods,"
                                " use the reset command!"),
                               delete_after=self.bot.ans_lifespan)
Ejemplo n.º 5
0
    async def admin_lock(self, ctx: commands.Context):
        """ Locks a channel's timer so no user can modify it.
            Unless they have permissions.
            This command either locks or unlocks, thus acting as a switch.
            Requires elevated permissions.
        """

        channel = lib.get_channel(ctx)
        interface = self.bot.get_interface(channel)

        if interface.spoofed is not None:
            channel = interface.spoofed

        if interface.locked:
            interface.locked = False

            await self.bot.say("Channel unlocked.",
                               delete_after=self.bot.ans_lifespan)
            lib.log(lib.get_author_name(ctx) + " unlocked the channel.",
                    channel_id=channel.id)
        else:
            interface.locked = True

            await self.bot.say("Channel locked.",
                               delete_after=self.bot.ans_lifespan)
            lib.log(lib.get_author_name(ctx) + " locked the channel.",
                    channel_id=channel.id)
Ejemplo n.º 6
0
    async def admin_sub(self, ctx: commands.Context, user_id: str,
                        channel_id=None):
        """ Forcefully subscribes a member to a timer.

        :param user_id: The ID of the user to subscribe
        :type user_id: str

        :param channel_id: The ID of the channel to subscribe the user to. If
            it's None or not provided, defaults to the channel this command was
            sent to.
        :type channel_id: str
        """

        if channel_id is None:
            channel_id = lib.get_channel(ctx).id

        server = lib.get_server(ctx)
        user = server.get_member(user_id)

        interface = self.bot.get_interface(server.get_channel(channel_id),
                                           False)
        author_name = lib.get_author_name(ctx, True)
        member_name = lib.get_name(user, True)
        if interface is None:
            lib.log("{} tried to subscribe {} to {}, "
                    "but the channel was not found or had no interface"
                    .format(author_name, member_name,  "this channel" if
                            channel_id is None else "channel with id=" +
                                                    channel_id),
                    channel_id=channel_id)
            await self.bot.say("Channel not found or invalid.",
                               delete_after=self.bot.ans_lifespan)
        elif user is None:
            lib.log("{} tried to forcefully subscribe an invalid member"
                    .format(author_name), channel_id=channel_id)
            await self.bot.say("User is invalid. Are you sure its his ID?",
                               delete_after=self.bot.ans_lifespan)
        else:
            if user in interface.subbed:
                await self.bot.say("User is already subscribed!",
                                   delete_after=self.bot.ans_lifespan)
                lib.log("{} tried to subscribe {} to {}, but user is already "
                        "subscribed".format(author_name, member_name,
                                            "this channel" if channel_id is None
                                            else "channel with id=" + channel_id
                                            ), channel_id=channel_id)
                return

            interface.add_sub(user, datetime.now())
            lib.log("{} forcefully subscribed {} to {}."
                    .format(author_name, member_name, "this channel" if
                            channel_id is None else "channel with id=" +
                                                    channel_id),
                    channel_id=channel_id)
            await self.bot.say("Member subscribed!",
                               delete_after=self.bot.ans_lifespan)
            await self.bot.say("{}, {} has subscribed you to this channel's "
                               "timer!".format(member_name, author_name),
                               delete_after=self.bot.ans_lifespan)
Ejemplo n.º 7
0
    async def timer_time(self, ctx: commands.Context):
        """ Gives the user the current period and time of the timer.
        """

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

        send = self.bot.get_interface(channel).timer.time(True)

        lib.log(send, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan * 2)
Ejemplo n.º 8
0
    async def timer_status(self, ctx: commands.Context):
        """ Tells whether the timer is stopped, running or paused,
            if it's correctly set up and if it will soon stop or pause.
        """

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

        send = self.bot.get_interface(channel).timer.show_status()

        lib.log(send, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan * 2)
Ejemplo n.º 9
0
    async def on_command_error(self, error, ctx: commands.Context):

        log = lib.get_author_name(ctx)
        send = None

        if isinstance(error, commands.CheckFailure):

            if str(error) == "timer not found":
                send = "No timer found for this channel."
                log += " tried to interact with a nonexistent timer."

            elif str(error) == "timer locked":
                send = "You are not allowed to modify this timer."
                log += " tried to modify a locked timer without permissions."

            elif str(error) == "no permissions" or str(error) == "not admin":
                send = "You do not have permission to do this!"
                log += (" tried to execute a command and failed, " +
                        "lacked permissions.")
            else:
                send = "Timers are not allowed in this channel."
                log += " tried to start a timer in a non-whitelisted channel."

        elif isinstance(error, commands.CommandNotFound):
            send = "Command not found: `" + ctx.invoked_with + "`."
            log += " tried to execute a nonexistent command: `{}`."\
                .format(ctx.invoked_with)

            alt = None
            for name, command in self.bot.commands.items():
                if ctx.invoked_with == name:
                    alt = name
                elif isinstance(command, commands.GroupMixin):
                    for sub_name, sub_command in command.commands.items():
                        if ctx.invoked_with == sub_name:
                            alt = name + " " + sub_name

            if alt is not None:
                send += " Did you mean `" + alt + "`?"

        elif isinstance(error, commands.CommandInvokeError):
            lib.log_cmd_stacktrace(error)
            return
        else:
            log = str(error)

        lib.log(log, channel_id=lib.get_channel_id(ctx), level=logging.WARN)
        await self.bot.safe_send(lib.get_channel(ctx),
                                 send,
                                 delete_after=self.bot.ans_lifespan)
Ejemplo n.º 10
0
    async def timer_resume(self, ctx: commands.Context):
        """ Resumes a paused timer.
        """

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

        if self.bot.get_interface(channel).timer.resume():
            await self.bot.run_timer(channel)
        else:
            lib.log("Unable to resume timer, stopped or already running.",
                    channel_id=channel.id)
            await self.bot.say("**grumble grumble.** The timer is " +
                               "stopped or already running, I can't " +
                               "resume that!",
                               delete_after=self.bot.ans_lifespan)
Ejemplo n.º 11
0
def unlocked_or_allowed(ctx: commands.Context) -> bool:
    """ Checks if a timer is unlocked, or if the author of the command
        has permissions to execute such command on a locked timer.

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

    :return: True if the command succeeds, else raises an exception.
    :raises: commands.CheckFailure: If the check fails.
        message : "timer locked"
    """

    if isinstance(ctx.bot, PomodoroBot) and \
       ctx.bot.is_locked(lib.get_channel(ctx)) and \
       not ctx.bot.has_permission(ctx.message.author):
        raise commands.CheckFailure(message="timer locked")
    return True
Ejemplo n.º 12
0
def channel_has_timer(ctx: commands.Context) -> bool:
    """ Checks if a channel has a valid timer set.

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

    :return: True if the command succeeds, else raises an exception.
    :raises: commands.CheckFailure: If the check fails.
        message : "timer not found"
    """

    if isinstance(ctx.bot, PomodoroBot):
        channel = ctx.bot.spoof(ctx.message.author, lib.get_channel(ctx))

        if ctx.bot.get_interface(channel).timer is not None:
            return True

    raise commands.CheckFailure(message="timer not found")
Ejemplo n.º 13
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()
Ejemplo n.º 14
0
    async def timer_stop(self, ctx: commands.Context):
        """ Stops the timer, if it's running.
            Resets the current period and time, but keeps the setup.
        """

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

        interface = self.bot.get_interface(channel)
        if interface.timer.stop():
            send = "Timer will stop soon."
            await self.bot.say(send, delete_after=interface.timer.step)

        else:
            await self.bot.remove_messages(channel)

            send = "Timer has stopped."
            await self.bot.say(send, tts=interface.tts)

        lib.log(send, channel_id=channel.id)
Ejemplo n.º 15
0
    async def admin_spoof(self, ctx: commands.Context, spoofed_id=None):
        """ Enables spoof-mode on a channel.
            Spoof mode allows users with permissions to modify another specified
            channel's timer from the one in which this command
            was executed.

            For example, if channel #session_1 has ID '249719010319532064'
            and someone executes '!spoof 249719010319532064' from #admin_area,
            all timer-related commands (except for setup) executed from
            #admin_area by members with permissions will either affect or give
            information of the timer in #session_1 instead.

        :param spoofed_id: The ID of the channel that instructions will be
            sent to.
        :type spoofed_id: str
        """

        channel = lib.get_channel(ctx)

        if channel.id == spoofed_id:
            await self.bot.say("How about no. " + spoofed_id,
                               delete_after=self.bot.ans_lifespan)
            return

        spoofed_channel = lib.get_server(ctx).get_channel(spoofed_id)

        if spoofed_id is not None:
            self.bot.get_interface(channel).spoofed = spoofed_channel

            send = "Now acting in channel " + spoofed_channel.name
            log = "Now acting as if in " + spoofed_channel.name

        elif self.bot.get_interface(channel).spoofed is not None:
            self.bot.get_interface(channel).spoofed = None

            send = "Now acting in current channel"
            log = "Spoofing now off"
        else:
            raise commands.MissingRequiredArgument

        await self.bot.say(send, delete_after=self.bot.ans_lifespan)
        lib.log(log, channel_id=channel.id)
Ejemplo n.º 16
0
    async def add_timer_period(self,
                               ctx: commands.Context,
                               period_info: str,
                               index='n'):
        """ Adds a period with the given information after the given index.

        :param period_info: The information of the period(s) you want to add,
            that must follow the same rules that the setup command requires.
            For example: `Study:30` will add a 30-minute period with the name
            Study.
        :param index: The index at which the period should be added,
            counting from `0` to `n`, where `n` is the current number of periods
            available. If the index given is negative, it will count backwards.
            Thus, if 0 is given, it will be added as the first period,
            and with `n` it will be added as the last one (using `-n` is
            the same as using 0).
            If a literal `n` is given, it will translate to whatever the amount
            of periods is currently.
        """

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

        interface = self.bot.get_interface(channel)
        timer = interface.timer

        amount = timer.add_periods(index, period_info)
        if amount == 0:
            await self.bot.say(
                "Could not add the period(s)."
                " Failed to parse the given information",
                delete_after=self.bot.ans_lifespan)
            return

        period_str = 'period' if amount == 1 else 'periods'

        if interface.timer.get_state() != State.STOPPED:
            await self.bot.edit_message(interface.list_message,
                                        timer.list_periods())

        await self.bot.say("Successfully added the new {}!".format(period_str),
                           delete_after=self.bot.ans_lifespan)
Ejemplo n.º 17
0
    async def admin_shutdown(self, ctx: commands.Context):
        """ Exits the program. Administrator only!
        """

        lib.log("Shutting down...")
        await self.bot.say("Hope I did well, bye!")

        for channel, timer in self.bot.valid_timers().items():
            if timer.get_state() != State.STOPPED:
                timer.stop()
                if lib.get_channel(ctx) != channel:
                    await self.bot.safe_send(
                        channel,
                        "I'm sorry, I have to go. See you later!"
                    )

                    await self.bot.remove_messages(channel)
        self.bot.unsub_all()

        await self.bot.logout()
Ejemplo n.º 18
0
    async def timer_superreset(self, ctx: commands.Context):
        """ Ignores all conditions and resets the channel's timer.
            Requires elevated permissions.
        """

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

        interface = self.bot.get_interface(channel)
        if interface.timer.get_state() == State.RUNNING:
            self.bot.timers_running -= 1
            await self.bot.update_status()

        await self.bot.remove_messages(channel)

        interface.timer = None

        lib.log("Successfully forced a reset on this channel's timer.",
                channel_id=channel.id)
        await self.bot.say("Timer has been force-reset",
                           delete_after=self.bot.ans_lifespan)
Ejemplo n.º 19
0
    async def timer_goto(self, ctx: commands.Context, period_idx):
        """ Skips to the n-th period, assuming the periods' indexes go
            from 1 to the amount of them.

        :param period_idx: The index of the period to start from, from 1 to n.
        :type period_idx: 'next' or int such that 1 <= period_idx <= n,
            n being the amount of periods set.
        """

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

        interface = self.bot.get_interface(channel)

        if period_idx == "next":
            idx = interface.timer.get_period(True) + 1
        else:
            try:
                idx = int(period_idx)
            except TypeError:
                raise commands.BadArgument

        label = interface.timer.goto(idx)

        if label is not None:
            log = send = "Moved to period number {!s} ({})".format(idx, label)

            if interface.timer.get_state() != State.STOPPED:
                await self.bot.edit_message(interface.list_message,
                                            interface.timer.list_periods())

                if interface.timer.get_state() == State.PAUSED:
                    await self.bot.edit_message(interface.time_message,
                                                interface.timer.time())
        else:
            log = "Invalid period number entered when trying goto command."
            send = "Invalid period number."

        lib.log(log, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan)
Ejemplo n.º 20
0
    async def toggle_countdown(self, ctx: commands.Context, toggle=None):
        """ Turns the timer's countdown setting on or off. If no state is
            specified, it will toggle it

        :param toggle: True, yes or on to turn the setting on. False, no or off
            to turn the setting off. If not specified, or None is given,
             it will toggle the setting.
        """
        author = ctx.message.author
        channel = self.bot.spoof(author, lib.get_channel(ctx))
        interface = self.bot.get_interface(channel)
        timer = interface.timer

        toggle = lib.to_boolean(toggle)
        if timer.countdown == toggle:
            return  # No need to edit it if it's the same.
        timer.toggle_countdown(toggle)

        await self.bot.edit_message(interface.time_message, timer.time())
        await self.bot.say(
            "Successfully toggled the countdown setting {}!".format(
                "on" if timer.countdown else "off"),
            delete_after=self.bot.ans_lifespan)
Ejemplo n.º 21
0
    async def timer_reset(self, ctx: commands.Context):
        """ Resets the timer setup.
        """

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

        interface = self.bot.get_interface(channel)
        if interface.timer.get_state() == State.STOPPED:
            interface.timer.set_state(None)

            interface.timer = None
            interface.time_message = None
            interface.list_message = None

            log = lib.get_author_name(ctx) + " reset the timer."
            send = "Successfully reset session configuration."
        else:
            log = (lib.get_author_name(ctx) + " tried resetting a timer that "
                   "was running or paused.")
            send = "Cannot do that while the timer is not stopped."

        lib.log(log, channel_id=channel.id)
        await self.bot.say(send, delete_after=self.bot.ans_lifespan)
Ejemplo n.º 22
0
    async def timer_tts(self, ctx: commands.Context, toggle: str = None):
        """ Sets the TTS option on or off for the channel.

        :param toggle: Whether to turn on or off the TTS option. If no option
            is provided, it will toggle it
        :type toggle: str
        """

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

        log = send = None

        if toggle is None:
            interface.tts = not interface.tts
            toggle = "ok"
        else:
            try:
                interface.tts = lib.to_boolean(toggle)

            except TypeError:
                toggle = None
                log = "TTS command failed, bad argument."
                send = ("I could not understand if you wanted to " +
                        "turn TTS on or off.")

        if toggle is not None:
            status = ("on" if interface.tts else "off")
            log = "TTS now " + status + " for this channel."
            send = "Text-to-speech now " + status + " for this channel."

        lib.log(log,
                channel_id=channel.id,
                level=logging.WARN if toggle is None else logging.INFO)
        await self.bot.say(send,
                           tts=interface.tts and toggle is not None,
                           delete_after=self.bot.ans_lifespan)
Ejemplo n.º 23
0
    async def timer_start(self, ctx: commands.Context, period_idx=1):
        """ Starts the timer with the recorded setup. The timer must be
            correctly set up and not running for it to work.

        :param period_idx: The index of the period to start from, from 1 to n.
        :type period_idx: int; 1 <= period_idx <= amount of periods
        """

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

        interface = self.bot.get_interface(channel)
        timer = interface.timer
        if timer.start():
            if not 0 < period_idx <= len(timer.periods):
                period_idx = 1

            try:
                if interface.restart_inactivity():
                    await self.bot.say(
                        "Timer has no subs. Will stop after"
                        " {} minutes unless someone subscribes!".format(
                            self.bot.timer_inactivity_allowed),
                        delete_after=self.bot.ans_lifespan)

                await self.bot.run_timer(channel, period_idx - 1)
            except discord.errors.HTTPException:
                await self.bot.say("@here\n"
                                   "Connection interrupted, please resume! (1)"
                                   )
                timer.pause()
        else:
            lib.log(lib.get_author_name(ctx) +
                    " tried to start a timer that was already running.",
                    channel_id=channel.id)
            await self.bot.say("This channel's timer is already running",
                               delete_after=self.bot.ans_lifespan)
Ejemplo n.º 24
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)