async def cmd_xproll(self, *args, member, channel, **_): target = member try: wsh = gc.open_by_key(CHAR_SHEET[str(target.id)]).sheet1 except: raise BotError("Impossible d'ouvrir la fiche de personnage du membre") ll = wsh.get_all_values() # type: List[List[str]] if len(ll[0]) < 13: raise BotError("La fiche de personnage doit au moins avoir une colonne 'M'") recap = [] to_update = {} for i, line in enumerate(ll): if line[12] == 'TRUE': # if column M == TRUE last_rec = xp_roll(line) recap.append(last_rec) if last_rec['success']: to_update[i + 1] = last_rec['new_xp'] if not recap: return await channel.send("Vous n'avez aucun jet d'XP à faire ...") await channel.send("```diff\n{}```".format('\n'.join( [( f"{'+' if d['success'] else '-'} {d['comp_name'][:16]:<16} {d['roll']:^3}/{d['old_total']:>3}" + ' | ' + (f"{d['old_total']:^3}->{d['new_total']:^3} (+{d['xp_won']}){' CRITIQUE' if d['crits'] else ''}" if d['success'] else 'Échoué')) for d in recap] ))) up = wsh.range(f"I1:I{len(ll)}") up = [gspread.Cell(cell.row, cell.col, to_update[cell.row]) for cell in up if cell.row in to_update] if up: wsh.update_cells(up) up = wsh.range(f"M1:M{len(ll)}") for cell in up: if cell.value == 'FALSE' or cell.value == 'TRUE': cell.value = False if up: wsh.update_cells(up)
async def cmd_mithrollversus(self, *args, message, content, member, channel, guild, **_): match = CMD_VERSUS_REGEX.match(content) if not match: raise InvalidArgs(f"The command content must match regular the regular expression\n``{CMD_VERSUS_REGEX.pattern}``") d = {k:v for k, v in match.groupdict().items() if v is not None} comp_atk = d['comp_atk'] atk_bonus = int(d.get('atk_bonus_sign', '+') + d.get('atk_bonus', '0')) comp_def = d.get('comp_def', comp_atk) def_bonus = int(d.get('def_bonus_sign', '+') + d.get('def_bonus', '0')) defenser = get_member(guild, d['def']) attacker = d.get('roller', None) attacker = member if attacker is None else get_member(guild, attacker) try: wsh1 = gc.open_by_key(CHAR_SHEET[str(attacker.id)]).sheet1 wsh2 = gc.open_by_key(CHAR_SHEET[str(defenser.id)]).sheet1 except: raise BotError("Impossible d'ouvrir la fiche de personnage du membre") datk = await roll_by_comp(parse_competences(wsh1), comp_atk.strip().lower(), atk_bonus) ddef = await roll_by_comp(parse_competences(wsh2), comp_def.strip().lower(), def_bonus) em = discord.Embed( title="Lancé de dés", description=f"{attacker.mention} **vs** {defenser.mention}", colour=attacker.colour ).set_footer(text=message.content).set_author(name=attacker.name, icon_url=attacker.avatar_url) em.add_field(name="Attaque", value=COMPROLL_DESC.format(**datk, member=attacker), inline=True) em.add_field(name="Défense", value=COMPROLL_DESC.format(**ddef, member=defenser), inline=True) em.add_field(name="Résultat", value=f"```diff\n{datk['verdict']}```**VS**```diff\n{ddef['verdict']}```", inline=False) if datk['verdict'] == "- Echec Critique": em.set_image(url=random_choice(FAIL_GIF)) elif datk['verdict'] == "+ Réussite Critique": em.set_image(url=random_choice(SUCCES_GIF)) await channel.send(embed=em)
async def cmd_mithroll(self, *args, message, channel, member, guild, content, **_): if '#' in content: content, target_query = content.split('#', 1) target = get_member(guild, target_query.strip()) else: target = member if not args: raise InvalidArgs("Usage: /mithroll {comp_name} [+/-][nombre]") try: wsh = gc.open_by_key(CHAR_SHEET[str(target.id)]).sheet1 except: raise BotError("Impossible d'ouvrir la fiche de personnage du membre") comp = parse_competences(wsh) re_result = re.search(r".*([+-])\s*(\d+)\s*$", content) if re_result: sign_char = re_result.group(1) name = content.split(sign_char, 1)[0] bonus = int(sign_char + re_result.group(2)) else: name, bonus = content, 0 d = await roll_by_comp(comp, name.strip().lower(), bonus) em = discord.Embed( title="Lancé de dés", description=COMPROLL_DESC.format(**d, member=member), colour=target.colour ).set_footer(text=message.content).set_author(name=target.name, icon_url=target.avatar_url) em.add_field(name="Résultat", value=f"```diff\n{d['verdict']}```") if d['verdict'] == "- Echec Critique": em.set_image(url=random_choice(FAIL_GIF)) elif d['verdict'] == "+ Réussite Critique": em.set_image(url=random_choice(SUCCES_GIF)) await channel.send(embed=em)
async def cmd_unvalidreport(self, *args, member, force, client, channel, **_): if not is_arbitre(member, client=client) and not force: raise Forbidden("You must be Arbitre for use this command") if not args: raise InvalidArgs("Command must take one argument") if not args[0].isdigit(): raise InvalidArgs("Argument must be a number") match = db.get_match(args[0]) if not match: raise NotFound("Match not found") if not match.validated: raise BotError("Match is already unvalided") db.unvalid_match(match) # update Players Stats database for i in match.report.players: db.unregister_plstats( i.id, match.report.gametype, i.position <= POSITION_REQUIRE_FOR_WIN[match.report.gametype]) # Verif if players are eligible to new roles civfr: nextcord.Guild = client.get_guild(CIVFR_GUILD_ID) tasks = [ recalc_role_for(civfr.get_member(i.id)) for i in match.report.players ] await asyncio.gather(*tasks) # Change embed validation_msg = await client.get_channel( REPORT_CHANNEL).fetch_message(match.check_msg_id) await validation_msg.edit(embed=match.to_embed(member.id)) await validation_msg.clear_reactions() await channel.send("Match invalidé.")
async def parse_vote_args(args, channel, member, message): if not args: members = get_member_in_channel(member.voice) else: try: members = get_member_in_channel(member.voice) except: members = [member] diff_members = message.mentions added = [] removed = [] for member in diff_members: if member in members: removed.append(member) members.remove(member) else: added.append(member) members.append(member) if removed: await channel.send( "The following player has been removed from the vote: " + ', '.join(i.mention for i in removed)) if added: await channel.send( "The following player has been added to the vote: " + ', '.join(i.mention for i in added)) if not members: raise BotError("Trying to run a vote without members") return members
async def cmd_validreport(self, *args, member, force, client, guild, channel, **_): if not is_arbitre(member, client=client) and not force: raise Forbidden("You must be Arbitre for use this command") if not args: raise InvalidArgs("Command must take one argument") if not args[0].isdigit(): raise InvalidArgs("Argument must be a number") r = await valid_report(int(args[0]), channel.id, guild, client, member) if r: raise BotError(r) else: await channel.send("Report validé de force")
def parse_competences(wsh : gspread.Worksheet): ll = wsh.get_all_values() # type: List[List[str]] comp = [] # type: List[Tuple[str, int, COMP_LEVEL]] for line in range(2, 10): comp.append((ll[line][COMP_NAME_COLUMN].strip().lower(), int(ll[line][COMP_SCORE_MAIN]), COMP_LEVEL.NORMAL)) comp_level = COMP_LEVEL.NORMAL line = 13 while ll[line][COMP_NAME_COLUMN] and ll[line][COMP_SCORE_XPABLE]: if not ll[line][COMP_SCORE_XPABLE].isnumeric(): try: comp_level = STR_TO_COMP_LEVEL[ll[line][COMP_SCORE_XPABLE]] except KeyError: raise BotError( f"Unexcepted value when parsing comp score, got \"{ll[line][COMP_SCORE_XPABLE]}\" at line {line} ({ll[line][COMP_NAME_COLUMN]})") else: comp.append((ll[line][COMP_NAME_COLUMN].strip().lower(), int(ll[line][COMP_SCORE_XPABLE]), comp_level)) line += 1 return comp