async def run_unschedule(self, context): """ Unschedule the event :param context: :return: """ user = User(context.message.author.id, context.guild.id, context) event = Event.get_by_guild(user.get_guild()) # Do they have the permissions to rename an event? self.check_permissions(context) # Make sure the event is running if event is None: return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:noexists', user.get_guild())) # Unschedule the event event.set_startdate(None) event.set_enddate(None) event.save() # Remove any tasks we already had saved for this event. Task.cancel('event', event.get_id()) return await context.send(user.get_mention() + ', ' + lib.get_string( 'event:unscheduled', user.get_guild()).format(event.get_title()))
async def run_end(self, context): """ Manually force the sprint to end (if the cron hasn't posted the message) and ask for final word counts :param context: :return: """ user = User(context.message.author.id, context.guild.id, context) sprint = Sprint(user.get_guild()) # If there is no active sprint, then just display an error if not sprint.exists(): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:noexists', user.get_guild())) # If they do not have permission to cancel this sprint, display an error if int(sprint.get_createdby()) != user.get_id() and context.message.author.permissions_in(context.message.channel).manage_messages is not True: return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:cannotend', user.get_guild())) # If the sprint hasn't started yet, it can't be ended. if not sprint.has_started(): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:notstarted', user.get_guild())) # Change the end reference to now, otherwise wpm calculations will be off, as it will use the time in the future when it was supposed to end. sprint.update_end_reference(int(time.time())) # Since we are forcing the end, we should cancel any pending tasks for this sprint Task.cancel('sprint', sprint.get_id()) # We need to set the bot into the sprint object, as we will need it when trying to get the guild object sprint.set_bot(self.bot) return await sprint.end(context)
async def run_delete(self, context): """ Delete the event on this server :param context: :return: """ user = User(context.message.author.id, context.guild.id, context) # Do they have the permissions to delete an event? self.check_permissions(context) # Check if there is an event running event = Event.get_by_guild(user.get_guild()) if event is None or not event.is_valid(): return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:noexists', user.get_guild())) # Make a fake prompt to wait for confirmation. argument = { 'prompt': lib.get_string('event:deletesure', user.get_guild()), 'check': lambda resp: resp.lower() in ('y', 'yes', 'n', 'no') } response = await self.prompt(context, argument, True) if not response: return response = response.content # If they confirm, then delete the event. if response.lower() in ('y', 'yes'): event.delete() # Remove any tasks we already had saved for this event. Task.cancel('event', event.get_id()) output = lib.get_string('event:deleted', user.get_guild()).format(event.get_title()) else: # Otherwise, just print 'OK' output = 'OK' await context.send(context.message.author.mention + ', ' + output)
def cancel(self, context): """ Cancel the sprint and notify the users who were taking part :return: """ # Load current user user = User(context.message.author.id, context.guild.id, context) # Delete sprints and sprint_users records self.__db.delete('sprint_users', {'sprint': self._id}) self.__db.delete('sprints', {'id': self._id}) # Delete pending scheduled tasks Task.cancel('sprint', self._id) # If the user created this, decrement their created stat if user.get_id() == self._createdby: user.add_stat('sprints_started', -1)
async def run_end(self, context): """ End the event now :param context: :return: """ user = User(context.message.author.id, context.guild.id, context) # Do they have the permissions to end an event? self.check_permissions(context) event = Event.get_by_guild(user.get_guild()) if event is None or not event.is_running(): return await context.send(user.get_mention() + ', ' + lib.get_string('event:err:noexists', user.get_guild())) event.set_context(context) event.set_guild_object(context.guild) # Remove any tasks we already had saved for this event. Task.cancel('event', event.get_id()) return await event.end()
async def run_declare(self, context, amount=None): """ Declare user's current word count for the sprint :param context: :param amount: :return: """ user = User(context.message.author.id, context.guild.id, context) sprint = Sprint(user.get_guild()) # If there is no active sprint, then just display an error if not sprint.exists(): return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:noexists', user.get_guild())) # If the user is not sprinting, then again, just display that error if not sprint.is_user_sprinting(user.get_id()): return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:notjoined', user.get_guild())) # If the sprint hasn't started yet, display error if not sprint.has_started(): return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:notstarted', user.get_guild())) # Get the user's sprint info user_sprint = sprint.get_user_sprint(user.get_id()) # If they joined without a word count, they can't add one. if user_sprint['sprint_type'] == Sprint.SPRINT_TYPE_NO_WORDCOUNT: return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:nonwordcount', user.get_guild())) # Did they enter something for the amount? if amount is None: return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:amount', user.get_guild())) # Are they trying to do a calculation instead of declaring a number? if amount[0] == '+' or amount[0] == '-': # Set the calculation variable to True so we know later on that it was not a proper declaration calculation = True # Convert the amount string to an int amount = int(amount) # Add that to the current word count, to get the new value new_amount = user_sprint['current_wc'] + amount else: calculation = False new_amount = amount # Make sure the amount is now a valid number if not lib.is_number(new_amount): return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:amount', user.get_guild())) # Just make sure the new_amount is defintely an int new_amount = int(new_amount) # If the declared value is less than they started with and it is not a calculation, then that is an error. if new_amount < int(user_sprint['starting_wc']) and not calculation: diff = user_sprint['current_wc'] - new_amount return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:err:wclessthanstart', user.get_guild( )).format(new_amount, user_sprint['starting_wc'], diff)) # Is the sprint finished? If so this will be an ending_wc declaration, not a current_wc one. col = 'ending' if sprint.is_finished() else 'current' # Before we actually update it, if the WPM is huge and most likely an error, just check with them if they meant to put that many words. written = new_amount - int(user_sprint['starting_wc']) seconds = int(sprint.get_end_reference()) - user_sprint['timejoined'] wpm = Sprint.calculate_wpm(written, seconds) # Does the user have a configured setting for max wpm to check? max_wpm = user.get_setting('maxwpm') if not max_wpm: max_wpm = self.WPM_CHECK if wpm > int(max_wpm): # Make a fake prompt to wait for confirmation. argument = { 'prompt': lib.get_string('sprint:wpm:sure', user.get_guild()).format(written, wpm), 'check': lambda resp: resp.lower() in ('y', 'yes', 'n', 'no') } response = await self.adhoc_prompt(context, argument, True) # If they confirm, then delete the event. if response is False or response.content.lower() in ('n', 'no'): return await context.send( user.get_mention() + ', ' + lib.get_string('sprint:declareagain', user.get_guild())) # Update the user's sprint record arg = {col: new_amount} sprint.update_user(user.get_id(), **arg) # Reload the user sprint info user_sprint = sprint.get_user_sprint(user.get_id()) # Which value are we displaying? wordcount = user_sprint['ending_wc'] if sprint.is_finished( ) else user_sprint['current_wc'] written = int(wordcount) - int(user_sprint['starting_wc']) await context.send(user.get_mention() + ', ' + lib.get_string( 'sprint:declared', user.get_guild()).format(wordcount, written)) # Is the sprint now over and has everyone declared? if sprint.is_finished() and sprint.is_declaration_finished(): Task.cancel('sprint', sprint.get_id()) await sprint.complete(context)
async def run_schedule(self, context): """ Schedule the event to start and end at a specific datetime :param context: :return: """ user = User(context.message.author.id, context.guild.id, context) event = Event.get_by_guild(user.get_guild()) # Do they have the permissions to rename an event? self.check_permissions(context) # Make sure the event is running if event is None: return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:noexists', user.get_guild())) # Make sure the event is running if event.is_running(): return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:alreadyrunning', user.get_guild())) # Do they have a timezone set in their user settings? user_timezone = user.get_setting('timezone') if user_timezone is None: return await context.send( user.get_mention() + ', ' + lib.get_string('event:err:timezonenotset', user.get_guild())) timezone = pytz.timezone(user_timezone) time = datetime.now(timezone).strftime('%H:%M:%S') offset = datetime.now(timezone).strftime('%z') # Print the pre-schedule information to check their timezone is correct. await context.send(user.get_mention() + ', ' + lib.get_string('event:preschedule', user.get_guild( )).format(user_timezone, time, offset)) # We now have various stages to go through, so we loop through the stages, ask the question and store the user input as the answer. answers = [] # Stage 1 - Start date answer = await self.run_stage_one(context) if not answer: return answers.append({'stage': 1, 'answer': answer}) # Stage 2 - Start time answer = await self.run_stage_two(context) if not answer: return answers.append({'stage': 2, 'answer': answer}) # Stage 3 - End date answer = await self.run_stage_three(context) if not answer: return answers.append({'stage': 3, 'answer': answer}) # Stage 4 - End time answer = await self.run_stage_four(context) if not answer: return answers.append({'stage': 4, 'answer': answer}) # Stage 5 - Confirmation answer = await self.run_stage_five(context, answers) if not answer: return answers.append({'stage': 5, 'answer': answer}) # Now run the checks to make sure the end date is later than start date, etc... check = await self.check_answers(context, answers) if not check: return # Now convert those start and end times to UTC timestamps start = datetime.strptime( lib.find(answers, 'stage', 1)['answer'] + ' ' + lib.find(answers, 'stage', 2)['answer'], '%d-%m-%Y %H:%M') end = datetime.strptime( lib.find(answers, 'stage', 3)['answer'] + ' ' + lib.find(answers, 'stage', 4)['answer'], '%d-%m-%Y %H:%M') adjusted_start = int(timezone.localize(start).timestamp()) adjusted_end = int(timezone.localize(end).timestamp()) # Schedule the event with those timestamps event.set_startdate(adjusted_start) event.set_enddate(adjusted_end) event.set_channel(context.message.channel.id) event.save() # Remove any tasks we already had saved for this event. Task.cancel('event', event.get_id()) # Schedule the tasks to run at those times. Task.schedule(Event.TASKS['start'], event.get_start_time(), 'event', event.get_id()) Task.schedule(Event.TASKS['end'], event.get_end_time(), 'event', event.get_id()) return await context.send( user.get_mention() + ', ' + lib.get_string('event:scheduled', user.get_guild()).format( event.get_title(), start, end))
async def run_declare(self, context, amount=None): """ Declare user's current word count for the sprint :param context: :param amount: :return: """ user = User(context.message.author.id, context.guild.id, context) sprint = Sprint(user.get_guild()) # If there is no active sprint, then just display an error if not sprint.exists(): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:noexists', user.get_guild())) # If the user is not sprinting, then again, just display that error if not sprint.is_user_sprinting(user.get_id()): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:notjoined', user.get_guild())) # If the sprint hasn't started yet, display error if not sprint.has_started(): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:notstarted', user.get_guild())) # Did they enter something for the amount? if amount is None: return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:amount', user.get_guild())) # Get the user's sprint info user_sprint = sprint.get_user_sprint(user.get_id()) # Are they trying to do a calculation instead of declaring a number? if amount[0] == '+' or amount[0] == '-': # Set the calculation variable to True so we know later on that it was not a proper declaration calculation = True # Convert the amount string to an int amount = int(amount) # Add that to the current word count, to get the new value new_amount = user_sprint['current_wc'] + amount else: calculation = False new_amount = amount # Make sure the amount is now a valid number if not lib.is_number(new_amount): return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:amount', user.get_guild())) # Just make sure the new_amount is defintely an int new_amount = int(new_amount) # If the declared value is less than they started with and it is not a calculation, then that is an error. if new_amount < int(user_sprint['starting_wc']) and not calculation: diff = user_sprint['current_wc'] - new_amount return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:wclessthanstart', user.get_guild()).format(new_amount, user_sprint['starting_wc'], diff)) # Is the sprint finished? If so this will be an ending_wc declaration, not a current_wc one. col = 'ending' if sprint.is_finished() else 'current' arg = {col: new_amount} # Update the user's sprint record sprint.update_user(user.get_id(), **arg) # Reload the user sprint info user_sprint = sprint.get_user_sprint(user.get_id()) # Which value are we displaying? wordcount = user_sprint['ending_wc'] if sprint.is_finished() else user_sprint['current_wc'] written = int(wordcount) - int(user_sprint['starting_wc']) await context.send(user.get_mention() + ', ' + lib.get_string('sprint:declared', user.get_guild()).format(wordcount, written)) # Is the sprint now over and has everyone declared? if sprint.is_finished() and sprint.is_declaration_finished(): Task.cancel('sprint', sprint.get_id()) await sprint.complete(context)