async def on_end(self, bot): if "out_channel" not in db.keys(): return out_channel = await bot.get_channel(db["out_channel"]) participation = db["raffle_participation"] # Computing the winner for the last raffle if len(participation) > 0: total_tickets = sum(participation.values()) winning_index = random.randrange(0, total_tickets) partial_sum = 0 for id, value in participation.items(): if partial_sum <= winning_index < partial_sum + value: break partial_sum += value prize = self.get_raffle_total_prize() db["raffle_participation"] = dict() # Giving the tax to the bot tax_value = total_tickets * self.ticket_price - prize piflouz_handlers.update_piflouz(bot.me.id, qty=tax_value, check_cooldown=False) message = f"Congratulations to <@{id}> for winning the raffle, earning {prize} {Constants.PIFLOUZ_EMOJI}!" piflouz_handlers.update_piflouz(id, prize, check_cooldown=False) await out_channel.send(message) await utils.update_piflouz_message(bot) bot.dispatch("raffle_won", id)
async def duel_deny_cmd(self, ctx, duel_id): """ Callback for the duel deny command -- input: ctx: interactions.CommandContext duel_id: int """ await ctx.defer(ephemeral=True) duel_index = None for i, duel in enumerate(db["duels"]): if duel["duel_id"] == duel_id: duel_index = i break await utils.custom_assert(duel_index is not None, "This duel does not exist", ctx) await utils.custom_assert(not duel["accepted"], "You already accepted this challenge", ctx) await utils.custom_assert(duel["user_id2"] != -1, "You can't deny a challenge at anyone", ctx) await utils.custom_assert(duel["user_id2"] == int(ctx.author.id), "You are not targeted by this duel", ctx) # Give back the money to the challenger piflouz_handlers.update_piflouz(duel["user_id1"], qty=duel["amount"], check_cooldown=False) del db["duels"][duel_index] await ctx.get_channel() await ctx.channel.send( f"{ctx.author.mention} denied <@{duel['user_id1']}>'s challenge!") await ctx.send("Done", ephemeral=True) await utils.update_piflouz_message(self.bot)
async def end_current_season(bot): """ Announces the end of the current season and computes the amount of turbo piflouz earned -- input: bot: interactions.Client """ # Reseting the previous stats for the season results db["season_results"] = {} # Ending the ongoing duels and giving back the money for duel in db["duels"]: piflouz_handlers.update_piflouz(duel["user_id1"], qty=duel["amount"], check_cooldown=False) if duel["accepted"]: piflouz_handlers.update_piflouz(duel["user_id2"], qty=duel["amount"], check_cooldown=False) # Adding turbo piflouz based on the amount of piflouz collected bank = list(db["piflouz_bank"].items()) reward_balance = lambda balance: int(sqrt(balance)) reward_turbo_piflouz_based_on_scores(bank, reward_balance, "Balance") # Adding turbo piflouz based on the amount of piflex images discovered piflex_count = [(user_id, len(discovered)) for user_id, discovered in db["discovered_piflex"].items()] reward_piflex = lambda count: int(310 / (12 ** 3) * count ** 3 + 20 * count) # so that there is at least an increase of 20 per image, and so that the whole 12 images give 550 turbo piflouz # the median of the required number of piflex is aroud 35, which lead to 35*8000 piflouz spent, which would lead to 530 turbo piflouz otherwhise reward_turbo_piflouz_based_on_scores(piflex_count, reward_piflex, "Discovered piflex") bonus_ranking = [100, 50, 30] # Adding piflouz based on the ranking in piflouz reward_turbo_piflouz_based_on_ranking(bank, bonus_ranking, "Balance ranking") # Adding piflouz based on the ranking in piflex reward_turbo_piflouz_based_on_ranking(piflex_count, bonus_ranking, "Piflex ranking") # Adding piflouz based on the ranking in donations donations = list(db["donation_balance"].items()) reward_turbo_piflouz_based_on_ranking(donations, bonus_ranking, "Donation ranking") await utils.update_piflouz_message(bot) # Reseting the database db["piflouz_bank"] = {} db["discovered_piflex"] = {} db["donation_balance"] = {} db["random_gifts"] = {} db["powerups"] = {} db["duels"] = [] # Sending the announcement message if "out_channel" in db.keys(): embed = await embed_messages.get_embed_end_season(bot) channel = await bot.get_channel(db["out_channel"]) await channel.send(embeds=embed)
async def donate_cmd(self, ctx, user_receiver, amount): """ Callback for the donate command -- input: ctx: interactions.CommandContext user_receiver: interactions.User amount: int """ await ctx.defer(ephemeral=True) user_sender = ctx.author # Trading await utils.custom_assert( piflouz_handlers.update_piflouz(user_sender.id, qty=-amount, check_cooldown=False), "Sender does not have enough money to donate", ctx) qty_tax = ceil(Constants.DONATE_TAX_RATIO / 100 * amount) qty_receiver = amount - qty_tax piflouz_handlers.update_piflouz(self.bot.me.id, qty=qty_tax, check_cooldown=False) piflouz_handlers.update_piflouz(user_receiver.id, qty=qty_receiver, check_cooldown=False) await ctx.send("Done!", ephemeral=True) channel = await ctx.get_channel() await channel.send( f"{user_sender.mention} sent {amount} {Constants.PIFLOUZ_EMOJI} to {user_receiver.mention}" ) await utils.update_piflouz_message(self.bot) self.bot.dispatch("donation_successful", ctx.author.id, amount, user_receiver.id) # Update the statistics to see the most generous donators id_sender = str(user_sender.id) id_receiver = str(user_receiver.id) if id_sender not in db["donation_balance"].keys(): db["donation_balance"][id_sender] = 0 if id_receiver not in db["donation_balance"].keys(): db["donation_balance"][id_receiver] = 0 db["donation_balance"][id_sender] += amount db["donation_balance"][id_receiver] -= qty_receiver
async def wordle_guess_cmd(self, ctx, word): """ Callback for the /wordle guess command -- input: ctx: interactions.CommandContext word: str """ await ctx.defer(ephemeral=True) await utils.custom_assert("current_event" in db.keys(), "No current event registered", ctx) current_event = eval(db["current_event"]) await utils.custom_assert( isinstance(current_event, events.Wordle_event), "The current event is not a wordle", ctx) wordle = Wordle(db["word_of_the_day"]) user_id = str(int(ctx.author.id)) if user_id not in db["wordle_guesses"].keys(): db["wordle_guesses"][user_id] = [] guesses = list(db["wordle_guesses"][user_id]) word = word.lower() await utils.custom_assert( len(guesses) < wordle.nb_trials, "The maximum amount of trials has been reached!", ctx) await utils.custom_assert(wordle.is_valid(word), "This is not a valid word!", ctx) await utils.custom_assert( guesses == [] or wordle.solution != guesses[-1], "You already won!", ctx) guesses.append(word) db["wordle_guesses"][user_id] = guesses header_str = "\n".join(wordle.guess(w) for w in guesses) if guesses[-1] == wordle.solution: header_str += f"\n\nCongratulations, you found the word of the day with {len(guesses)}/{wordle.nb_trials} trials!\nYou earnt {current_event.reward}{Constants.PIFLOUZ_EMOJI}" piflouz_handlers.update_piflouz(user_id, current_event.reward, check_cooldown=False) elif len(guesses) == wordle.nb_trials: header_str += f"\n\nOuch, you failed :(\nThe answer was: **{wordle.solution}**" await self.send_wordle_embed(ctx, wordle, guesses, header_str)
def on_buy(self, user_id, current_time): user_id = str(user_id) if user_id not in db["powerups"].keys(): db["powerups"][user_id] = [] i = None for current, powerup_str in enumerate(db["powerups"][user_id]): if powerup_str.startswith(f"{__name__}.{type(self).__name__}"): i = current self.qty = eval(db["powerups"][user_id][i][len(__name__) + 1:]).qty break # Remove the '__name__.' at the begining if i is not None and eval( db["powerups"][user_id][i][len(__name__) + 1:]).qty == self.max_qty: return False # User already has the maximum number of this powerup self.qty += 1 powerup_str = self.to_str() if not piflouz_handlers.update_piflouz( user_id, qty=-self.price, check_cooldown=False): return False if i is not None: del db["powerups"][user_id][i] db["powerups"][user_id].append(powerup_str) return True
async def giveaway_cmd(self, ctx, amount): """ Callback for the giveway command -- input: ctx: interactions.CommandContext amount: int -> how many piflouz given """ await ctx.defer(ephemeral=True) user_sender = ctx.author # Trading await utils.custom_assert( piflouz_handlers.update_piflouz(user_sender.id, qty=-amount, check_cooldown=False), "Sender does not have enough money to giveaway", ctx) custom_message = f"This is a gift from the great {user_sender.mention}, be sure to thank them! " await piflouz_handlers.spawn_pibox(self.bot, amount, custom_message=custom_message) await ctx.send("Done!", ephemeral=True) await utils.update_piflouz_message(self.bot) self.bot.dispatch("giveaway_successful", ctx.author.id)
async def buy_rank_piflex_cmd(self, ctx): """ Callback for the buyRankPiflex command -- input: ctx: interactions.CommandContext """ await ctx.defer(ephemeral=True) user_id = str(ctx.author.id) member = ctx.author role_id = Constants.PIFLEXER_ROLE_ID if user_id in db["piflouz_bank"] and piflouz_handlers.update_piflouz(user_id, qty=-Constants.PIFLEXER_COST, check_cooldown=False) and role_id not in member.roles: await member.add_role(role=role_id, guild_id=ctx.guild_id) channel = await ctx.get_channel() await channel.send(f"{member.mention} just bought the piflexer rank!") await ctx.send("Done!", ephemeral=True) await utils.update_piflouz_message(self.bot) db["piflexers"][user_id] = int(ctx.id.epoch) self.bot.dispatch("piflexer_rank_bought", ctx.author.id) else: # User does not have enough money if role_id not in member.roles: await ctx.send(f"You need {Constants.PIFLEXER_COST - db['piflouz_bank'][user_id]} {Constants.PIFLOUZ_EMOJI} to buy the rank!", ephemeral=True) # User already have the rank else: await ctx.send("You already have the rank!", ephemeral=True)
def validate(self, user_id): """ Registers the validation of the achievement in the database and gives the reward to the user -- input: user_id: int/str """ user_id = str(user_id) if user_id not in db["achievements"].keys(): db["achievements"][user_id] = [] db["achievements"][user_id].append(self.to_str()) piflouz_handlers.update_piflouz(user_id, qty=self.reward, check_cooldown=False) print(f"validated {self.to_str()} for user {user_id}")
async def on_end(self, bot): if "out_channel" not in db.keys(): return out_channel = await bot.get_channel(db["out_channel"]) participation = list(db["birthday_raffle_participation"]) # Computing the winner for the last raffle if len(participation) > 3: winner1 = random.choice(participation) participation.remove(winner1) winner2 = random.choice(participation) participation.remove(winner2) winner3 = random.choice(participation) db["birthday_raffle_participation"] = [] prize1 = round(self.reward * .5) prize2 = round(self.reward * .3) prize3 = round(self.reward * .2) piflouz_handlers.update_piflouz(winner1, qty=prize1, check_cooldown=False) piflouz_handlers.update_piflouz(winner2, qty=prize2, check_cooldown=False) piflouz_handlers.update_piflouz(winner3, qty=prize3, check_cooldown=False) message = f"The birthday raffle is over! <@{winner1}> won {prize1} {Constants.PIFLOUZ_EMOJI}, <@{winner2}> won {prize2} {Constants.PIFLOUZ_EMOJI} and <@{winner3}> won {prize3} {Constants.PIFLOUZ_EMOJI}!" await out_channel.send(message)
async def duel_accept_cmd(self, ctx, duel_id): """ Callback for the duel accept command -- input: ctx: interactions.CommandContext duel_id: int """ await ctx.defer(ephemeral=True) duel_index = None for i, duel in enumerate(db["duels"]): if duel["duel_id"] == duel_id: duel_index = i break # Check the duel exists await utils.custom_assert(duel_index is not None, "This duel does not exist", ctx) # Check that the duel is still available await utils.custom_assert(not duel["accepted"], "This challenge has already been accepted", ctx) # Check that you are a target of the duel await utils.custom_assert( duel["user_id2"] == int(ctx.author.id) or duel["user_id2"] == -1, "You are not targeted by this duel", ctx) # Check that you are not the one who made the challenge await utils.custom_assert(duel["user_id1"] != int(ctx.author.id), "You can't challenge yourself!", ctx) # Check the user has enough money await utils.custom_assert( piflouz_handlers.update_piflouz(ctx.author.id, qty=-duel["amount"], check_cooldown=False), "You don't have enough piflouz to do that", ctx) db["duels"][duel_index]["accepted"] = True db["duels"][duel_index]["user_id2"] = int(ctx.author.id) duel_type = duel["duel_type"] channel = await ctx.get_channel() await channel.send( f"{ctx.author.mention} accepted <@{duel['user_id1']}>'s challenge! Use `/duel play {duel_type} {duel['duel_id']} [your move]`" ) await ctx.send("Done!", ephemeral=True) await utils.update_piflouz_message(self.bot) self.bot.dispatch("duel_accepted", int(ctx.author.id), duel_id)
async def duel_cancel_cmd(self, ctx, duel_id): """ Callback for the duel cancel command -- input: ctx: interactions.CommandContext duel_id: int """ await ctx.defer(ephemeral=True) duel_index = None for i, duel in enumerate(db["duels"]): if duel["duel_id"] == duel_id: duel_index = i break await utils.custom_assert(duel_index is not None, "This duel does not exist", ctx) await utils.custom_assert(not duel["accepted"], "The duel was already accepted", ctx) await utils.custom_assert(duel["user_id1"] == int(ctx.author.id), "You did not create this challenge", ctx) # Give back the money to the challenger piflouz_handlers.update_piflouz(ctx.author.id, qty=duel["amount"], check_cooldown=False) del db["duels"][duel_index] mention = "anyone" if duel[ "user_id2"] == -1 else f"<@{duel['user_id2']}>" await ctx.get_channel() await ctx.channel.send( f"{ctx.author.mention} cancelled his/her challenge to {mention}, what a loser" ) await ctx.send("Done!", ephemeral=True) await utils.update_piflouz_message(self.bot)
async def raffle_cmd(self, ctx, nb_tickets): """ Callback for the /raffle command -- input: ctx: interactions.CommandContext nb_tickets: int """ await ctx.defer(ephemeral=True) await utils.custom_assert("current_event" in db.keys(), "No current event registered", ctx) current_event = eval(db["current_event"]) await utils.custom_assert( isinstance(current_event, events.Raffle_event), "The current event is not a raffle", ctx) price = nb_tickets * current_event.ticket_price user_id = str(ctx.author.id) # user doesn't have enough money await utils.custom_assert( piflouz_handlers.update_piflouz(user_id, qty=-price, check_cooldown=False), f"User {ctx.author} doesn't have enough money to buy {nb_tickets} tickets", ctx) if not user_id in db["raffle_participation"].keys(): db["raffle_participation"][user_id] = 0 db["raffle_participation"][user_id] += nb_tickets await ctx.send(f"Successfully bought {nb_tickets} tickets", ephemeral=True) await current_event.update_raffle_message(self.bot) await utils.update_piflouz_message(self.bot) self.bot.dispatch("raffle_participation_successful", ctx.author.id, nb_tickets)
async def piflex_cmd(self, ctx): """ Callback for the piflex command -- input: ctx: interactions.CommandContext """ await ctx.defer(ephemeral=True) user_id = str(ctx.author.id) # User has enough money if user_id in db["piflouz_bank"] and piflouz_handlers.update_piflouz(user_id, qty=-Constants.PIFLEX_COST, check_cooldown=False): await ctx.author.add_role(role=Constants.MEGA_PIFLEXER_ROLE_ID, guild_id=ctx.guild_id) t = int(ctx.id.epoch) db["mega_piflexers"][user_id] = t embed, index = embed_messages.get_embed_piflex(ctx.author) if str(ctx.author.id) not in db["discovered_piflex"].keys(): db["discovered_piflex"][str(ctx.author.id)] = [] already_discovered = set(db["discovered_piflex"][str(ctx.author.id)]) new = index not in already_discovered already_discovered.add(index) db["discovered_piflex"][str(ctx.author.id)] = list(already_discovered) content = None if not new else "Congratulations, this is a new image!" channel = await ctx.get_channel() await channel.send(content, embeds=embed) await ctx.send("Done!", ephemeral=True) await utils.update_piflouz_message(self.bot) self.bot.dispatch("piflex_bought", ctx.author.id) # User doesn't have enough money else: balance = 0 if user_id not in db["piflouz_bank"].keys() else db["piflouz_bank"][user_id] await ctx.send(f"You need {Constants.PIFLEX_COST - balance} more {Constants.PIFLOUZ_EMOJI} to piflex!", ephemeral=True)
async def duel_challenge_cmd(self, ctx, amount, duel_type, user=None): """ Callback for the duel challenge command -- input: ctx: interactions.CommandContext amount: int -> how many piflouz involved by both users duel_type: string -> what kind of duel user: interactions.User -> the person challenged """ await ctx.defer(ephemeral=True) await utils.custom_assert( user is None or int(ctx.author.id) != int(user.id), "You can't challenge yourself!", ctx) await utils.custom_assert( piflouz_handlers.update_piflouz(ctx.author.id, qty=-amount, check_cooldown=False), "You don't have enough piflouz to do that", ctx) id_challenged = -1 if user is None else int(user.id) new_duel = utils.create_duel(int(ctx.author.id), id_challenged, amount, duel_type) db["duels"].append(new_duel) mention = "anyone" if user is None else user.mention channel = await ctx.get_channel() await channel.send( f"{ctx.author.mention} challenged {mention} at {duel_type} betting {amount} {Constants.PIFLOUZ_EMOJI}! Use `/duel accept {new_duel['duel_id']}` to accept or `/duel deny {new_duel['duel_id']}` to deny." ) await ctx.send("Done!", ephemeral=True) await utils.update_piflouz_message(self.bot) self.bot.dispatch("duel_created", ctx.author.id, id_challenged, amount, duel_type)
async def get_cmd(self, ctx): """ Callback for the get command -- input: ctx: interactions.CommandContext """ await ctx.defer(ephemeral=True) current_time = int(ctx.id.epoch) piflouz_handlers.update_combo(ctx.author.id, current_time) successful_update, qty = piflouz_handlers.update_piflouz( ctx.author.id, current_time=current_time) if not successful_update: timer = utils.get_timer(ctx.author.id, current_time) output_text = f"You still need to wait {utils.seconds_to_formatted_string(timer)} before earning more {Constants.PIFLOUZ_EMOJI}!" else: output_text = f"You just earned {qty} {Constants.PIFLOUZ_EMOJI}! Come back later for some more\nYour current combo: {db['mining_combo'][str(ctx.author.id)]} / {piflouz_handlers.get_max_rewardable_combo(ctx.author.id)}" await ctx.send(output_text, ephemeral=True) await utils.update_piflouz_message(self.bot) self.bot.dispatch("combo_updated", ctx.author.id)
def actions_every_hour(self, user_id): user_id = str(user_id) piflouz_earned = self.value * self.qty piflouz_handlers.update_piflouz(user_id, qty=piflouz_earned, check_cooldown=False)
async def duel_play_shifumi_cmd(self, ctx, duel_id, value): """ Callback for the duel accept command -- input: ctx: interactions.CommandContext duel_id: int value: string -> the move played by the player """ await ctx.defer(ephemeral=True) duel_index = None for i, duel in enumerate(db["duels"]): if duel["duel_id"] == duel_id: duel_index = i break await utils.custom_assert(duel_index is not None, "This duel does not exist", ctx) await utils.custom_assert(duel["accepted"], "This duel is not accepted yet", ctx) await utils.custom_assert( int(ctx.author.id) in [duel["user_id1"], duel["user_id2"]], "You are not part of this challenge", ctx) if duel["user_id1"] == ctx.author.id: await utils.custom_assert(duel["move1"] is None, "You already played!", ctx) db["duels"][duel_index]["move1"] = value id1 = int(ctx.author.id) id2 = duel["user_id2"] else: await utils.custom_assert(duel["move2"] is None, "You already played!", ctx) db["duels"][duel_index]["move2"] = value id1 = duel["user_id1"] id2 = int(ctx.author.id) await ctx.send("Done! Just wait for the other player to make a move", ephemeral=True) move1 = db["duels"][duel_index]["move1"] move2 = db["duels"][duel_index]["move2"] total_money = 2 * duel["amount"] money_tax = ceil(total_money * Constants.DUEL_TAX_RATIO / 100) money_if_win = total_money - money_tax win_shifumi = { "Rock": "Scissors", "Paper": "Rock", "Scissors": "Paper" } channel = await ctx.get_channel() if move1 is not None and move2 is not None: # Tie, everyone gets all of their money back if move1 == move2: piflouz_handlers.update_piflouz(id1, qty=duel["amount"], check_cooldown=False) piflouz_handlers.update_piflouz(id2, qty=duel["amount"], check_cooldown=False) await channel.send( f"<@{id1}> and <@{id2}> tied at {duel['duel_type']}! They both played {move1}! They both got their money back" ) self.bot.dispatch("duel_tie", id1, id2, duel["amount"], duel["duel_type"]) # Player 1 won elif win_shifumi[move1] == move2: piflouz_handlers.update_piflouz(id1, qty=money_if_win, check_cooldown=False) piflouz_handlers.update_piflouz(self.bot.me.id, qty=money_tax, check_cooldown=False) await channel.send( f"<@{id1}> won at {duel['duel_type']} against <@{id2}>, earning {money_if_win} {Constants.PIFLOUZ_EMOJI}! They played {move1} vs {move2}" ) self.bot.dispatch("duel_won", id1, id2, duel["amount"], duel["duel_type"]) # Player 2 won else: piflouz_handlers.update_piflouz(id2, qty=money_if_win, check_cooldown=False) piflouz_handlers.update_piflouz(self.bot.me.id, qty=money_tax, check_cooldown=False) await channel.send( f"<@{id2}> won at {duel['duel_type']} against <@{id1}>, earning {money_if_win} {Constants.PIFLOUZ_EMOJI}! They played {move2} vs {move1}" ) self.bot.dispatch("duel_won", id2, id1, duel["amount"], duel["duel_type"]) del db["duels"][duel_index] await utils.update_piflouz_message(self.bot)