async def _price(self, ctx, *args): """ Permet de connaître le montant d'une grille de loto et de sa cagnotte actuelle. Usage : `!price` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Permet de connaître le montant d'une grille de loto et de sa cagnotte actuelle." ) args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Calculate price loto = LotoDraw.get_or_none(LotoDraw.date == date.today()) currency = self.get_currency(DISCORD_MONEY_SYMBOL) price = round( DISCORD_LOTO_PRICE + round(loto.value / DISCORD_LOTO_LIMIT, 1), 1) await ctx.author.send( f":game_die: Une grille de loto coûte **~{round(price,2):n} {currency.symbol}**.\n" f":money_bag: Le montant de la cagnotte est estimé à **~{round(loto.value,2):n} {currency.symbol}**." )
async def _seed(self, ctx, *args): """ Modifie la graine du générateur de nombres pseudo-aléatoire (admin uniquement). Usage : `!seed [<nombre>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Permet de modifier la graine du générateur de nombres pseudo-aléatoire." ) parser.add_argument('seed', type=int, nargs='?', help="Seed") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return if args.seed: self.seeds.append(args.seed) else: self.seeds.clear() seeds = ', '.join(map(str, self.seeds)) await ctx.author.send( f":game_die: Graine(s) configurée(s) : **{seeds or 'aucune'}**")
def __init__(self, grab, task, graph, spider=None): Parser.__init__(self, grab, task, graph, failonerror=False, spider=spider)
async def _rate(self, ctx, *args): """ Permet de consulter le taux d'une devise. Usage : `!rate <symbole>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de consulter le taux d'une devise.") parser.add_argument('symbol', type=str, help="Symbole de la devise") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check currency currency = self.get_currency(args.symbol) if not currency: await ctx.author.send( f":no_entry: La devise sélectionnée n'existe pas.") return # Get currency infos base = self.get_currency(DISCORD_MONEY_SYMBOL) total = Balance.select(pw.fn.SUM( Balance.value)).where(Balance.currency == currency).scalar() or 0.0 rate = round(currency.value * currency.rate / (total or 1), 5) # Display infos messages = [ f"**{currency.name}** ({currency.symbol}), créée par **{currency.user.name}**" if currency.user else f"**{currency.name}** ({currency.symbol}), devise de base générale", f"Nombre en circulation : **{round(total,2):n}**" ] if currency != base: messages.extend([ f"Taux actuel : **{round(currency.rate, 2):.0%}**", f"Valeur totale : **{round(currency.value,2):n} {base.symbol}**", f"Valeur individuelle : **{round(rate,2):n} {base.symbol}**" ]) messages.append( f"Classement des 10 plus grosses fortunes en **{currency.name}** :" ) balances = Balance.select(Balance, User).join(User).where( Balance.currency == currency, Balance.value > 0.001).order_by(Balance.value.desc()).limit(10) for indice, balance in zip(self.RANKS, balances): indice = self.get_icon(indice) if currency == base: messages.append( f"{indice} {balance.user.name} : **{round(balance.value,2):n} {currency.symbol}**" ) else: messages.append( f"{indice} {balance.user.name} : **{round(balance.value,2):n} {currency.symbol}** " f"soit **~{round(balance.value * rate,2):n} {base.symbol}**" ) await ctx.author.send("\n".join(messages))
async def _roles(self, ctx, *args): """ Permet de s'attribuer un ou plusieurs rôles. Usage : `!roles <role> [<role> ...]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Get roles list_roles = [r.split("=") for r in DISCORD_ROLES.split(",") ] if DISCORD_ROLES else [] help_roles = ",\n".join(f"- {rolename} ({shortcut})" for (shortcut, rolename) in list_roles) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de s'attribuer un ou plusieurs rôles.", epilog=f"Rôles disponibles :\n{help_roles}", formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('roles', metavar='role', type=str, nargs='*', help="Rôle") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Collect all allowed roles roles = {} for role in ctx.guild.roles: for shortcut, rolename in list_roles: if role.name.lower() == rolename.lower(): roles[shortcut] = role # Collect selected roles new_roles = [] selected_roles = map(str.lower, args.roles) for shortcut, role in roles.items(): if shortcut.lower() in selected_roles: new_roles.append(role) elif role.name.lower() in selected_roles: new_roles.append(role) if not new_roles: help_roles = ", ".join(f"**{rolename}** ({shortcut})" for (shortcut, rolename) in list_roles) await ctx.author.send( f":warning: Vous devez sélectionner un ou plusieurs rôles parmi : {help_roles}" ) return # Clear roles old_roles = list(roles.values()) await ctx.author.remove_roles(*old_roles) # Add roles await ctx.author.add_roles(*new_roles) role_names = ', '.join(role.name for role in new_roles) await ctx.author.send( f":scroll: Vous avez désormais accès aux rôles suivants : **{role_names}** !" )
async def _create(self, ctx, *args): """ Permet de créer une nouvelle devise. Usage : `!create <symbole> "<nom>" [<montant>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser(prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de créer une nouvelle devise.") parser.add_argument('symbol', type=str, help="Symbole de la devise") parser.add_argument('name', type=str, help="Nom de la devise") parser.add_argument('amount', type=int, nargs='?', help="Investissement initial") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Update balance if args.amount and args.amount < DISCORD_MONEY_CREATE: await ctx.author.send( f":no_entry: Vous devez investir au minimum **{DISCORD_MONEY_CREATE:n} {DISCORD_MONEY_SYMBOL}** " f"lors de la création de votre nouvelle devise.") return value = args.amount or DISCORD_MONEY_CREATE # Check balance base_currency = self.get_currency(DISCORD_MONEY_SYMBOL) balance = self.get_balance(user, base_currency) if balance.value < value: await ctx.author.send( f":no_entry: Vous n'avez pas assez d'argent sur votre compte : vous avez actuellement " f"**{round(balance.value,2):n} {base_currency.symbol}** " f"et il vous faut **{round(value,2):n} {base_currency.symbol}**." ) return balance.value -= value Balance.update(value=Balance.value - value).where(Balance.id == balance.id).execute() # Try create currency currency = self.get_currency(args.symbol, create=True, name=args.name, user=user, value=value) if currency.user != user: await ctx.author.send( f":no_entry: Cette devise ne vous appartient pas.") return await ctx.author.send( f":white_check_mark: Votre nouvelle devise **{args.name}** ({args.symbol}) a été créée avec succès !\n" f"Vous pouvez désormais en distribuer autant que vous le voulez avec `{ctx.prefix}give`, lui donner de la " f"valeur en l'approvisionnant avec `{ctx.prefix}store` et consulter son cours avec `{ctx.prefix}rate`." )
async def _open(self, ctx, *args): """ Ferme la soumission des candidatures et ouvre l'accès au vote pour un scrutin. Usage : `!open [--poll <poll_id>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Ferme la soumission des candidatures et ouvre l'accès au vote pour un scrutin." ) parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and votable polls polls = Poll.select().where(Poll.open_apply & ~Poll.open_vote) poll = await self.handle_poll(polls, args, ctx.author) if not poll: return channel = poll.channel or ctx.channel # Update poll poll.open_apply = False poll.open_vote = True poll.save(only=( 'open_apply', 'open_vote', )) # Assign letter to every candidate for i, candidate in enumerate( Candidate.select(Candidate, User).join(User).order_by(User.name.asc())): candidate.indice = self.INDICES[i] candidate.save(only=('indice', )) # Message to user/channel message = ( f":ballot_box: Les candidatures au scrutin **{poll}** (`{poll.id}`) " f"sont désormais fermées et les votes sont ouverts, vous pouvez voter en " f"utilisant la commande `{ctx.prefix}vote` et voir les candidats avec `{ctx.prefix}info` !" ) if channel and hasattr(channel, 'topic'): await channel.send(message) else: await ctx.author.send(message)
async def _info(self, ctx, *args): """ Permet de consulter la liste des candidats au scrutin. Usage : `!info [--poll <poll_id>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de consulter la liste des candidats au scrutin." ) parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and appliable polls polls = Poll.select() poll = await self.handle_poll(polls, args, ctx.author) if not poll: return # Build message message = [ f"Voici la liste des candidats actuels au scrutin **{poll}** (`{poll.id}`) :" ] for candidate in Candidate.select(Candidate, User).join(User).order_by( Candidate.indice.asc(), User.name.asc()): if poll.proposals: message.append( f"{self.get_icon(candidate.indice)} **{candidate.proposal}** (par {candidate.user.name})" ) else: message.append( f"{self.get_icon(candidate.indice)} **{candidate.user.name}**" ) message = '\n'.join(message) # Send message is_admin = any(role.name == DISCORD_ADMIN for role in ctx.author.roles) if is_admin and hasattr(ctx.channel, 'name'): channel = poll.channel or ctx.channel await channel.send(message) else: await ctx.author.send(message)
async def _money(self, ctx, *args): """ Permet de consulter votre compte en banque. Usage : `!money [<utilisateur>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de consulter votre compte en banque.") parser.add_argument('user', type=str, nargs='?', help="Utilisateur") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check user target = await self.get_user(args.user) if args.user and not target: await ctx.author.send( f":no_entry: L'utilisateur ciblé n'existe pas.") return # Display infos if target: messages = [f"**{target.name}** a actuellement :"] else: messages = ["Vous avez actuellement :"] target = user balances = Balance.select(Balance, Currency).join(Currency).where( Balance.user == target, Balance.value > 0.001).order_by(pw.fn.Lower(Currency.name)) for balance in balances: messages.append( f"> **{round(balance.value,2):n} {balance.currency.symbol}** ({balance.currency.name})" ) chunks, remaining = [], 2000 for message in messages: length = len(message) + 1 if length > remaining: await ctx.author.send("\n".join(chunks)) chunks, remaining = [], 2000 chunks.append(message) remaining -= length if chunks: await ctx.author.send("\n".join(chunks))
async def _rename(self, ctx, *args): """ Permet de renommer une devise existante. Usage : `!rename <symbole> "<nom>"` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser(prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de créer une nouvelle devise.") parser.add_argument('symbol', type=str, help="Symbole de la devise") parser.add_argument('name', type=str, help="Nom de la devise") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check currency currency = self.get_currency(args.symbol) if currency.user != user: await ctx.author.send( f":no_entry: Cette devise ne vous appartient pas.") return # Change name if needed if currency.name != args.name: currency.name = args.name currency.save(only=('name', )) await ctx.author.send( f":white_check_mark: Vous avez renommé votre devise **{currency.name}** ({currency.symbol}) avec succès !" )
async def _store(self, ctx, *args): """ Permet d'alimenter une devise pour augmenter sa valeur. Usage : `!store <symbole> <montant>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Permet d'alimenter une devise pour augmenter sa valeur.") parser.add_argument('symbol', type=str, help="Symbole de la devise") parser.add_argument('amount', type=float, help="Quantité d'argent") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check positive if not args.amount > 0: await ctx.author.send( f":no_entry: La quantité ne peut être négative ou nulle.") return # Check currency currency = self.get_currency(args.symbol) if not currency: await ctx.author.send( f":no_entry: La devise sélectionnée n'existe pas.") return # Check ownership if not currency.user: await ctx.author.send( f":no_entry: Il n'est pas possible d'alimenter cette devise.") return # Check balance base = self.get_currency(DISCORD_MONEY_SYMBOL) balance = self.get_balance(user, base) if balance.value < args.amount: await ctx.author.send( f":no_entry: Vous n'avez pas assez d'argent sur votre compte : vous avez actuellement " f"**{round(balance.value,2):n} {currency.symbol}** " f"et il vous faut **{round(args.amount,2):n} {currency.symbol}**." ) return # Transfert money balance.value -= args.amount Balance.update(value=Balance.value - args.amount).where(Balance.id == balance.id).execute() currency.value += args.amount Currency.update(value=Currency.value + args.amount).where( Currency.id == currency.id).execute() await ctx.author.send( f":white_check_mark: Vous avez transféré **{args.amount:n} {base.symbol}** ({base.name}) sur la devise " f"**{currency.name}** ({currency.symbol}) ! Valeur totale : **{round(currency.value,2):n} {base.symbol}**." )
async def _delete(self, ctx, *args): """ Permet de supprimer une devise créée. Usage : `!delete <symbole>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de supprimer une devise créée.", epilog="Attention ! La suppression d'une devise est définitive " "et ses investissements ne seront pas remboursés.") parser.add_argument('symbol', type=str, help="Symbole de la devise") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check currency currency = self.get_currency(args.symbol) if not currency: await ctx.author.send( f":no_entry: La devise sélectionnée n'existe pas.") return if currency.user != user: await ctx.author.send( f":no_entry: Cette devise ne vous appartient pas.") return # Delete balances and currency Balance.delete().where(Balance.currency == currency).execute() currency.delete_instance() # Empty caches self.currencies.clear() self.balances.clear() await ctx.author.send( f":white_check_mark: La devise **{currency.name}** ({currency.symbol}) a été supprimée avec succès !" )
async def _new(self, ctx, *args): """ Permet de créer un nouveau scrutin et l'ouvre aux candidatures. Usage : `!new <name> [--winners <count> --proposals]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Permet de créer un nouveau scrutin et l'ouvre aux candidatures.") parser.add_argument('name', type=str, help="Nom du scrutin") parser.add_argument('--winners', '-w', type=int, help="Nombre de vainqueurs") parser.add_argument('--proposals', '-p', action='store_true', help="Propositions ?") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Create new poll poll = Poll.create(name=args.name, winners=args.winners or 1, proposals=args.proposals) # Message to user/channel message = ( f":ballot_box: Le scrutin **{poll}** (`{poll.id}`) a été créé et ouvert aux candidatures, " f"vous pouvez utiliser la commande `{ctx.prefix}apply` pour vous présenter (ou `{ctx.prefix}leave` pour vous retirer) !" ) if hasattr(ctx.channel, 'name'): # Save channel for announcements poll.channel_id = ctx.channel.id poll.save(only=('channel_id', )) await ctx.channel.send(message) else: await ctx.author.send(message)
async def _pass(self, ctx, *args): """ Définit un mot de passe pour pouvoir voter anonymement aux scrutins. Usage : `!pass <password>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Définit un mot de passe pour pouvoir voter anonymement aux scrutins." ) parser.add_argument('password', type=str, help="Mot de passe (pour l'anonymat)") parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and appliable polls polls = Poll.select().where(Poll.open_apply | Poll.open_vote) poll = await self.handle_poll(polls, args, ctx.author) if not poll: return # Encoding and saving password for the user password, created = Password.get_or_create( poll=poll, user=user, defaults=dict(password=self.hash(args.password))) if not created: # If user already has a password await ctx.author.send( ":no_entry: Vous avez déjà défini un mot de passe pour ce scruting." ) return await ctx.author.send( f":white_check_mark: Votre mot de passe de scrutin a été défini avec succès." )
async def _apply(self, ctx, *args): """ Permet de postuler en tant que candidat au scrutin avec ou sans proposition. Usage : `!apply [--poll <poll_id> --proposal <text>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Permet de postuler en tant que candidat au scrutin avec ou sans proposition." ) parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") parser.add_argument( '--proposal', '-P', type=str, help="Texte de la proposition (si autorisé par le scrutin)") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and appliable polls polls = Poll.select().where(Poll.open_apply & ~Poll.open_vote) poll = await self.handle_poll(polls, args, ctx.author) if not poll: return channel = poll.channel or ctx.channel # Create candidate if poll.proposals: if not args.proposal: await ctx.author.send( f":no_entry: Ce scrutin nécessite que vous ajoutiez une proposition à votre candidature, " f"vous pouvez le faire en utilisant le paramètre `--proposal \"<proposition>\"`." ) return candidate, created = Candidate.get_or_create( user=user, poll=poll, proposal=args.proposal) if created: await ctx.author.send( f":white_check_mark: Votre proposition **{args.proposal}** " f"(`{candidate.id}`) au scrutin de **{poll}** (`{poll.id}`) a été enregistrée !" ) if channel and hasattr(channel, 'topic'): await channel.send( f":raised_hand: <@{user.id}> a ajouté la proposition **{args.proposal}** " f"(`{candidate.id}`) au scrutin de **{poll.name}** (`{poll.id}`) !" ) return await ctx.author.send( f":no_entry: Vous avez déjà ajouté la proposition **{args.proposal}** " f"(`{candidate.id}`) à l'élection de **{poll}** (`{poll.id}`) !" ) else: candidate, created = Candidate.get_or_create(user=user, poll=poll) if created: await ctx.author.send( f":white_check_mark: Vous avez postulé avec succès en tant " f"que candidat au scrutin de **{poll}** (`{poll.id}`) !") if channel and hasattr(channel, 'topic'): await channel.send( f":raised_hand: <@{user.id}> se porte candidat " f"au scrutin de **{poll.name}** (`{poll.id}`) !") return await ctx.author.send( f":no_entry: Vous êtes déjà candidat à l'élection de **{poll}** (`{poll.id}`) !" )
async def _loto(self, ctx, *args): """ Permet d'enregistrer une participation au tirage du loto du jour. Usage : `!loto <nombre> <nombre> <nombre> <nombre> <nombre>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description= "Permet d'enregistrer une participation au tirage du loto du jour." ) parser.add_argument('numbers', metavar='number', type=int, nargs=DISCORD_LOTO_COUNT, help=f"Numéros du tirage (entre 1 et 49)") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check numbers numbers = sorted(set(args.numbers)) if len(numbers) != DISCORD_LOTO_COUNT or not all(1 <= n <= 49 for n in numbers): await ctx.author.send( f":no_entry: Vous devez sélectionner **{DISCORD_LOTO_COUNT} numéros distincts** " f"ayant une valeur comprise **entre 1 et 49**.") return # Check loto loto = LotoDraw.get_or_none(LotoDraw.date == date.today()) if not loto: await ctx.author.send( f":no_entry: Il n'y a pas encore de tirage LOTO prévu pour aujourd'hui. " f"Veuillez patienter jusqu'à ce que le tirage de la veille soit réalisé." ) return # Check balance currency = self.get_currency(DISCORD_MONEY_SYMBOL) balance = self.get_balance(user, currency) price = round( DISCORD_LOTO_PRICE + round(loto.value / DISCORD_LOTO_LIMIT, 1), 1) if balance.value < price: await ctx.author.send( f":no_entry: Vous n'avez pas assez d'argent sur votre compte : une grille coûte " f"**{round(price,2):n} {currency.symbol}** et vous n'avez actuellement que " f"**{round(balance.value,2):n} {currency.symbol}**).") return # Pay and create grid balance.value -= price Balance.update(value=Balance.value - price).where(Balance.id == balance.id).execute() grid = LotoGrid.create(user=user, draw=' '.join(map(str, numbers))) # Display information draw = ' - '.join(f"{d:02}" for d in numbers) for i in range(10): draw = draw.replace(str(i), self.get_icon(str(i))) await ctx.author.send( f":white_check_mark: Vous avez acheté avec succès une grille pour le tirage du " f"**{grid.date:%A %d %B %Y}** avec les numéros suivants : **{draw}**" )
async def _leave(self, ctx, *args): """ Permet de retirer sa candidature au scrutin. Usage : `!leave [--poll <poll_id>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de retirer sa candidature au scrutin.") parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") parser.add_argument('--proposal', '-P', type=int, help="Identifiant de la proposition") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and appliable polls polls = Poll.select().where(Poll.open_apply & ~Poll.open_vote) poll = await self.handle_poll(polls, args, ctx.author) if not poll: return channel = poll.channel or ctx.channel # Delete candidate if poll.proposals: if not args.proposal: await ctx.author.send( f":no_entry: Vous devez fournir l'identifiant de la " f"proposition à retirer à l'aide du paramètre `--proposal <id>`." ) return candidate = Candidate.get_or_none(user=user, poll=poll, id=args.proposal) if candidate: candidate.delete_instance() await ctx.author.send( f":white_check_mark: Vous avez retiré avec succès votre proposition " f"**{candidate.proposal}** au scrutin de **{poll}** (`{poll.id}`) !" ) if channel and hasattr(channel, 'topic'): await channel.send( f":door: <@{user.id}> retire sa proposition **{candidate.proposal}** " f"au scrutin de **{poll}** (`{poll.id}`) !") return await ctx.author.send( f":no_entry: Vous n'avez pas cette proposition à l'élection de **{poll}** (`{poll.id}`) !" ) else: candidate = Candidate.get_or_none(user=user, poll=poll) if candidate: candidate.delete_instance() await ctx.author.send( f":white_check_mark: Vous vous êtes retiré avec succès en tant " f"que candidat à l'élection de **{poll}** !") if channel and hasattr(channel, 'topic'): await channel.send( f":door: <@{user.id}> se retire en tant que candidat l'élection de **{poll}** !" ) return await ctx.author.send( f":no_entry: Vous n'êtes pas candidat à l'élection de **{poll}** (`{poll.id}`) !" )
async def _slot(self, ctx, *args): """ Joue une quantité d'argent à la machine à sous. Usage : `!slot <montant> [<symbole>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Joue une quantité d'argent à la machine à sous.") parser.add_argument('amount', type=int, help="Quantité d'argent") parser.add_argument('symbol', type=str, nargs='?', help="Symbole de la devise") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check positive if not args.amount > 0: await ctx.author.send( f":no_entry: La quantité ne peut être négative ou nulle.") return # Check currency currency = self.get_currency(args.symbol or DISCORD_MONEY_SYMBOL) if not currency: await ctx.author.send( f":no_entry: La devise sélectionnée n'existe pas.") return if currency.user == user: await ctx.author.send( f":no_entry: Cette devise vous appartient, vous ne pouvez pas la jouer." ) return # Check balance balance = self.get_balance(user, currency) if balance.value < args.amount: await ctx.author.send( f":no_entry: Vous n'avez pas assez d'argent sur votre compte : vous avez actuellement " f"**{round(balance.value,2):n} {currency.symbol}** " f"et il vous faut **{round(args.amount,2):n} {currency.symbol}**." ) return # Place the bet balance.value -= args.amount Balance.update(value=Balance.value - args.amount).where(Balance.id == balance.id).execute() # Play the slots slots = { 1: ':apple:', 2: ':tangerine:', 3: ':lemon:', 4: ':four_leaf_clover:', 5: ':bell:', 6: ':gem:' } multipliers = { (1, 1, 1): 2.0, (2, 2, 2): 3.0, (3, 3, 3): 4.0, (4, 4, 4): 5.0, (5, 5, 5): 10.0, (6, 6, 6): 15.0 } values = list(slots.keys()) seed(self.seeds.pop(0) if self.seeds else None) results = choice(values), choice(values), choice(values) result = args.amount * multipliers.get( results, 1.0 if len(set(results)) < len(results) else 0.0) if result: balance.value += result Balance.update(value=Balance.value + result).where(Balance.id == balance.id).execute() # Add loss to loto if not result: value = args.amount if currency.symbol != DISCORD_MONEY_SYMBOL: total = Balance.select(pw.fn.SUM(Balance.value)).where( Balance.currency == currency).scalar() or 0.0 value = round( args.amount * (currency.value * currency.rate / (total or 1)), 5) # Reduce value of currency subvalue = args.amount * (currency.value / (total or 1)) currency.value -= subvalue Currency.update(value=Currency.value - subvalue).where( Currency.id == currency.id).execute() LotoDraw.update(value=LotoDraw.value + value).where( LotoDraw.date == date.today()).execute() # Create display message slot1, slot2, slot3 = sorted(results, reverse=True) messages = [ "C'est parti !", f"{slots[slot1]}", f"{slots[slot2]}", f"{slots[slot3]}" ] if ctx.channel and hasattr(ctx.channel, 'name'): endpoint = ctx.channel if result > args.amount: messages.append( f"<@{user.id}> a remporté **{round(result,2):n} {currency.symbol}** ! :smile:" ) elif result: messages.append( f"<@{user.id}> a récupéré sa mise de **{round(result,2):n} {currency.symbol}**. :slight_smile:" ) else: messages.append( f"<@{user.id}> a perdu **{round(args.amount,2):n} {currency.symbol}** ! :frowning:" ) else: endpoint = ctx.author if result > args.amount: messages.append( f"Vous remportez **{round(result,2):n} {currency.symbol}** ! :smile:" ) elif result: messages.append( f"Vous récupérez votre mise de **{round(result,2):n} {currency.symbol}** ! :slight_smile:" ) else: messages.append( f"Vous perdez **{round(args.amount,2):n} {currency.symbol}** ! :frowning:" ) # Display slot machine message = await endpoint.send(messages[0]) for i in range(1, len(results) + 1): for value in sample(values, len(values)): content = ' '.join(messages[:i] + [slots[value]]) await message.edit(content=content) await asyncio.sleep(0.5) content = ' '.join(messages) await message.edit(content=content)
async def _buy(self, ctx, *args): """ Permet d'acheter une quantité d'une devise quelconque au taux actuel Usage : `!buy <nombre> <symbol>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Joue une quantité d'argent à la machine à sous.") parser.add_argument('amount', type=int, help="Quantité d'argent") parser.add_argument('symbol', type=str, help="Symbole de la devise") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check positive if not args.amount > 0: await ctx.author.send( f":no_entry: La quantité ne peut être négative ou nulle.") return # Check currency base_currency = self.get_currency(DISCORD_MONEY_SYMBOL) currency = self.get_currency(args.symbol) if not currency: await ctx.author.send( f":no_entry: La devise sélectionnée n'existe pas.") return if currency.user == user: await ctx.author.send( f":no_entry: Cette devise vous appartient, vous ne pouvez pas en acheter." ) return if not currency.user: await ctx.author.send( f":no_entry: La devise principale (**{base_currency.name}**) ne peut être achetée." ) # Get currency rate total = Balance.select(pw.fn.SUM( Balance.value)).where(Balance.currency == currency).scalar() or 0.0 value = round( args.amount * (currency.value * currency.rate / (total or 1)), 5) rate = round(args.amount / (total + args.amount), 2) if total + args.amount else 0.0 rate = max(0.0, min(rate, currency.rate)) # Check balance base_balance = self.get_balance(user, base_currency) if base_balance.value < value: await ctx.author.send( f":no_entry: Vous n'avez pas assez d'argent sur votre compte : vous avez actuellement " f"**{round(base_balance.value,2):n} {currency.symbol}** " f"et il vous faut **{round(value,2):n} {currency.symbol}**.") return # Update balance base_balance.value -= value Balance.update(value=Balance.value - value).where(Balance.id == base_balance.id).execute() balance = self.get_balance(user, currency) balance.value += args.amount Balance.update(value=Balance.value + args.amount).where(Balance.id == balance.id).execute() # Update currency currency.value += value currency.rate -= rate Currency.update( value=Currency.value + value, rate=Currency.rate - rate, ).where(Currency.id == currency.id).execute() # Message to user await ctx.author.send( f":moneybag: Vous avez acheté **{args.amount:n} {currency.symbol}** ({currency.name}) " f"pour une valeur de **{round(value,2):n} {base_currency.symbol}** ({base_currency.name}) !" )
async def _market(self, ctx, *args): """ Permet de consulter l'ensemble des devises existantes. Usage : `!market [<utilisateur>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de consulter l'ensemble des devises existantes." ) parser.add_argument('user', type=str, nargs='?', help="Utilisateur") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Check user target = await self.get_user(args.user) if args.user and not target: await ctx.author.send( f":no_entry: L'utilisateur ciblé n'existe pas.") return # Display infos base = self.get_currency(DISCORD_MONEY_SYMBOL) messages = [ f"Voici les devises créées par **{target.name}** :" if target else "Voici toutes les devises existantes :" ] currencies = (Currency.select( Currency, User, pw.fn.SUM(Balance.value).alias('total')).join( User, pw.JOIN.LEFT_OUTER)).switch(Currency).join( Balance, pw.JOIN.LEFT_OUTER).group_by(Currency).order_by( pw.fn.Lower(Currency.name)) if target: currencies = currencies.where(Currency.user == target) for currency in currencies: total = currency.total or 0 value = (currency.value * currency.rate) / (total or 1) if currency.user: if target: messages.append( f"> **{currency.name}** ({currency.symbol}) avec " f"**{round(total, 2):n}** unités en circulation d'une valeur de " f"**{round(value, 2):n} {base.symbol}** (taux: {round(currency.rate,2):.0%})" ) else: messages.append( f"> **{currency.name}** ({currency.symbol}) créée par **{currency.user.name}** avec " f"**{round(total,2):n}** unités en circulation d'une valeur de " f"**{round(value,2):n} {base.symbol}** (taux: {round(currency.rate,2):.0%})" ) else: messages.append( f"> **{currency.name}** ({currency.symbol}) devise principale avec " f"**{round(total, 2):n}** unités en circulation") chunks, remaining = [], 2000 for message in messages: length = len(message) + 1 if length > remaining: await ctx.author.send("\n".join(chunks)) chunks, remaining = [], 2000 chunks.append(message) remaining -= length if chunks: await ctx.author.send("\n".join(chunks))
async def _close(self, ctx, *args): """ Ferme le vote à un scrutin et affiche les résultats. Usage : `!close [--poll <poll_id>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Ferme le vote à un scrutin et affiche les résultats.") parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and votable polls polls = Poll.select().where(~Poll.open_apply & Poll.open_vote) poll = await self.handle_poll(polls, args, ctx.author) if not poll: return channel = poll.channel or ctx.channel # Update poll poll.open_apply = False poll.open_vote = False poll.save(only=( 'open_apply', 'open_vote', )) # Compute results self.get_results(poll, save=True) # Display winners votes = Vote.select( Vote.id).where(Vote.poll == poll).count() # Count total votes candidates = Candidate.select(Candidate.id).where( Candidate.poll == poll).count() # Count total candidates winners = Candidate.select(Candidate, User).join(User).where( Candidate.poll == poll, Candidate.winner).order_by(Candidate.proposal.asc(), User.name.asc()) winners = ', '.join([ f"{self.get_icon(winner.indice)} **{winner.proposal}** (par <@{winner.user_id}>)" if poll.proposals else f"{self.get_icon(winner.indice)} <@{winner.user_id}>" for winner in winners ]) message = ( f":trophy: Les élections de **{poll}** sont désormais terminées, " f"il y a eu **{votes}** votes pour **{candidates}** candidatures. " f"Merci à tous pour votre participation !\n") if poll.winners > 1: message += f"Les vainqueurs sont : {winners} ! Félicitations !" else: message += f"Le vainqueur est : {winners} ! Félicitations !" if channel and hasattr(channel, 'topic'): await channel.send(message) else: await ctx.author.send(message)
def __init__(self, grab, task, graph, spider=None): Parser.__init__(self, grab, task, graph, spider=spider) self.dbpedia = Graph(SPARQLStore(config.sparqlstore['dbpedia_url'], context_aware=False), namespace_manager=self.graph.namespace_manager)
async def _give(self, ctx, *args): """ Permet de donner de l'argent à un autre utilisateur. Usage : `!give <montant> <symbole> <utilisateur>` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser( prog=f'{ctx.prefix}{ctx.command.name}', description="Permet de donner de l'argent à un autre utilisateur.") parser.add_argument('amount', type=int, help="Quantité d'argent") parser.add_argument('symbol', type=str, help="Symbole de la devise") parser.add_argument('user', type=str, help="Utilisateur") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return if not args.amount > 0: await ctx.author.send( f":no_entry: La quantité ne peut être négative ou nulle.") return if args.amount > DISCORD_MONEY_LIMIT: await ctx.author.send( f":no_entry: Il n'est pas possible d'échanger plus de " f"**{round(DISCORD_MONEY_LIMIT,2):n} unités** d'une même devise en une seule fois." ) return # Check currency currency = self.get_currency(args.symbol) if not currency: await ctx.author.send( f":no_entry: La devise sélectionnée n'existe pas.") return # Check target target = await self.get_user(args.user) if not target or target.user.bot or target == user or target == currency.user: await ctx.author.send( f":no_entry: Le destinataire n'est pas valide.") return # Check balance if currency.user != user: source = self.get_balance(user, currency) if source.value < args.amount: await ctx.author.send( f":no_entry: Vous n'avez pas assez d'argent sur votre compte : vous avez actuellement " f"**{round(source.value, 2):n} {currency.symbol}** " f"et il vous faut **{round(args.amount, 2):n} {currency.symbol}**." ) return source.value -= args.amount Balance.update(value=Balance.value - args.amount).where( Balance.id == source.id).execute() # Decrease currency rate if currency.user: currency.rate = max(DISCORD_MONEY_MINI, currency.rate * DISCORD_MONEY_RATE) Currency.update(rate=currency.rate).where( Currency.id == currency.id).execute() # Give money balance = self.get_balance(target, currency) balance.value += args.amount Balance.update(value=Balance.value + args.amount).where(Balance.id == balance.id).execute() if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.channel.send( f":moneybag: <@{user.id}> a donné **{args.amount:n} {currency.symbol}** " f"({currency.name}) à <@{target.id}> !") else: await ctx.author.send( f":moneybag: Vous avez donné **{args.amount:n} {currency.symbol}** " f"({currency.name}) à **{target.name}** !") await target.user.send( f":moneybag: **{user.name}** vous a donné **{args.amount:n} " f"{currency.symbol}** ({currency.name}) !")
async def _vote(self, ctx, *args): """ Permet de voter à un scruting donné. Usage : `!vote <candidat> [<candidat> ...] --password <password> [--poll <poll_id>]` """ if ctx.channel and hasattr(ctx.channel, 'name'): await ctx.message.delete() user = await self.get_user(ctx.author) # Argument parser parser = Parser(prog=f'{ctx.prefix}{ctx.command.name}', description="") parser.add_argument('password', type=str, help="Mot de passe (pour l'anonymat)") parser.add_argument( 'candidates', metavar='candidat', type=str, nargs='+', help="Candidats (par ordre de préférence du plus ou moins apprécié)" ) parser.add_argument('--poll', '-p', type=str, help="Identifiant de scrutin") args = parser.parse_args(args) if parser.message: await ctx.author.send(f"```{parser.message}```") return # Get active and votable polls polls = Poll.select().where(~Poll.open_apply & Poll.open_vote) poll = await self.handle_poll(polls, args, ctx.author) if not poll: return # Check if all candidates where selected and sorted candidates = list(map(str.upper, args.candidates)) possibles = Candidate.select(Candidate.indice).where( Candidate.indice.is_null(False) & (Candidate.poll == poll)).order_by(Candidate.indice.asc()) possibles = {c.indice for c in possibles} if possibles != set(candidates) or len(possibles) != len(candidates): await ctx.author.send( f":no_entry: Vous n'avez pas sélectionné et/ou classé l'ensemble des candidats !" ) return # Create new password for user password, created = Password.get_or_create( poll=poll, user=user, defaults=dict(password=self.hash(args.password))) # ... or verify user password if not created and self.hash(args.password) != password.password: await ctx.author.send( f":no_entry: Votre mot de passe de scrutin est incorrect ou n'a pas encore configuré, " f"utilisez la commande `{ctx.prefix}pass` pour le définir !") return # Encrypt user with password and save vote choices encrypted, choices = self.encrypt(args.password, user.id), ' '.join(candidates) vote, created = Vote.get_or_create(user=encrypted, poll=poll, defaults=dict(choices=choices)) if not created: vote.choices = choices vote.save(only=('choices', )) await ctx.author.send(f":ballot_box: Merci pour votre vote !")