async def cmd_ladder(self, ctx, *args): if len(args) != 1: await ctx.message.add_reaction(Lang.CMDERROR) return embed = discord.Embed() entries = {} for uid in Storage().get(self)["ladder"]: member = discord.utils.get(ctx.guild.members, id=uid) points = Storage().get(self)["ladder"][uid] if points not in entries: entries[points] = [member] else: entries[points].append(member) values = [] keys = sorted(entries.keys(), reverse=True) place = 0 for el in keys: for user in entries[el]: values.append("**#{}:** {} - {}".format( place, el, get_best_username(Storage().get(self), user))) if len(values) == 0: await ctx.send("So far, nobody is on the ladder.") return embed.add_field(name="Ladder:", value="\n".join(values)) await ctx.send(embed=embed)
async def cmd_emoji(self, ctx, *args): # Delete emoji if len(args) == 1: if ctx.message.author.id in Storage().get(self)["emoji"]: del Storage().get(self)["emoji"][ctx.message.author.id] await ctx.message.add_reaction(Lang.CMDSUCCESS) Storage().save(self) else: await ctx.message.add_reaction(Lang.CMDERROR) return # Too many arguments if len(args) != 2: await ctx.message.add_reaction(Lang.CMDERROR) return emoji = args[1] try: await ctx.message.add_reaction(emoji) except HTTPException: await ctx.message.add_reaction(Lang.CMDERROR) return Storage().get(self)["emoji"][ctx.message.author.id] = emoji Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS)
def update_ladder(self, member, points): ladder = Storage().get(self)["ladder"] if member.id in ladder: ladder[member.id] = int( round(ladder[member.id] * 3 / 4 + points * 1 / 4)) else: ladder[member.id] = int(round(points * 3 / 4)) Storage().save(self)
async def role_update(self, ctx, *message_content): if len(message_content) > 0: Storage().get(self)['message']['content'] = " ".join( message_content) Storage().save(self) await self.update_role_management(ctx) await ctx.send(Lang.lang(self, 'role_update')) await utils.log_to_admin_channel(ctx)
async def get_init_msg(self): """Returns the role management init message or None if not set""" if self.has_init_msg_set(): channel = self.bot.get_channel( Storage().get(self)['message']['channel_id']) return await channel.fetch_message( Storage().get(self)['message']['message_id']) else: return None
def remove_reminder(self, reminder_id): """ Removes the reminder if in config :param reminder_id: the reminder ID """ if reminder_id in self.reminders: self.reminders[reminder_id].cancel() del (self.reminders[reminder_id]) if reminder_id in Storage().get(self)['reminders']: del (Storage().get(self)['reminders'][reminder_id]) Storage().save(self) logging.info("Reminder {} removed".format(reminder_id))
def __init__(self, bot): super().__init__(bot) bot.register(self, help.DefaultCategories.MISC) self.reminders = {} reminders_to_remove = [] for reminder_id in Storage().get(self)['reminders']: reminder = Storage().get(self)['reminders'][reminder_id] if not self.register_reminder(reminder['chan'], reminder['user'], reminder['time'], reminder_id, reminder['text'], True): reminders_to_remove.append(reminder_id) for el in reminders_to_remove: self.remove_reminder(el)
def register_reminder(self, channel_id: int, user_id: int, remind_time: datetime, reminder_id: int, text, is_restart: bool = False): """ Registers a reminder :param channel_id: The id of the channel in which the reminder was set :param user_id: The id of the user who sets the reminder :param remind_time: The remind time :param reminder_id: The reminder ID :param text: The reminder message text :param is_restart: True if reminder is restarting after bot (re)start :returns: True if reminder is registered, otherwise False """ if remind_time < datetime.now(): logging.debug("Attempted reminder {} in the past: {}".format( reminder_id, remind_time)) return False logging.info("Adding reminder {} for user with id {} at {}: {}".format( reminder_id, user_id, remind_time, text)) job_data = { 'chan': channel_id, 'user': user_id, 'time': remind_time, 'text': text, 'id': reminder_id } timedict = timers.timedict(year=remind_time.year, month=remind_time.month, monthday=remind_time.day, hour=remind_time.hour, minute=remind_time.minute) job = self.bot.timers.schedule(self.reminder_callback, timedict, repeat=False) job.data = job_data self.reminders[reminder_id] = job if not is_restart: Storage().get(self)['reminders'][reminder_id] = job_data Storage().save(self) return True
async def create_message_text(self, server_roles, ctx): """ Returns the message text for the role manage init message including the reactions and mod roles for the roles :param server_roles: the roles on the server :param ctx: The context of the used command to create the new message """ msg = "{}\n".format(Storage().get(self)['message']['content']) for rid in self.rc(): role = discord.utils.get(server_roles, id=rid) emote_msg = "" modrole_msg = "" if self.rc()[rid]['emoji']: emote_msg = Lang.lang( self, 'init_reaction', await utils.emojize(self.rc()[rid]['emoji'], ctx)) if self.rc()[rid]['modrole'] != 0: modrole = discord.utils.get(server_roles, id=self.rc()[rid]['modrole']) modrole_msg = Lang.lang(self, 'init_modrole', modrole.name) if emote_msg and modrole_msg: todo_part = "{}, {}".format(emote_msg, modrole_msg) elif emote_msg: todo_part = emote_msg elif modrole_msg: todo_part = modrole_msg else: todo_part = Lang.lang(self, 'init_admin') msg += "\n{} - {}".format(role.name, todo_part) return msg
async def status(self, msg): """ Called when the status command is invoked. """ embed = discord.Embed(title="Kwiss: question {}/{}".format( self.quizapi.current_question_index() + 1, len(self.quizapi))) embed.add_field(name="Category", value=self.quizapi.category_name(self.category)) embed.add_field(name="Difficulty", value=Difficulty.human_readable(self.difficulty)) embed.add_field(name="Mode", value="Points (Everyone answers)") embed.add_field(name="Initiated by", value=get_best_username(Storage().get(self.plugin), self.requester)) status = ":arrow_forward: Running" if self.state == Phases.REGISTERING: status = ":book: Signup phase" # status = ":pause_button: Paused" embed.add_field(name="Status", value=status) if self.ranked: embed.add_field(name="Ranked", value=":memo:") if self.debug: embed.add_field(name="Debug mode", value=":beetle:") if self.gecki: embed.add_field(name="Gecki", value="I'm in! 😍") await self.channel.send(embed=embed)
def embed(self, end=False, sort_by_points=False): embed = discord.Embed(title=Lang.lang(self.plugin, "results_title")) ladder = self.ladder(sort_by_points=sort_by_points) place = 0 for i in range(len(ladder)): user = ladder[i] if i == 0 or self._score[user] < self._score[ladder[i - 1]]: place += 1 # embed name = "**#{}** {}".format( place, get_best_username(Storage().get(self.plugin), user)) value = "Correct answers: {}".format(self._score[user]) if len(self) > 1: value = "{}\nScore: {}".format(value, self.calc_points(user)) embed.add_field(name=name, value=value) i += 1 if len(ladder) == 0: if end: embed.add_field(name="Nobody has scored!", value=" ") else: embed.add_field(name="**#1** Geckarbot", value="I won! :)") return embed
async def end(self): embed = self.score.embed() winners = [get_best_username(Storage().get(self.plugin), x) for x in self.score.winners()] # Übergangslösung points = self.score.points() for user in points: self.plugin.update_ladder(user, points[user]) msgkey = "quiz_end" if len(winners) > 1: msgkey = "quiz_end_pl" elif len(winners) == 0: msgkey = "quiz_end_no_winner" winners = utils.format_andlist(winners, ands=Lang.lang(self.plugin, "and"), emptylist=Lang.lang(self.plugin, "nobody")) msg = Lang.lang(self.plugin, msgkey, winners) if msg is None: await self.channel.send(embed=embed) elif embed is None: await self.channel.send(msg) else: await self.channel.send(msg, embed=embed) self.plugin.end_quiz(self.channel)
async def end(self): embed = self.score.embed() winners = [get_best_username(Storage().get(self.plugin), x) for x in self.score.winners()] msgkey = "quiz_end" if len(winners) > 1: msgkey = "quiz_end_pl" elif len(winners) == 0: msgkey = "quiz_end_no_winner" winners = utils.format_andlist(winners, ands=Lang.lang(self.plugin, "and"), emptylist=Lang.lang(self.plugin, "nobody")) msg = Lang.lang(self.plugin, msgkey, winners) if msg is None: await self.channel.send(embed=embed) elif embed is None: await self.channel.send(msg) else: await self.channel.send(msg, embed=embed) if self.ranked: for player in self.registered_participants: self.plugin.update_ladder(player, self.score.calc_points(player)) self.plugin.end_quiz(self.channel)
def __init__(self, bot): super().__init__(bot) self.can_reload = True bot.register(self, category="DSC") self.log = logging.getLogger("dsc") self._fill_rule_link() Storage().save(self)
async def cmd_react(self, ctx, *args): if len(args) != 1: await ctx.message.add_reaction(Lang.CMDERROR) return emoji = Storage().get(self)["emoji"].get(ctx.message.author.id) if emoji is None: emoji = Lang.CMDERROR await ctx.message.add_reaction(emoji)
async def cmd_del(self, ctx, *args): if len(args) != 2: await ctx.message.add_reaction(Lang.CMDERROR) return if not permChecks.check_full_access(ctx.message.author): await ctx.message.add_reaction(Lang.CMDERROR) return try: user = await commands.MemberConverter().convert(ctx, args[1]) except (commands.CommandError, IndexError): await ctx.message.add_reaction(Lang.CMDERROR) return ladder = Storage().get(self)["ladder"] if user.id in ladder: del ladder[user.id] Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS) else: await ctx.message.add_reaction(Lang.CMDNOCHANGE)
async def eval(self): """ Is called when the question is over. Evaluates scores and cancels the timer. :return: """ self.plugin.logger.debug("Ending question") # End timeout timer if self.current_question_timer is not None: try: self.current_question_timer.cancel() except utils.HasAlreadyRun: self.plugin.logger.warning("This should really, really not happen.") self.current_question_timer = None else: # We ran into a timeout and need to give that function time to communicate this fact await asyncio.sleep(1) if self.current_reaction_listener is not None: self.current_reaction_listener.unregister() question = self.quizapi.current_question() # Normalize answers for el in self.registered_participants: if len(self.registered_participants[el]) != 1: self.registered_participants[el] = None else: self.registered_participants[el] = self.registered_participants[el][0] # Increment scores correctly_answered = [] for user in self.registered_participants: if question.check_answer(self.registered_participants[user], emoji=True): correctly_answered.append(user) for user in correctly_answered: self.score.increase(user, self.current_question, totalcorr=len(correctly_answered)) correct = [get_best_username(Storage().get(self.plugin), el) for el in correctly_answered] correct = utils.format_andlist(correct, Lang.lang(self.plugin, "and"), Lang.lang(self.plugin, "nobody")) if self.config["emoji_in_pose"]: ca = question.correct_answer_emoji else: ca = question.correct_answer_letter await self.channel.send(Lang.lang(self.plugin, "points_question_done", ca, correct)) # Reset answers list for user in self.registered_participants: self.registered_participants[user] = [] await asyncio.sleep(self.config["question_cooldown"]) self.state = Phases.QUESTION
def __init__(self, *args, **kwargs): self.geck_cogs = [] self.guild = None self._plugins = [] super().__init__(*args, **kwargs) self.reaction_listener = reactions.ReactionListener(self) self.dm_listener = dmlisteners.DMListener(self) self.timers = timers.Mothership(self) self.ignoring = ignoring.Ignoring(self) self.helpsys = help.GeckiHelp(self) Lang().bot = self Config().bot = self Storage().bot = self
async def status(self, msg): embed = discord.Embed(title="Kwiss: question {}/{}".format( self.quizapi.current_question_index() + 1, len(self.quizapi))) embed.add_field(name="Category", value=self.quizapi.category_name(self.category)) embed.add_field(name="Difficulty", value=Difficulty.human_readable(self.difficulty)) embed.add_field(name="Mode", value="Rush (Winner takes it all)") embed.add_field(name="Initiated by", value=get_best_username(Storage().get(self.plugin), self.requester)) status = ":arrow_forward: Running" # status = ":pause_button: Paused" embed.add_field(name="Status", value=status) if self.debug: embed.add_field(name="Debug mode", value=":beetle:") await msg.add_reaction(Lang.CMDSUCCESS) await self.channel.send(embed=embed)
async def eval(self): """ Is called when the question is over. Evaluates scores and cancels the timer. :return: """ self.plugin.logger.debug("Ending question") question = self.quizapi.current_question() # Increment score self.score.increase(self.last_author, question) await self.channel.send(Lang.lang(self.plugin, "correct_answer", get_best_username(Storage().get(self.plugin), self.last_author), question.correct_answer_letter)) await asyncio.sleep(self.config["question_cooldown"]) self.state = Phases.QUESTION
async def user_bridge(self, ctx, user=None): discord_user = ctx.message.author.id # User-Verbindung entfernen if user is None: if discord_user in self.spaetzle_conf()["discord_user_bridge"]: del self.spaetzle_conf()["discord_user_bridge"][discord_user] await ctx.message.add_reaction(Lang.CMDSUCCESS) else: await ctx.send(self.spaetzle_lang('user_not_bridged')) return # User-Verbindung hinzufügen try: self.get_user_cell(user) self.spaetzle_conf()["discord_user_bridge"][ctx.message.author.id] = user Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS) except UserNotFound: await ctx.send(self.spaetzle_lang('user_not_found'))
async def about_to_start(self): """ ABOUTTOSTART -> QUESTION; ABOUTTOSTART -> ABORT """ self.plugin.logger.debug("Ending the registering phase") abort = False if len(self.registered_participants) == 0: abort = True if abort: embed, msg = self.plugin.end_quiz(self.channel) self.channel.send(msg, embed=embed) return else: for user in self.registered_participants: self.score.add_participant(user) embed = discord.Embed(title=Lang.lang(self.plugin, "quiz_phase")) value = "\n".join([get_best_username(Storage().get(self.plugin), el, mention=True) for el in self.registered_participants]) embed.add_field(name="Participants:", value=value) await self.channel.send(embed=embed) await asyncio.sleep(10) self.state = Phases.QUESTION
async def _dsc_save_state(self, ctx, new_state: DscState): Storage.get(self)['state'] = new_state Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS)
def has_init_msg_set(self): return (Storage().get(self)['message']['channel_id'] != 0 and Storage().get(self)['message']['message_id'] != 0)
def rc(self): """Returns the roles config""" return Storage().get(self)['roles']
async def update_role_management(self, ctx): """ Updates saved roles from server, removes not existing roles from config, remove not existing roles from init message and add new roles and their emojis and reactions to the init message. """ # Remove old roles current_server_roles = await self.bot.guild.fetch_roles() server_role_ids = [r.id for r in current_server_roles] removed_roles = deepcopy(self.rc()) for role_in_config in self.rc(): if role_in_config in server_role_ids: del (removed_roles[role_in_config]) # remove emojis and mod roles that aren't on server anymore if self.rc()[role_in_config]['modrole'] not in server_role_ids: self.rc()[role_in_config]['modrole'] = 0 if (self.rc()[role_in_config]['emoji'] and emoji.emoji_count( emoji.emojize(self.rc()[role_in_config]['emoji'], True)) < 1): for e in self.bot.emojis: if str(e) == self.rc()[role_in_config]['emoji']: break else: self.rc()[role_in_config]['emoji'] = "" for role_to_remove in removed_roles: del (self.rc()[role_to_remove]) # update message message_text = await self.create_message_text(current_server_roles, ctx) message = await self.get_init_msg() if message is not None: await message.edit(content=message_text) else: await utils.write_debug_channel( self.bot, Lang.lang(self, 'creating_init_msg')) channel = self.bot.get_channel( Storage().get(self)['message']['channel_id']) message = await channel.send(message_text) Storage().get(self)['message']['message_id'] = message.id self.bot.reaction_listener.register( message, self.update_reaction_based_user_role) # remove reactions w/o role for reaction in message.reactions: reaction_str = emoji.demojize(str(reaction), True) for role in self.rc(): if self.rc()[role]['emoji'] == reaction_str: break else: await message.clear_reaction(reaction) # add reactions for new roles for role_config in self.rc(): emoji_id = self.rc()[role_config]['emoji'] if not emoji_id: continue emote = await utils.emojize(emoji_id, ctx) await message.add_reaction(emote) Storage().save(self)
async def dsc_set_yt_link(self, ctx, link): link = utils.clear_link(link) Storage.get(self)['yt_link'] = link Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS)
async def dsc_set_date(self, ctx, date_str, time_str=None): if not time_str: time_str = "23:59" Storage.get(self)['state_end'] = datetime.strptime(f"{date_str} {time_str}", "%d.%m.%Y %H:%M") Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS)
async def dsc_set_status(self, ctx, *points): Storage.get(self)['points'] = "-".join(points) Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS)
async def dsc_set_status(self, ctx, *message): Storage.get(self)['status'] = " ".join(message) Storage().save(self) await ctx.message.add_reaction(Lang.CMDSUCCESS)