async def user_speaks(self, user): user_id = user.id xp = 0 next_role = None curr_time = datetime.datetime.now() out_message = None if user_id not in self.user_cache: # First, if user is not in cache, try and fetch from DB xp_db = db.fetch_user_xp(user_id) if xp_db is not None: # If user is in the DB, use that value xp = xp_db else: # Otherwise, give them starting XP value xp = STARTING_XP # Since they weren't in the cache, make sure they have the correct roles next_role = await self.check_roles(user, xp) else: # If user is in cache, get that value instead user_data = self.user_cache[user_id] # Check their last timestamp. # NOTE: Mayor Lewis used to only give XP if they spoke in a "new" minute. But that would involve rounding a datetime, and I can't be bothered. last_mes_time = user_data.timestamp dt = curr_time - last_mes_time # Users only get XP every minute, so if not enough time has elapsed, ignore them if dt < datetime.timedelta(minutes=1): return None # Else, grab their data xp = user_data.xp next_role = user_data.next_role_at xp += XP_PER_MINUTE * self.xp_multiplier # If we have earned enough XP to level up, award and find next role if next_role != None and xp >= next_role: # Find what the congratulatory message should be # Not very efficient, but there will likely only be a handful of ranks for rank in RANKS: rank_xp = rank["level"] * XP_PER_LVL if rank_xp == next_role: out_message = rank["message"] break next_role = await self.check_roles(user, xp) username = "******".format(user.name, user.discriminator) avatar = user.avatar # Update their entry in the cache self.user_cache[user_id] = UserData(xp, curr_time, username, avatar, next_role) # Update their entry in the database db.set_user_xp(user_id, xp, username, avatar) return out_message
async def refresh_db(self, server): leaders = db.get_leaders() # Iterate thru every leader on the leaderboard and collect data for leader in leaders: leader_id = leader[0] leader_xp = leader[1] user = discord.utils.get(server.members, id=leader_id) # Update users that are still in the server if user != None: leader_name = f"{user.name}#{user.discriminator}" leader_avatar = user.avatar # NOTE: May be worth to populate the cache here as well db.set_user_xp(leader_id, leader_xp, leader_name, leader_avatar) # Otherwise, prune their username/avatar so that they don't appear on the leaderboard else: db.set_user_xp(leader_id, leader_xp, None, None)
async def give_xp(self, user, server, xp_add=None): user_id = user.id xp = 0 monthly_xp = 0 next_role = None curr_time = datetime.datetime.now() out_message = None if user_id not in self.user_cache: xp = db.fetch_user_xp(user_id) monthly_xp = db.fetch_user_monthly_xp(user_id) # Since they weren't in the cache, make sure they have the correct roles next_role = await self.check_roles(user, xp) else: # If user is in cache, get that value instead user_data = self.user_cache[user_id] last_mes_time = user_data.timestamp # Check their last timestamp if we aren't manually adding XP # NOTE: Mayor Lewis used to only give XP if they spoke in a "new" minute. But that would involve rounding a datetime, and I can't be bothered. if xp_add == None: dt = curr_time - last_mes_time # Users only get XP every minute, so if not enough time has elapsed, ignore them if dt < datetime.timedelta(minutes=1): return None # Else, grab their data xp = user_data.xp monthly_xp = user_data.monthly_xp next_role = user_data.next_role_at # Check if we've rolled over to a new month if last_mes_time.month != curr_time.month: monthly_xp = 0 if not xp_add: xp_add = XP_PER_MINUTE * self.xp_multiplier xp += xp_add monthly_xp += xp_add # If we have earned enough XP to level up, award and find next role if next_role != None and xp >= next_role: # Find what the congratulatory message should be # Not very efficient, but there will likely only be a handful of ranks for rank in RANKS: rank_xp = rank["level"] * XP_PER_LVL if rank_xp == next_role: if rank['message'] != "": out_message = f"<@{user_id}> {rank['message']}" if rank['welcome']['message'] != "": for welcome_id in rank['welcome']['channels']: chan = discord.utils.get(server.channels, id=welcome_id) await chan.send( f"Hello <@{user_id}>! {rank['welcome']['message']}" ) break next_role = await self.check_roles(user, xp) username = f"{user.name}#{user.discriminator}" avatar = user.avatar # Update their entry in the cache self.user_cache[user_id] = UserData(xp, monthly_xp, curr_time, username, avatar, next_role) # Update their entry in the database db.set_user_xp(user_id, xp, username, avatar, monthly_xp, curr_time.month) return out_message