def getUserSizes(g): # Find the largest and smallest current users. smallestuser = None smallestsize = SV.infinity largestuser = None largestsize = SV(0) allusers = {} for _, userid in userdb.listUsers(guildid=g.id): member = g.get_member(userid) if not (member and str(member.status) != "offline"): continue userdata = userdb.load(g.id, userid) if userdata.height == 0 or userdata.height == SV.infinity: continue if not userdata.is_active: continue if userdata.height > largestsize: largestuser = userid largestsize = userdata.height if userdata.height < smallestsize: smallestuser = userid smallestsize = userdata.height allusers[userid] = userdata.height return { "smallest": { "id": smallestuser, "size": smallestsize }, "largest": { "id": largestuser, "size": largestsize }, "users": allusers }
def getUserSizes(g): # Find the largest and smallest current users. # TODO: Check to see if these users are recently active, which would determine if they count towards the check. smallestuser = 000000000000000000 smallestsize = SV(SV.infinity) largestuser = 000000000000000000 largestsize = SV(0) allusers = {} for _, testid in userdb.listUsers(g.id): if testid in list( [m.id for m in g.members if str(m.status) != "offline"]): testdata = userdb.load(g.id, testid) allusers[testid] = testdata.height if testdata.height <= 0 or testdata.height >= SV.infinity: break if testdata.height > largestsize: largestuser = testid largestsize = testdata.height if testdata.height < smallestsize: smallestuser = testid smallestsize = testdata.height smallestuser = int(smallestuser) largestuser = int(largestuser) return { "smallest": { "id": smallestuser, "size": smallestsize }, "largest": { "id": largestuser, "size": largestsize }, "users": allusers }
async def register(self, ctx): # nick: str # currentheight: SV = proportions.defaultheight # baseheight: SV = proportions.defaultheight # baseweight: WV = userdb.defaultweight # unitsystem: str = "m" # species: str = None """Registers a user for SizeBot.""" userdata = None try: userdata = userdb.load(ctx.guild.id, ctx.author.id, allow_unreg=True) except errors.UserNotFoundException: userdata = None # User data already exists if userdata: if userdata.registered: await ctx.send( "Sorry! You already registered with SizeBot.\n" f"To unregister, use the `{conf.prefix}unregister` command." ) else: await showNextStep(ctx, userdata) return # User is already in different guilds, offer to copy profile to this guild? guilds = [ self.bot.get_guild(g) for g, _ in userdb.listUsers(userid=ctx.author.id) ] guilds = [g for g in guilds if g is not None] guilds_names = [g.name for g in guilds] if guilds_names: guildsstring = "\n".join(guilds_names) sentMsg = await ctx.send( f"You are already registered with SizeBot in these servers:\n{guildsstring}\n" f"You can copy a profile from one of these guilds to this one using `{ctx.prefix}copy.`\n" "Proceed with registration anyway?") await sentMsg.add_reaction(emojis.check) await sentMsg.add_reaction(emojis.cancel) # Wait for requesting user to react to sent message with emojis.check or emojis.cancel def check(reaction, reacter): return reaction.message.id == sentMsg.id \ and reacter.id == ctx.author.id \ and ( str(reaction.emoji) == emojis.check or str(reaction.emoji) == emojis.cancel ) try: reaction, ctx.author = await self.bot.wait_for("reaction_add", timeout=60.0, check=check) except asyncio.TimeoutError: # User took too long to respond await sentMsg.delete() return # if the reaction isn't the right one, stop. if reaction.emoji != emojis.check: return telemetry.RegisterStarted(ctx.guild.id, ctx.author.id).save() userdata = userdb.User() userdata.guildid = ctx.guild.id userdata.id = ctx.author.id userdata.nickname = ctx.author.display_name userdata.display = False if ctx.me.guild_permissions.manage_nicknames: userdata.display = True if any(c in ctx.author.display_name for c in "()[]"): await ctx.send( f"If you have already have a size tag in your name, you can fix your nick with `{conf.prefix}setnick`." ) userdata.registration_steps_remaining = [ "setheight", "setweight", "setsystem" ] # TODO: If the bot has MANAGE_NICKNAMES permission but can't change this user's permission, let the user know # TODO: If the bot has MANAGE_NICKNAMES permission but can't change this user's permission, and the user is an admin, let them know they may need to fix permissions userdb.save(userdata) await addUserRole(ctx.author) logger.warn(f"Started registration for a new user: {ctx.author}!") logger.info(userdata) # user has display == "y" and is server owner if userdata.display and userdata.id == ctx.author.guild.owner.id: await ctx.send( "I can't update a server owner's nick. You'll have to manage it manually." ) await ctx.send("Initial registration completed!") await showNextStep(ctx, userdata)
async def copy(self, ctx): """Copy your SizeBot profile from a different guild to this one.""" inputdict = { "1️⃣": 1, "2️⃣": 2, "3️⃣": 3, "4️⃣": 4, "5️⃣": 5, "6️⃣": 6, "7️⃣": 7, "8️⃣": 8, "9️⃣": 9, "0️⃣": 10 } guilds = [ self.bot.get_guild(g) for g, _ in userdb.listUsers(userid=ctx.author.id) ] guilds = [g for g in guilds if g is not None] guilds_ids = [g.id for g in guilds] guilds_names = [g.name for g in guilds] if guilds_ids == []: await ctx.send("You are not registered with SizeBot in any guilds." f"To register, use `{ctx.prefix}register`.") return # TODO: This doesn't seem to work. if guilds_ids == [ctx.guild.id]: await ctx.send( "You are not registered with SizeBot in any other guilds.") return outmsg = await ctx.send(emojis.loading) outstring = "" if userdb.exists(ctx.guild.id, ctx.author.id): outstring += "**:rotating_light:WARNING::rotating_light:**\n**You are already registered with SizeBot on this guild. Copying a profile to this guild will overwrite any size data you have here. Proceed with caution.**\n\n" outstring += "Copy profile from what guild?\n" # TODO: Replace this with a Menu. for i in range( min(len(guilds_ids), 10) ): # Loops over either the whole list of guilds, or if that's longer than 10, 10 times. outstring += f"{list(inputdict.keys())[i]} *{guilds_names[i]}*\n" await outmsg.add_reaction(list(inputdict.keys())[i]) await outmsg.add_reaction(emojis.cancel) outstring += f"\nClick {emojis.cancel} to cancel." await outmsg.edit(content=outstring) # Wait for requesting user to react to sent message with emojis.check or emojis.cancel def check(reaction, reacter): return reaction.message.id == outmsg.id \ and reacter.id == ctx.author.id \ and ( str(reaction.emoji) == emojis.check or str(reaction.emoji) in inputdict.keys() ) try: reaction, ctx.author = await self.bot.wait_for("reaction_add", timeout=60.0, check=check) except asyncio.TimeoutError: # User took too long to respond await outmsg.delete() return # if the reaction isn't the right one, stop. if reaction.emoji == emojis.cancel: await outmsg.delete() return if reaction.emoji not in inputdict.keys(): await outmsg.delete() raise errors.ThisShouldNeverHappenException chosen = inputdict[reaction.emoji] - 1 chosenguildid = guilds_ids[chosen] userdata = userdb.load(chosenguildid, ctx.author.id) userdata.guildid = ctx.guild.id userdb.save(userdata) telemetry.ProfileCopied(ctx.guild.id, ctx.author.id).save() await outmsg.delete() await ctx.send( f"Successfully copied profile from *{self.bot.get_guild(int(chosenguildid)).name}* to here!" )
async def advancedregister(self, ctx, nick: str, currentheight: SV = proportions.defaultheight, baseheight: SV = proportions.defaultheight, baseweight: WV = userdb.defaultweight, unitsystem: str = "m", species: str = None): """Registers a user for SizeBot, legacy style. Parameters: • `nick`: Your nickname. This will be the first thing displayed in your nickname. For a nickname with spaces, this must be wrapped in quotes. • `currentheight`: Self-explnatory. • `baseheight`: The default height of your character. It is recommended that this is a vaugely reasonable, human-like value, for instance your IRL height, except in rare circumnstances (for instance, if your character is a cat, or an orc, etc.) • `baseweight`: The default weight of your character. All the recommendations for baseheight apply here. • `unitsystem`: The unit system your size tag, and basic versions of your stats, will be displayed in by default. Accepts `M` for Metric, and `U` or `I` for U.S./Imperial. • `species`: Optional, a string to be appened after your size in your sizetag. Appears in the format `<nick> [<size>, <species>]`. If `species` is to contain a space, wrap it in quotes. Measurement parameters can accept a wide variety of units, as listed in `&units`. Examples: `®ister DigiDuncan 0.5in 5'7.5 120lb U` `®ister Surge 11ft 5'8 140lb U Raichu` `®ister "Speck Boi" 0.1mm 190cm 120kg M` """ readable = f"CH {currentheight}, BH {baseheight}, BW {baseweight}" logger.warn(f"New user attempt! Nickname: {nick}") logger.info(readable) # Already registered if userdb.exists(ctx.guild.id, ctx.author.id): await ctx.send("Sorry! You already registered with SizeBot.\n" "To unregister, use the `&unregister` command.") logger.warn( f"User already registered on user registration: {ctx.author}.") return guilds = [ self.bot.get_guild(g) for g, _ in userdb.listUsers(userid=ctx.author.id) ] guilds = [g for g in guilds if g is not None] guilds_names = [g.name for g in guilds] if guilds_names != []: guildsstring = "\n".join(guilds_names) sentMsg = await ctx.send( f"You are already registered with SizeBot in these servers:\n{guildsstring}\n" f"You can copy a profile from one of these guilds to this one using `{ctx.prefix}copy.`\n" "Proceed with registration anyway?") await sentMsg.add_reaction(emojis.check) await sentMsg.add_reaction(emojis.cancel) # Wait for requesting user to react to sent message with emojis.check or emojis.cancel def check(reaction, reacter): return reaction.message.id == sentMsg.id \ and reacter.id == ctx.author.id \ and ( str(reaction.emoji) == emojis.check or str(reaction.emoji) == emojis.cancel ) reaction = None try: reaction, ctx.author = await self.bot.wait_for("reaction_add", timeout=60.0, check=check) except asyncio.TimeoutError: # User took too long to respond await sentMsg.delete() # if the reaction isn't the right one, stop. if reaction.emoji != emojis.check: return # Invalid size value if (currentheight <= 0 or baseheight <= 0 or baseweight <= 0): logger.warn("Invalid size value.") await ctx.send("All values must be an integer greater than zero.") return # Invalid unit value if unitsystem.lower() not in ["m", "u", "i"]: logger.warn(f"unitsystem was {unitsystem}, must be M or U/I.") await ctx.send("Unitsystem must be `M` or `U`/`I`.") raise errors.InvalidUnitSystemException # I system is really U. if unitsystem.lower() == "i": unitsystem = "u" telemetry.AdvancedRegisterUsed(ctx.guild.id, ctx.author.id).save() userdata = userdb.User() userdata.guildid = ctx.guild.id userdata.id = ctx.author.id userdata.nickname = nick userdata.display = True userdata.height = currentheight userdata.baseheight = baseheight userdata.baseweight = baseweight userdata.unitsystem = unitsystem userdata.species = species userdb.save(userdata) await addUserRole(ctx.author) logger.warn(f"Made a new user: {ctx.author}!") logger.info(userdata) await ctx.send(f"Registered <@{ctx.author.id}>. {userdata}.") # user has display == "y" and is server owner if userdata.display and userdata.id == ctx.author.guild.owner.id: await ctx.send( "I can't update a server owner's nick. You'll have to manage it manually." ) return