async def restock(self, ctx: Context, *, drink_name: Optional[str]): """ Restock the bar or only one drink. Barman role required. Parameters: drink_name: name of the drink """ server = get_server_from_context(ctx) lang = server.lang if drink_name is not None and len(drink_name) > DRINK_NAME_LENGTH: await ctx.send( conf.lang(lang, "wrong_drink_name").format(DRINK_NAME_LENGTH)) return if drink_name is None: (Drink.update(portions_left=Drink.portions_per_day).where( Drink.server == server)).execute() await ctx.send(conf.lang(lang, "restocked_all")) log.info("Restocked all drinks on {1}".format( drink_name, ctx.guild.id)) else: (Drink.update(portions_left=Drink.portions_per_day).where( Drink.server == server and Drink.name == drink_name)).execute() await ctx.send( conf.lang(lang, "restocked_single").format(drink_name)) log.info("Restocked drink \"{0}\" on {1}".format( drink_name, ctx.guild.id))
async def lang(self, ctx: Context, lang_code: str = None): """ If lang is provided, sets the language. Requires Manage Guild permission. Return the list of available languages and quick reminder how to set it. """ if lang_code: if lang_code not in get_langs(): await ctx.send(conf.international("incorrect_language")) else: logger.info("Updated lang on {0} to {1}".format( ctx.guild.id, lang_code)) with db.atomic(): server = get_server_or_create(ctx.guild.id, ctx.guild.preferred_locale) Server.update(lang=lang_code).where( Server.sid == ctx.guild.id).execute() Drink.delete().where(Drink.server == server.id).execute() await add_default_drinks(ctx.guild) await ctx.send(conf.lang(lang_code, "lang_selected")) else: langs = "\n".join( "{0}, lang_code \"{1}\"".format(conf.lang(lang, "name"), lang) for lang in conf.get_langs()) await ctx.send( conf.international("lang_list").format(self.bot.command_prefix) + '\n' + langs)
async def reset(self, ctx: Context, to_defaults: bool = False): """ Reset all drinks to defaults. Barman role required. """ Drink.delete().where(Drink.server == ctx.guild.id).execute() if to_defaults: await add_default_drinks(ctx.guild)
async def serve(self, ctx: Context, drink_name: str, to: commands.Greedy[Member]): """ Trying to give a drink to the member. This command will send a message, where the member can choose to drink or not. Parameters: drink_name: name of the drink to: member (can be mention) """ gid = ctx.guild.id server = get_server_from_context(ctx) lang = server.lang try: drink = Drink.get(Drink.server == server and Drink.name == drink_name) except DoesNotExist: if not check_guild_drink_count(gid): await ctx.send( conf.lang(lang, "too_many_drinks").format(DRINKS_PER_SERVER)) return drink = Drink.create(server=server, name=drink_name, intoxication=DEFAULT_INTOXICATION, portion_size=DEFAULT_PORTION_SIZE, portions_per_day=DEFAULT_PORTIONS_PER_DAY, portions_left=DEFAULT_PORTIONS_PER_DAY) msg = await ctx.send( conf.lang(lang, "serve_message").format(author=ctx.author.mention, drink=drink_name, portion_size=drink.portion_size)) await msg.add_reaction(conf.lang(lang, "ok-emoji")) await msg.add_reaction(conf.lang(lang, "no-emoji")) expected = set(to) def check(reaction, user): return user in expected and str(reaction.emoji) in { conf.lang(lang, "ok-emoji"), conf.lang(lang, "no-emoji") } while len(expected): try: reaction, user = await self.bot.wait_for( "reaction_add", timeout=conf.limitation("serve_timeout"), check=check) except asyncio.TimeoutError: break else: expected.remove(user) if str(reaction) == conf.lang(lang, "ok-emoji"): await give_a_drink(ctx, user, drink) await msg.delete() log.info("Deleted message {0} on {1} by time exceeding".format( msg.id, ctx.guild.id))
async def on_guild_remove(self, guild): log.info("Removing guild {0}".format(guild.id)) server = get_server_or_create(guild.id, guild.preferred_locale) with db.atomic(): Drink.delete().where(Drink.server == server).execute() Person.delete().where(Person.server == server).execute() server.delete_instance() return True
async def add_default_drinks(guild): server = get_server_or_create(guild.id, guild.preferred_locale) default_drinks = conf.lang_raw(server.lang, "default_drinks") with db.atomic(): for default_drink in default_drinks: Drink.create(server=server, name=default_drink.name, intoxication=default_drink.intoxication, portion_size=default_drink.portion, portions_per_day=default_drink.portions_per_day, portions_left=default_drink.portions_per_day) log.info("Added drinks to {0}".format(guild.id))
async def add_default_drinks(guild): default_drinks = conf.lang_raw("ru_RU", "default_drinks") with db.atomic(): for default_drink in default_drinks: Drink.create(server=guild.id, name=default_drink.name, intoxication=default_drink.intoxication, portion_size=default_drink.portion, portions_per_day=default_drink.portions_per_day, portions_left=default_drink.portions_per_day) log.info("Added drinks to {0}".format(guild.id))
async def reset(self, ctx: Context, to_defaults: bool = False): """ Reset all drinks to defaults. Barman role required. """ server = get_server_from_context(ctx) lang = server.lang Drink.delete().where(Drink.server == server).execute() if to_defaults: await add_default_drinks(ctx.guild) await ctx.send(conf.lang(lang, "reset_to_defaults_complete")) else: await ctx.send(conf.lang(lang, "reset_complete"))
async def add(self, ctx: Context, drink_name: str, intoxication: int = DEFAULT_INTOXICATION, portion_size: int = DEFAULT_PORTION_SIZE, portions_per_day: int = DEFAULT_PORTIONS_PER_DAY): """ Add a new drink to the bar. Barman role required. Parameters: drink_name: name of the drink, not empty intoxication: percent of intoxication (0-100). When man drinks a drink, this value will be appended to the level of intoxication. portion_size: size of portion, in milliliters, greater than 0 and less than 10000 (10l). portions_per_day: portions of this drink available for one day, greater than 0 and less than 10000. """ if not 0 <= intoxication <= 100: await ctx.send(conf.lang("ru_RU", "wrong_intoxication")) elif not 0 < portion_size <= PORTION_MAX_SIZE: await ctx.send( conf.lang("ru_RU", "wrong_portion_size").format(PORTION_MAX_SIZE)) elif not 0 < portions_per_day <= PORTIONS_PER_DAY: await ctx.send( conf.lang("ru_RU", "wrong_portions_per_day").format(PORTIONS_PER_DAY)) elif drink_name is None or len(drink_name) > DRINK_NAME_LENGTH: await ctx.send( conf.lang("ru_RU", "wrong_drink_name").format(DRINK_NAME_LENGTH)) elif not check_guild_drink_count(ctx.guild.id): await ctx.send( conf.lang("ru_RU", "too_many_drinks").format(DRINKS_PER_SERVER)) elif Drink.select().where(Drink.server == ctx.guild.id and Drink.name == drink_name).count() > 0: await ctx.send( conf.lang("ru_RU", "duplicate_drink").format(drink_name)) else: Drink.create(server=ctx.guild.id, name=drink_name, intoxication=intoxication, portion_size=portion_size, portions_per_day=portions_per_day, portions_left=portions_per_day) await ctx.send( conf.lang("ru_RU", "drink_added").format(drink_name)) log.info("Added drink \"{0}\" on {1}".format( drink_name, ctx.guild.id))
async def serve(self, ctx: Context, drink_name: str, to: commands.Greedy[Member]): """ Trying to give a drink to the member. This command will send a message, where the member can choose to drink or not. Parameters: drink_name: name of the drink to: member (can be mention) """ gid = ctx.guild.id try: drink = Drink.get(Drink.server == gid and Drink.name == drink_name) except DoesNotExist: if not check_guild_drink_count(gid): await ctx.send( conf.lang("ru_RU", "too_many_drinks").format(DRINKS_PER_SERVER)) return drink = Drink.create(server=gid, name=drink_name, intoxication=DEFAULT_INTOXICATION, portion_size=DEFAULT_PORTION_SIZE, portions_per_day=DEFAULT_PORTIONS_PER_DAY, portions_left=DEFAULT_PORTIONS_PER_DAY) msg = await ctx.send( conf.lang("ru_RU", "serve_message").format(author=ctx.author.mention, drink=drink_name, portion_size=drink.portion_size)) await asyncio.wait({ msg.add_reaction(conf.lang("ru_RU", "ok-emoji")), msg.add_reaction(conf.lang("ru_RU", "no-emoji")) }) message_dict[msg.id] = (ctx, msg, set(to), datetime.today() + timedelta(0, 60 * 10), drink)
async def consume_drink(ctx: Context, person: Person, drink: Drink): if person.intoxication > 100 or person.intoxication < 0: person.intoxication = 0 guild: Guild = ctx.guild member: Member = guild.get_member(person.uid) if drink.portions_left <= 0: await ctx.send( conf.lang("ru_RU", "no_portions_left").format(drink.name)) else: if drink.portions_left == 1: await ctx.send( conf.lang("ru_RU", "last_portion").format(drink.name)) person.intoxication += drink.intoxication drink.portions_left -= 1 if person.intoxication >= 100: try: await member.move_to(None, reason="Drank too much") await ctx.send( conf.lang("ru_RU", "overdrink_kick_message").format(member.mention)) except Forbidden: log.info("Can't kick an alcoholic: no permissions in " + guild.id) await ctx.send( conf.lang("ru_RU", "overdrink_no_kick_message").format( member.mention)) finally: person.intoxication = 0 elif person.intoxication > 80: await ctx.send( conf.lang("ru_RU", "pre_overdrink").format(member.display_name)) log.info("{0} consumed drink \"{1}\" on {2}".format( member.display_name, drink.name, guild.id)) with db.atomic(): person.save() drink.save()
async def list(self, ctx: Context): """ Returns the list with available drinks """ server = get_server_from_context(ctx) lang = server.lang drinks = Drink.select().where(Drink.server == server) out = "\n".join([ conf.lang(lang, "drink_info").format(drink.name, drink.portion_size, drink.portions_left, drink.portions_per_day) for drink in drinks ]) if out != "": await ctx.send(out) else: await ctx.send(conf.lang(lang, "no_drinks"))
async def list(self, ctx: Context): """ Returns the list with available drinks """ drinks = Drink.select().where(Drink.server == ctx.guild.id) # out = "" # for drink in drinks: # out += conf.lang("ru_RU", "drink_info").format(str(drink.name), str(drink.portion_size)) # out += '\n' out = "\n".join([ conf.lang("ru_RU", "drink_info").format(drink.name, drink.portion_size, drink.portions_left, drink.portions_per_day) for drink in drinks ]) if out != "": await ctx.send(out) else: await ctx.send(conf.lang("ru_RU", "no_drinks"))
async def drink(self, ctx: Context, *, drink_name: str): """ Drinks a drink and tails some random joke. Parameters: drink_name: name of the drink, not empty """ server = get_server_from_context(ctx) lang = server.lang if drink_name is None or len(drink_name) > DRINK_NAME_LENGTH: await ctx.send( conf.lang(lang, "wrong_drink_name").format(DRINK_NAME_LENGTH)) return try: drink = Drink.get(Drink.server == server and Drink.name == drink_name) except DoesNotExist: await ctx.send( conf.lang(lang, "drink_not_found").format(drink_name)) else: await give_a_drink(ctx, ctx.author, drink)
async def remove(self, ctx: Context, *, drink_name: str): """ Remove the drink from the bar. Barman role required. Parameters: drink_name: name of the drink, not empty """ server = get_server_from_context(ctx) lang = server.lang if drink_name is None or len(drink_name) > DRINK_NAME_LENGTH: await ctx.send( conf.lang(lang, "wrong_drink_name").format(DRINK_NAME_LENGTH)) return try: drink = Drink.get(Drink.server == server and Drink.name == drink_name) drink.delete_instance() await ctx.send(conf.lang(lang, "drink_deleted").format(drink_name)) log.info("Removed drink \"{0}\" from {1}".format( drink_name, ctx.guild.id)) except DoesNotExist: await ctx.send( conf.lang(lang, "drink_not_found").format(drink_name))
async def drink(self, ctx: Context, *, drink_name: str): """ Drinks a drink and tails some random joke. Parameters: drink_name: name of the drink, not empty """ if drink_name is None or len(drink_name) > DRINK_NAME_LENGTH: await ctx.send( conf.lang("ru_RU", "wrong_drink_name").format(DRINK_NAME_LENGTH)) return try: drink = Drink.get(Drink.server == ctx.guild.id and Drink.name == drink_name) person = get_person_or_create(ctx.guild.id, ctx.author.id) await consume_drink(ctx, person, drink) async with ctx.typing(): joke = get_joke("ru_RU") await ctx.send(joke or conf.lang("ru_RU", "joke_not_loaded")) except DoesNotExist: await ctx.send( conf.lang("ru_RU", "drink_not_found").format(drink_name))
def check_guild_drink_count(gid: int): return Drink.select(Drink).join(Server).where( Server.sid == gid).count() < DRINKS_PER_SERVER
async def restock(): (Drink.update(portions_left=Drink.portions_per_day)).execute() log.info("Restocked every server")
def check_guild_drink_count(gid: int): return Drink.select().where( Drink.server == gid).count() < DRINKS_PER_SERVER