async def kick(self, ctx, user: Member): if user in self.tournament.participants: await user.remove_roles(self.roles.participant) if user in self.tournament.winners: self.tournament.winners.remove(user) self.tournament.remove_participant(user) await ctx.send( f"{Emote.leave} {user.mention} was kicked from the tournament." ) Log("Participant Kicked", description= f"{user.mention} was kicked from **{self.tournament.name}** by {ctx.author.mention}.", color=Color.dark_gold()) embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed) await self.checklist.update_text(ctx, self.tournament) elif user in self.tournament.spectators: await user.remove_roles(self.roles.spectator) self.tournament.spectators.remove(user) await ctx.send( f"{ctx.author.mention} is no longer spectating the tournament." ) Log("Spectator Kicked", description= f"{ctx.author.mention} was kicked from **{self.tournament.name}** by {ctx.author.mention}.", color=Color.dark_gold()) embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed) else: raise commands.BadArgument("This user is not in a tournament!")
async def leave(self, ctx): if ctx.author in self.tournament.participants: await ctx.author.remove_roles(self.roles.participant) if ctx.author in self.tournament.winners: self.tournament.winners.remove(ctx.author) self.tournament.remove_participant(ctx.author) await ctx.send( f"{Emote.leave} {ctx.author.mention} left the tournament.") Log("Participant Left", description= f"{ctx.author.mention} left **{self.tournament.name}**.", color=Color.dark_gold()) embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed) await self.checklist.update_text(ctx, self.tournament) elif ctx.author in self.tournament.spectators: await ctx.author.remove_roles(self.roles.spectator) self.tournament.spectators.remove(ctx.author) await ctx.send( f"{ctx.author.mention} is no longer spectating the tournament." ) Log("Spectator Left", description= f"{ctx.author.mention} left **{self.tournament.name}**.", color=Color.dark_gold()) embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed) else: raise commands.BadArgument("You are not in a tournament!")
async def ign(self, ctx, ign=None): if ign is None: await ctx.send( "Please provide your Werewolf Online in-game name: `;ign example_name`" ) return user = User.fetch_by_id(ctx, ctx.author.id) old_ign = user.ign user.ign = ign self.client.get_cog("TOrganizer").cache_ign(ctx.author, ign) await ctx.send( f"{Emote.check} {ctx.author.mention}, your Werewolf Online IGN has been set to `{ign}`." ) Log("IGN Set", description=f"{ctx.author.mention} has set their IGN to `{ign}`.", color=0x6a0dad, fields=[{ 'name': 'Previous IGN', 'value': old_ign }])
async def spectate(self, ctx): await self.CheckRequirements(ctx.author) if ModifierCheck("SpectatorsAllowed", self.tournament.modifiers) is False: raise TournamentJoinException( "spectators are not allowed for this tournament!") if ctx.author in self.tournament.spectators: raise TournamentJoinException("you are already a spectator!") spec_count = len(self.tournament.spectators) join_msg = f"{Emote.join} {ctx.author.mention} joined the spectators. **{str(spec_count + 1)}** spectators are now watching the tournament." if spec_count == 0: # First join, make singular i = join_msg[-35:].index("s are") + len(join_msg) - 35 join_msg = join_msg[:i] + " is" + join_msg[i + 5:] await ctx.author.add_roles(self.roles.spectator) await self.channels.t_chat.send(join_msg) self.tournament.spectators.append(ctx.author) Log("Spectator Joined", description= f"{ctx.author.mention} joined **{self.tournament.name}**.", color=Color.dark_green(), fields=[{ 'name': "Spectator Count", 'value': str(spec_count + 1) }]) embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed)
async def begin(self, ctx): if self.tournament.status != Status.Opened: raise commands.BadArgument( "The tournament cannot be closed right now.") if len(self.tournament.get_participants()) < 1: raise commands.BadArgument( "There are no participants in the tournament.") no_ign = "" for player in self.tournament.get_participants(): user = User.fetch_by_id(ctx, player.id) if user.ign is None: no_ign += f"**{player.name}**\n" if no_ign != "": raise commands.BadArgument( "Some players do not have an IGN set: \n" + no_ign) await ctx.send( f"{Emote.check} The tournament has been closed. Players can no longer join!" ) self.tournament.status = Status.Closed Log("Tournament Closed", description= f"{ctx.author.mention} closed **{self.tournament.name}**.", color=Color.dark_orange()) await self.tournament.msg.clear_reactions() embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed)
async def edit(self, ctx, modifier, *, value): i = ModifierCheck(modifier, self.tournament.modifiers) if i is False: raise commands.BadArgument(f"`{modifier}` is not active.") modifier = self.tournament.modifiers[i] if isinstance(modifier, str): raise commands.BadArgument( f"The value for `{modifier}` cannot be edited.") old_value = modifier['value'] j = self.modifiers[ModifierCheck(modifier['name'], self.modifiers)] modifier['value'] = await ModifierUtils.convert_value( ctx, j['value'], value) if old_value == modifier['value']: await ctx.send("Nothing changed. Silly!") return await ctx.send( f"{Emote.check} The value for `{modifier['name']}` was changed to **{modifier['value']}**." ) fields = [{ 'name': "Old Value", 'value': old_value }, { 'name': "New Value", 'value': modifier['value'] }] Log("Modifier Edited", description= f"{ctx.author.mention} changed the value of `{modifier['name']}` for **{self.tournament.name}**.", color=Color.dark_teal(), fields=fields)
def __init__(self, client: motor.motor_asyncio.AsyncIOMotorClient, db_name: str): self.log = Log(self.__class__.__name__) self.client = client self.db_name = db_name self.db = self.client[self.db_name] self._collections = {}
async def x(index): log = Log(f"{from_}=>{to_}#{index}") retries = retries_ while True: found = False async for item in db.choose(M, {FIELD_NAME: from_}, {FIELD_NAME: to_}, limit_=limit): log.info(item=item) processed[(from_, to_)] += 1 await asyncio.sleep(sleep_time) found = True if found: break if retries == 0: return retries -= 1 log.warning(retry=retries_ - retries) await asyncio.sleep(sleep_time * sleep_coef) log.important("STOP")
async def rw(self, ctx, users): if self.tournament.status != 4: raise commands.BadArgument( "The tournament must have begun in order to add winners.") u_list = users.split(",") for user in u_list: user = await self._parse_player(ctx, user) if user not in self.tournament.participants and user != self.tournament.host: raise commands.BadArgument( f"**{user.name}** is not in the tournament.") if user not in self.tournament.winners: raise commands.BadArgument(f"**{user.name}** is not a winner.") self.tournament.winners.remove(user) await ctx.send( f":heavy_minus_sign: Removed **{user.name}** from the winners." ) Log("Winner Removed", description= f"{ctx.author.mention} removed {user.mention} from the winners of **{self.tournament.name}**.", color=Color.from_rgb(200, 200, 0))
async def on_command_error(ctx: commands.Context, error): if isinstance(error, commands.errors.BadArgument): # Bad Argument Raised e = str(error).replace('"', '`') await ctx.send(f"{Emote.deny} {e}") return # Missing Required Argument Raised if isinstance(error, commands.errors.MissingRequiredArgument): await ctx.send( f"{Emote.deny} **Missing Required Argument** \nThis command requires more arguments. Try again by " f"providing a `{error.param}` parameter this time!") return if isinstance(error, commands.errors.NotOwner): print("Someone tried to use an owner command!") return if isinstance(error, TournamentJoinException): message = f"{Emote.deny} {ctx.author.mention}, {str(error)}" await ctx.send(message, delete_after=10) Log("Tournament Join Failed", color=discord.Color.dark_red(), fields=[{'name': "Denial Message", 'value': message}]) return if isinstance(error, commands.errors.CommandNotFound): return if isinstance(error, MissingPermissions): if ctx.command.qualified_name == "setign": await ctx.send("I think the command you are looking for is `;ign`. Try it!") return if isinstance(error, InvalidChannel): await ctx.send(f"You cannot use this command here. Move to {Channel(client).bot_cmds.mention} and try again!") return if isinstance(error, OperationalError) and error.args[0] == "database is locked": await ctx.send("Database is locked. Attempting to fix this, type your command again to retry...") client.get_cog("Debug").unlock_db() return # None of previously mentioned errors embed = discord.Embed(title="An error occured!", description="An unexecpted problem was encountered! The issue has automatically been " "reported. Sorry for the incovenience!", color=discord.Color.red()) await ctx.send(embed=embed) try: await send_traceback(ctx, error) except Exception as e: await Channel(client).error_logs.send( "Unable to send to send full traceback: " f"\nCause: `{str(type(e))}: {str(e)}`" f"\nMinimal Traceback: `{str(type(error))}: {str(error)}`") finally: traceback.print_exception(type(error), error, error.__traceback__)
async def tplan(self, ctx): if self.tournament.status != Status.Pending: raise commands.BadArgument( f"The tournament cannot be scheduled at the moment.") req = ['name', 'host', 'time'] missing = [] for attr in req: if getattr(self.tournament, attr) is None: missing.append("`" + attr + "`") if missing: items = " and ".join(item for item in missing) raise commands.BadArgument( f"You have not specified a {items} for the tournament.") embed = Embed(title=self.tournament.name, color=Color.orange()) embed.set_author(name="Tournament Scheduled") for attr in self.attr: val = getattr(self.tournament, attr) if attr == 'time': val = val.strftime("%A %d %b at %I:%M%p *GMT*") if attr == 'host': val = val.mention if attr not in ['name', 'roles'] and val is not None: embed.add_field(name=attr.title(), value=val) embed.set_footer( text= f"This tournament will take place in {TimeUntil(self.tournament.time)}!" ) await ctx.message.add_reaction(Emote.check) await self.channels.t_planned.send( f"New tournament scheduled! {self.roles.schedule.mention}", embed=embed) # Add stuff and Log Log("Tournament Planned", description= f"{ctx.author.mention} scheduled **{self.tournament.name}**.", color=Color.orange(), fields=[{ "name": "Host", "value": self.tournament.host }, { "name": "Time", "value": self.tournament.time }]) self.tournament.status = Status.Scheduled self.tournament.save() await ctx.send("Tournament ID: " + str(self.tournament.id)) if self.tournament not in self.queue: self.queue.append(self.tournament) self.tournament = Tournament()
def __init__(self, name: str, ts: InpT, vs: Optional[InpT] = None): self.name = name self.log = Log(f"TimeSeries:{name}") if vs is None: self.ts, self.vs = np.unique(ts, return_counts=True) else: self.ts, self.vs = ts, vs assert isinstance(self.ts, np.ndarray) assert isinstance(self.vs, np.ndarray) assert len(self.ts) == len(self.vs)
def __init__(self, addr, port): self.addr = addr self.port = port self.log = Log(f"Monitoring") self._pages: Dict[str, BasePage] = {} self.main_page = MainPage("_main", "Info") self.add_page(self.main_page) self.app: web.Application = None self._middleware = []
def __init__(self): self.log = Log("RedirectServer") self.app: web.Application = None self.runner: web.AppRunner = None self.site: web.TCPSite = None self.template: str = None self.data = None self.data_received = Event() self.address = "localhost" self.port = randint(8081, 9000)
def __init__(self, servers, leaderID): self.servers = servers self.sockets = {} self.leaderID = leaderID self.term = 1 self.log = Log(None, None, None, True) for server in self.servers.items(): serverID, IP_port = server self.createSocket(IP_port[0], IP_port[1], serverID) self.initServerThreads()
def __init__(self, config_vk): self.log = Log("VK") self.config = config_vk self.additional_params = { 'access_token': self.config.token, 'lang': 'ru', 'v': "5.103" } self.person_fields = ",".join([ "first_name", "last_name", "deactivated", "verified", "sex", "bdate", "city", # TODO: https://vk.com/dev/places.getCityById "country", # TODO: https://vk.com/dev/places.getCountryById "home_town", "photo_400_orig", "online", "has_mobile", "contacts", "education", "universities", "schools", "last_seen", "occupation", "hidden", ]) self.group_info_fields = ",".join([ 'id', 'name', 'type', 'photo_200', 'city', 'description', 'place' ]) self.post_fields = ",".join([]) self.session: aiohttp.ClientSession = None self.last_call = 0 self.threshold = 1 / 3 self._update_token = None self.query_lock = asyncio.Lock() self.stats = VKStats('vk', "VK API") self.auth_lock = asyncio.Lock()
async def cancel(self, ctx): if self.tournament.status not in (1, 3, 4): raise commands.BadArgument("The tournament has not started.") await ctx.send( f"Are you sure you want to cancel **{self.tournament.name}**? `yes`/`no`" ) def check(m): return m.author == ctx.message.author and m.channel == ctx.message.channel try: msg = await self.client.wait_for('message', check=check, timeout=30) except asyncio.TimeoutError: raise commands.BadArgument("Command cancelled.") if msg.content.lower() == "no": raise commands.BadArgument( "Alright, the tournament will not be cancelled.") if msg.content.lower() != "yes": raise commands.BadArgument( "Invalid choice. Please type the command again to retry.") cancel_msg = await ctx.send(":flag_white: Cancelling...") try: self.queue.remove(self.tournament) except ValueError: pass if self.tournament.status in (3, 4): await self.cleanup() await self.client.get_command("nto").__call__(ctx) else: await self.update_reminders() try: await cancel_msg.edit(content=":flag_white: Tournament cancelled.") except HTTPException: pass Log("Tournament Cancelled", description= f"{ctx.author.mention} cancelled **{self.tournament.name}**.", color=Color.from_rgb(40, 40, 40)) self.tournament.status = Status.Cancelled self.tournament.save() self.tournament = Tournament()
async def join(self, ctx): await self.CheckRequirements(ctx.author) player_count = len(self.tournament.get_participants()) mod_index = ModifierCheck("MaxParticipants", self.tournament.modifiers) if mod_index is not False: max_count = self.tournament.modifiers[mod_index]['value'] else: max_count = 15 # Default if player_count >= max_count: raise TournamentJoinException( f"the tournament is full! The maximum number of participants is **{str(max_count)}**." ) join_msg = f"{Emote.join} {ctx.author.mention} joined. **{str(player_count + 1)}** players are now ready." if player_count == 0: # First join, make singular i = join_msg[-35:].index("s are") + len(join_msg) - 35 join_msg = join_msg[:i] + " is" + join_msg[i + 5:] user = User.fetch_by_id(ctx, ctx.author.id) if user.participations == 0: join_msg += "\nThis is the first tournament they are participating in. Welcome! 🎉" await SendFirstTournamentMessage(ctx) if user.ign is None: join_msg += "\nThis player does not have an IGN set yet." else: join_msg += f"\nIGN: `{user.ign}`" ign_cache[ctx.author.id] = user.ign await ctx.author.add_roles(self.roles.participant) await ctx.author.remove_roles(self.roles.spectator) await self.channels.t_chat.send(join_msg) Log("Participant Joined", description= f"{ctx.author.mention} joined **{self.tournament.name}**.", color=Color.dark_green(), fields=[{ 'name': "Player Count", 'value': str(player_count + 1) }]) self.tournament.add_participant(ctx.author) if ctx.author in self.tournament.spectators: self.tournament.spectators.remove(ctx.author) embed = UpdatedEmbed(self.tournament) await self.tournament.msg.edit(embed=embed) await self.checklist.update_text(ctx, self.tournament)
async def treset(self, ctx): if self.tournament.status in (2, 3, 4): raise commands.BadArgument( f"The tournament is ongoing and cannot be reset. Please try to use `;cancel` instead." ) self.tournament = Tournament() await ctx.send( f"{Emote.check} The tournament has succesfully been reset.") Log("Tournament Reset", description= f"{ctx.author.mention} has reset the tournament to default values.", color=Color.dark_red())
def testDeletePrevEntries(self): log = Log(10**8, 10**8, None) iteratorIDs = [0, 1] log.initIterators(iteratorIDs, []) func = print args = [1, 2] params_1 = [0, 1, 2, 3, 4, 5] shm_name, entry_size = log.createLogEntry(func, args, params_1) reference_1 = {} reference_1['func'], reference_1['args'] = func, args reference_1['logIndex'], reference_1['currentTerm'], reference_1[ 'prevLogIndex'] = params_1[0], params_1[1], params_1[2] reference_1['prevLogTerm'], reference_1['commitIndex'], reference_1[ 'leaderID'] = params_1[3], params_1[4], params_1[5] reference_1['shm_name'], reference_1['shm_size'], reference_1[ 'isCommitted'] = shm_name, entry_size, False params_1_extended = params_1 + [entry_size, False] log.addEntry(shm_name, params_1_extended) func = print args = [2, 3, 4] params_2 = [1, 2, 3, 4, 5, 6] shm_name, entry_size = log.createLogEntry(func, args, params_2) reference_2 = {} reference_2['func'], reference_2['args'] = func, args reference_2['logIndex'], reference_2['currentTerm'], reference_2[ 'prevLogIndex'] = params_2[0], params_2[1], params_2[2] reference_2['prevLogTerm'], reference_2['commitIndex'], reference_2[ 'leaderID'] = params_2[3], params_2[4], params_2[5] reference_2['shm_name'], reference_2['shm_size'], reference_2[ 'isCommitted'] = shm_name, entry_size, False params_2_extended = params_2 + [entry_size, False] log.addEntry(shm_name, params_2_extended) entry_0 = log.jump(0, 2, getNode=True) self.assertEqualEntry(log, entry_0, reference_2) log.deleteAllPrevEntries(entry_0) self.assertEqual(len(log), 3, "len(log) should be 3") entry_1 = log.jump(1, 2, getNode=True) log.deleteAllPrevEntries(entry_0) self.assertEqual(len(log), 1, "len(log) should be 1") self.assertEqual(log.nodeSizes[0], reference_2['shm_size'], 'shm_size does not match for reference') log.deleteAllEntries() self.assertEqual(len(log), 0, "len(log) should be 0")
def __init__(self, max_size: int): # TODO: Less logs self.log = Log("TasksManager") self.size = max_size self._tasks = asyncio.Queue(self.size) self._results = asyncio.Queue(self.size) self._exceptions = asyncio.Queue(self.size) self.is_run = True self.executors = [ asyncio.create_task(self._executor(i)) for i in range(max_size) ]
async def start(self, ctx): if self.tournament.status >= 3: raise commands.BadArgument("The tournament has already started.") req = ('name', 'host') missing = [] for attr in req: if getattr(self.tournament, attr) is None: missing.append("`" + attr + "`") if missing: items = " and ".join(item for item in missing) raise commands.BadArgument( f"You have not specified a {items} for the tournament.") if self.tournament.time is None: self.tournament.time = datetime.utcnow() await self.tournament.host.add_roles(self.roles.temp_host) host_id = self.tournament.host.id ign_cache[host_id] = User.fetch_attr_by_id(host_id, "IGN") User.fetch_attr_by_id(host_id, "IGN") await ctx.message.add_reaction(Emote.check) Log("Tournament Started", description= f"{ctx.author.mention} started **{self.tournament.name}**.", color=Color.green()) self.tournament.status = Status.Opened embed = UpdatedEmbed(self.tournament) try: msg = await self.channels.t_channel.fetch_message( self.channels.t_channel.last_message_id) await msg.delete() except (AttributeError, NotFound): pass self.tournament.msg = await self.channels.t_channel.send( f"Tournament **{self.tournament.name}** has started!" f" {self.roles.tournament.mention}", embed=embed) await self.tournament.msg.add_reaction(Emote.join) if ModifierCheck("SpectatorsAllowed", self.tournament.modifiers) is not False: await self.tournament.msg.add_reaction("📽️") self.checklist = await Checklist.create(ctx)
def testInit(self): log = Log(10**8, 10**8, None) iteratorIDs = [0, 1] log.initIterators(iteratorIDs, []) self.assertEqual(list(log.ptrs.keys()), [0, 1], "Iterator IDs do not match within log.ptrs") self.assertEqual(log.ptrs[0][0].value, 0, "log.first is not None from log.ptrs[0][0]") self.assertEqual(log.ptrs[1][0].value, 0, "log.first is not None from log.ptrs[1][0]") self.assertEqual(log.ptrs[0][1], 0, "log.ref_point is not 0 from log.ptrs[0][0]") self.assertEqual(log.ptrs[1][1], 0, "log.ref_point is not 0 from log.ptrs[1][0]")
def LoadConfig(file_name: str = None) -> "Config": log = Log("LoadConfig") file_name = file_name or "private.yaml" log.info("Load config", source=file_name) with open(file_name, "rt") as f: data = yaml.safe_load(f) def do_update(): log.info("Update config file", source=file_name) with open(file_name, "wt") as f: yaml.safe_dump(data, f) return Config(data, do_update, "", source=file_name)
class Funcs: logger = Log("Funcs") @staticmethod def eq(grid: Grid, pos): yield pos, 1 eq.__name__ = "⊜" @staticmethod def simple(grid: Grid, pos): yield grid[pos], 1 simple.__name__ = "dridded" @staticmethod def divide(grid: Grid, pos): left = grid[pos] right = grid.right(left) yield left, (pos - left) / grid.step yield right, (right - pos) / grid.step divide.__name__ = "divided" @classmethod def spline(cls, size): if size == 1: cls.logger.warning("Do not use spline method with", size=size) def _(grid: Grid, pos): width = size * grid.step half = width / 2 current = grid[pos - half] while True: coef = (current - pos) / width + 0.5 if coef >= 1: break elif coef > 0: yield current, spline_dist_f(coef) / size * 4 current = grid.right(current) _.__name__ = f"spline_{size}" return _
class _UidAttribute(ModelAttribute): logger = Log("_UidAttribute") def __init__(self): super().__init__(description="UID calculated attribute for MongoDB", default=None, uid=True) @property def is_uid_attribute(self): return True @property def is_id_alias(self): return False @property def name(self): return "_id" @name.setter def name(self, value): if value is not None: if value != '_id': raise ValueError("Use `ModelAttribute(uid=True)`") @staticmethod def _hash_method(w): import hashlib h = hashlib.sha3_512(bytes(w, 'UTF-8')) import base64 return base64.encodebytes(h.digest()).decode("UTF-8").replace("\n", "") def __get__(self, instance: "Model", owner: Type["Model"]): if instance is None: return self aliases = sorted(instance.__uids__.keys()) storage_value = super(_UidAttribute, self).__get__(instance, owner) if len(aliases) != 0 and storage_value is not None: raise ValueError("Not alowed to directly change _id field") if len(aliases) == 0: return storage_value s = "/".join(str(value := getattr(instance, key)) + ":" + type(value).__name__ for key in aliases)
def __init__(self): work_name = self.__class__.__name__ self.log = Log(work_name) self.log.debug("Register work") self.work_ids.setdefault(work_name, -1) self.work_ids[work_name] += 1 work_id = f"{work_name}_{self.work_ids[work_name]}" self.log.debug("Work registered", work_id=work_id) self.stat = Stats(work_id, work_name) self.log.debug("Run task manager") self.task_manager = TasksManager(self.PARALLEL) self.tasks: List[TaskInfo] = [] self.state = "Base class initialized"
async def remove(self, ctx, modifier): i = ModifierCheck(modifier, self.tournament.modifiers) if i is False: raise commands.BadArgument( f"Modifier `{modifier}` is not active on this tournament.") old = self.tournament.modifiers[i] self.tournament.modifiers.pop(i) await ctx.send(f"{Emote.check} `{modifier}` has been removed.") fields = [] if isinstance(old, dict): fields.append({'name': "Old Value", 'value': old['value']}) Log("Modifier Removed", description= f"{ctx.author.mention} has removed `{modifier}` from **{self.tournament.name}**.", color=Color.dark_teal(), fields=fields)
async def setign(self, ctx, member: discord.Member, ign): user = User.fetch_by_id(ctx, member.id) old_ign = user.ign user.ign = ign self.client.get_cog("TOrganizer").cache_ign(member, ign) await ctx.send( f"{Emote.check} {ctx.author.mention}, **{member.name}**'s IGN has been set to `{ign}`." ) Log("IGN Set (Staff)", description= f"{ctx.author.mention} has set {member.mention}'s IGN to `{ign}`.", color=0x4a0dff, fields=[{ 'name': 'Previous IGN', 'value': old_ign }])
async def _set(self, ctx, stat, user: discord.Member, amount: int): if stat not in STATS_LIST: raise commands.BadArgument( f"The `{stat}` stat doesn't exist! Check your spelling and" " make sure everything is lowercase!") profile = User.fetch_by_id(ctx, user.id) current = getattr(profile, stat) setattr(profile, stat, amount) await ctx.send( f"{Emote.check} Set **{user.name}**'s {stat} to {str(amount)}.") Log(title=f"{stat.capitalize()} Set", description= f"{ctx.author.mention} set {user.mention}'s {stat} to {str(amount)}.", fields=[{ "name": "Value", "value": f"{str(current)} -> {str(amount)}" }], color=discord.Color.orange())