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
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)
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)
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)
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
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.")
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))
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))
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()
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)
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)