async def execute_time_triggers(self, scope, command, options, lines, **kwargs): """ List all time triggers. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("__**List of time triggers**__") with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT id, script, start_time as 'start_time_ [timestamp]' FROM " + scope.shell.dbtable("time_triggers") + " WHERE discord_sid = ? ORDER BY start_time", [int(scope.server.id)]): start_time = timezone('UTC').localize(row[2]) start_time = start_time.astimezone(timezone('Europe/Paris')) await stream.send("\n\n:timer: **Time trigger #" + str(row[0]) + ":** `" + start_time.strftime("%Y-%m-%d %H:%M:%S") + "`\n```\n" + row[1] + "\n```") await stream.finish()
async def execute_boards(self, scope, command, options, lines, **kwargs): """ List all boards. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("**List of boards**\n") with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT name, discord_cid FROM " + scope.shell.dbtable("boards") + " WHERE discord_sid = ? ORDER BY name", [int(scope.guild.id)]): chan = scope.shell.find_channel(str(row[1]), scope.guild) if not chan: continue if scope.permission < praxisbot.UserPermission.Script and not chan.permissions_for( scope.user).read_messages: continue await stream.send("\n - `" + row[0] + "` in " + chan.mention) await stream.finish()
async def execute_role_members(self, scope, command, options, lines, **kwargs): """ Display members of a role. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) parser.add_argument('role', help='Role to edit.') args = await self.parse_options(scope, parser, options) if not args: return role = scope.shell.find_role(args.role, scope.server) if not role: await scope.shell.print_error( scope, "Role `" + args.role + "` not found.") return stream = praxisbot.MessageStream(scope) await stream.send("__**Members of the role " + role.name + "**__\n") members = [] for m in scope.server.members: for r in m.roles: if r.id == role.id: members.append(m.name + "#" + m.discriminator) break members.sort() for m in members: await stream.send_monospace("\n" + m) await stream.finish()
async def execute_cf_sessions(self, scope, command, options, lines, **kwargs): """ List active conversational sessions """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("__**List of conversational sessions**__") for s in self.sessions: if scope.guild.id != s[2]: continue user = scope.shell.find_member(s[0], scope.guild) if not user: continue channel = scope.shell.find_channel(s[1], scope.guild) if not channel: continue await stream.send("\n\n:speech_balloon: **Session with "+user.name+"#"+user.discriminator+" in "+channel.mention+"**") await stream.send("\n - Current node: "+self.sessions[s].current_node) await stream.send("\n - Start time: "+self.sessions[s].start_time.strftime("%Y-%m-%d %H:%M:%S")) await stream.send("\n - Last execution time: "+self.sessions[s].last_time.strftime("%Y-%m-%d %H:%M:%S")) await stream.finish()
async def execute_message_triggers(self, scope, command, options, lines, **kwargs): """ List all message triggers. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("__**List of message triggers**__") with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT id, script, regex FROM " + scope.shell.dbtable("message_triggers") + " WHERE discord_sid = ?", [int(scope.server.id)]): await stream.send("\n\n**:scroll: Message trigger #" + str(row[0]) + ":** `" + row[2] + "`\n```\n" + row[1] + "\n```") await stream.finish()
async def execute_list_channels(self, scope, command, options, lines, **kwargs): """ List all channels of the server. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) parser.add_argument( '--user', help='List channels from the point of view of this user.') args = await self.parse_options(scope, parser, options) if not args: return if not args.user: user = scope.user else: user = scope.shell.find_member(args.user, scope.server) if not user: await scope.shell.print_error(scope, "User not found.") return clist = [] for c in scope.server.channels: if c.permissions_for( scope.user).read_messages and c.permissions_for( user).read_messages: if c.type == discord.ChannelType.text: pos = (c.position + 1) * 10 cat = c.server.get_channel(c.parent_id) if cat: pos = pos + 1000 * (cat.position + 1) if c.permissions_for(user).send_messages: clist.append((pos, " :pencil2: " + c.name)) else: clist.append((pos, " :eye: " + c.name)) elif c.type == discord.ChannelType.voice: pos = (c.position + 1) * 10 cat = c.server.get_channel(c.parent_id) if cat: pos = pos + 1000 * (cat.position + 1) clist.append((pos, " :microphone2: " + c.name)) elif c.type == discord.ChannelType.category: pos = (c.position + 1) * 1000 clist.append((pos, "\n**" + c.name + "**")) clist = sorted(clist, key=lambda x: x[0]) stream = praxisbot.MessageStream(scope) for c in clist: await stream.send(c[1] + "\n") await stream.finish()
async def execute_polls(self, scope, command, options, lines, **kwargs): """ List all current polls. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("__**List of polls**__") with scope.shell.dbcon: c0 = scope.shell.dbcon.cursor() c1 = scope.shell.dbcon.cursor() for row in c0.execute( "SELECT id, description, discord_cid, end_time as 'end_time_ [timestamp]' FROM " + scope.shell.dbtable("polls") + " WHERE discord_sid = ? ORDER BY end_time", [int(scope.guild.id)]): chan = scope.shell.find_channel(str(row[2]), scope.guild) chan_name = "an unknown channel" if chan: chan_name = chan.mention end_time = timezone('UTC').localize(row[3]) end_time = end_time.astimezone(timezone('Europe/Paris')) counter = scope.shell.get_sql_data("votes", ["COUNT(id)"], {"poll": row[0]}) await stream.send("\n\n:bar_chart: **Poll #" + str(row[0]) + " in " + chan_name + "**") await stream.send("\n - Closing time: " + end_time.strftime("%Y-%m-%d %H:%M:%S")) choices = [] for choice in c1.execute( "SELECT emoji, description FROM " + scope.shell.dbtable("poll_choices") + " WHERE poll = ?", [row[0]]): choices.append(choice[0] + " " + choice[1]) await stream.send("\n - Voters: " + str(counter[0])) await stream.send("\n - Choices: " + ", ".join(choices)) if len(row[1]) > 0: description = "```\n" + row[1] + "\n```" await stream.finish()
async def execute_help(self, scope, command, options, lines, **kwargs): """ Help page of PraxisBot. """ stream = praxisbot.MessageStream(scope) for p in scope.shell.plugins: await stream.send("\n**" + p.name + "**\n\n") for c in p.cmds: desc = inspect.getdoc(p.cmds[c]) if desc: await stream.send(" - `" + c + "` : " + desc + "\n") else: await stream.send(" - `" + c + "`\n") await stream.finish()
async def execute_emojis(self, scope, command, options, lines, **kwargs): """ List of all custom emojis """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("**List of emojis**\n") for e in scope.server.emojis: await stream.send("\n - <:" + e.name + ":" + e.id + "> `" + e.name + "`") await stream.finish()
async def execute_mod_levels(self, scope, command, options, lines, **kwargs): """ List all moderator levels. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return scope stream = praxisbot.MessageStream(scope) await stream.send("**__List of moderator levels__**\n") with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT name, priority, ban_timelimit, ban_prioritylimit, purge FROM " + scope.shell.dbtable("mod_levels") + " WHERE discord_sid = ? ORDER BY priority DESC", [int(scope.server.id)]): await stream.send("\n:label: **" + row[0] + "**") await stream.send("\n - Priority: " + str(row[1])) if not row[2] or row[2] < 0: tlimit = 0 else: tlimit = row[2] await stream.send("\n - Duration bewteen two bans: " + str(tlimit) + "h") if not row[3] or row[3] < 0: plimit = row[1] - 1 else: plimit = min(row[3], row[1]) await stream.send( "\n - Maximum priority that can be banned: " + str(plimit)) if not row[4] or row[4] <= 0: purge = "Can't use purge command" else: purge = "Can use purge command" await stream.send("\n - " + purge) await stream.finish()
async def execute_cf_nodes(self, scope, command, options, lines, **kwargs): """ List all nodes and links """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) with scope.shell.dbcon: c0 = scope.shell.dbcon.cursor() c1 = scope.shell.dbcon.cursor() await stream.send("__**List of nodes**__") for row in c0.execute("SELECT name, script FROM "+scope.shell.dbtable("cf_nodes")+" WHERE discord_sid = ? ORDER BY name", [int(scope.guild.id)]): await stream.send("\n\n:triangular_flag_on_post: **"+row[0]+"**") for link in c1.execute("SELECT node_start, script FROM "+scope.shell.dbtable("cf_links")+" WHERE discord_sid = ? AND node_start = ? AND node_end == node_start ORDER BY node_start, priority DESC", [int(scope.guild.id), str(row[0])]): await stream.send("\n - Self link: **"+str(row[0])+"** → **"+str(row[0])+"**") for link in c1.execute("SELECT node_start, script FROM "+scope.shell.dbtable("cf_links")+" WHERE discord_sid = ? AND node_end = ? AND node_end != node_start ORDER BY node_start, priority DESC", [int(scope.guild.id), str(row[0])]): await stream.send("\n - Incoming link: "+link[0]+" → **"+str(row[0])+"**") for link in c1.execute("SELECT node_end, script FROM "+scope.shell.dbtable("cf_links")+" WHERE discord_sid = ? AND node_start = ? AND node_end != node_start ORDER BY node_end, priority DESC", [int(scope.guild.id), str(row[0])]): await stream.send("\n - Outcoming link: **"+str(row[0])+"** → "+link[0]) if len(row[1]) > 0: await stream.send("\n - Script:") await stream.send("\n```\n"+row[1]+"\n```") await stream.send("\n\n__**List of links**__") for row in c0.execute("SELECT node_start, node_end, script, type, value, priority FROM "+scope.shell.dbtable("cf_links")+" WHERE discord_sid = ? ORDER BY node_start, node_end", [int(scope.guild.id)]): await stream.send("\n\n:link: **"+row[0]+" → "+row[1]+"**") await stream.send("\n - Priority: "+str(row[5])) if row[3] == LinkType.UserRegex: await stream.send("\n - Condition: user message match `"+row[4]+"`") elif row[3] == LinkType.Timeout: await stream.send("\n - Condition: timeout of "+row[4]+"") elif row[3] == LinkType.Reaction: await stream.send("\n - Condition: reaction added "+row[4]+"") if len(row[2]) > 0: await stream.send("\n - Script:") await stream.send("\n```\n"+row[2]+"\n```") await stream.finish()
async def execute_variables(self, scope, command, options, lines, **kwargs): """ List all current variables. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("**List of variables**\n") for v in scope.vars: if scope.vars[v].find("\n") >= 0: await stream.send("\n" + v + " = \n```" + scope.vars[v] + "```") else: await stream.send("\n" + v + " = `" + scope.vars[v] + "`") await stream.finish()
async def execute_last_bans(self, scope, command, options, lines, **kwargs): """ List last bans. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return scope stream = praxisbot.MessageStream(scope) await stream.send("**__Last bans__**") bans = await scope.shell.client.get_ban_logs(scope.server, limit=5) for b in bans: author = b.author target = b.target reason = b.reason if b.author.id == scope.shell.client.user.id: #Try to find the true author in the reason res = re.search("(.+#[0-9][0-9][0-9][0-9]) using ban command", b.reason) if res: u = scope.shell.find_member(res.group(1), scope.server) if u: author = u res = re.search("using ban command:(.+)", b.reason) if res: reason = res.group(1).strip() await stream.send("\n\n**" + target.name + "#" + target.discriminator + " by " + author.name + "#" + author.discriminator + "**\n" + reason) await stream.finish()
async def execute_last_bans(self, scope, command, options, lines, **kwargs): """ List last bans. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return scope stream = praxisbot.MessageStream(scope) await stream.send("**__Last bans__**") async for b in scope.guild.audit_logs( action=discord.AuditLogAction.ban, limit=5): user = b.user target = b.target reason = b.reason if b.user.id == scope.shell.client.user.id: #Try to find the true author (user) in the reason res = re.search("(.+#[0-9][0-9][0-9][0-9]) using ban command", b.reason) if res: u = scope.shell.find_member(res.group(1), scope.guild) if u: user = u res = re.search("using ban command:(.+)", b.reason) if res: reason = res.group(1).strip() await stream.send("\n\n**{}#{} by {}#{}**\n{}".format( target.name, target.discriminator, user.name, user.discriminator, reason)) await stream.finish()
async def display_counters(self, scope, counters, counter_max, title, format): stream = praxisbot.MessageStream(scope) await stream.send("__**" + title + "**__") for counter in counters: text = "\nFrom " start_date = counter["start_date"] start_date = timezone('UTC').localize(start_date) start_date = start_date.astimezone(timezone('Europe/Paris')) text = text + start_date.strftime(format) text = text + " to " end_date = counter["end_date"] end_date = timezone('UTC').localize(end_date) end_date = end_date.astimezone(timezone('Europe/Paris')) text = text + end_date.strftime(format) text = text + " " if counter_max > 0: nb_box = int(20.0 * counter["counter"] / counter_max) nb_empty = 20 - nb_box else: nb_box = 0 nb_empty = 20 for i in range(0, nb_box): text = text + "█" for i in range(0, nb_empty): text = text + "▁" text = text + " " + str(counter["counter"]) + " messages" await stream.send_monospace(text) await stream.finish()
async def execute_commands(self, scope, command, options, lines, **kwargs): """ List all custom commands. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("__**List of commands**__\n") with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT command FROM " + scope.shell.dbtable("triggers") + " WHERE discord_sid = ? ORDER BY command", [int(scope.server.id)]): if row[0].find("@") != 0: await stream.send("\n - " + row[0]) await stream.finish()
async def execute_cookies(self, scope, command, options, lines, **kwargs): """ List all cookies. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return stream = praxisbot.MessageStream(scope) await stream.send("**List of HTTP cookies**\n") with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT nameid, filter FROM " + scope.shell.dbtable("cookies") + " WHERE discord_sid = ? ORDER BY name", [int(scope.server.id)]): await stream.send("\n - " + row[0] + ": `" + row[1] + "`") await stream.finish()
async def execute_whois(self, scope, command, options, lines, **kwargs): """ Get all available informations about an user. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) parser.add_argument('user', help='An user') parser.add_argument('--channel', '-c', help='Channel where to send the message') args = await self.parse_options(scope, parser, options) if not args: return if args.channel: chan = scope.shell.find_channel( scope.format_text(args.channel).strip(), scope.server) else: chan = scope.channel if not chan: await scope.shell.print_error(scope, "Unknown channel.") return if scope.permission < praxisbot.UserPermission.Script and not chan.permissions_for( scope.user).send_messages: await scope.shell.print_permission( scope, "You don't have write permission in this channel.") return u = scope.shell.find_member(scope.format_text(args.user), scope.server) if not u: await scope.shell.print_error( scope, "User not found. User name must be of the form `@User#1234` or `User#1234`." ) return e = discord.Embed() e.type = "rich" e.set_author(name=u.name + "#" + u.discriminator, icon_url=u.avatar_url.replace(".webp", ".png")) e.set_thumbnail(url=u.avatar_url.replace(".webp", ".png")) e.add_field(name="Nickname", value=str(u.display_name)) e.add_field(name="Discord ID", value=str(u.id)) if u.colour.value != 0: e.colour = u.colour e.add_field(name="Created since", value=str(datetime.datetime.utcnow() - u.created_at)) e.add_field(name="Joined since", value=str(datetime.datetime.utcnow() - u.joined_at)) if u.server_permissions.administrator: e.add_field(name="Administrator", value=":crown: Yes") if u.server_permissions.manage_server: e.add_field(name="Manage server", value=":tools: Yes") if u.server_permissions.manage_channels: e.add_field(name="Manage channels", value=":tools: Yes") if u.server_permissions.manage_messages: e.add_field(name="Manage messages", value=":speech_balloon: Yes") if u.server_permissions.view_audit_logs: e.add_field(name="View audit logs", value=":eye: Yes") if u.server_permissions.ban_members: e.add_field(name="Ban members", value=":punch: Yes") if u.server_permissions.kick_members: e.add_field(name="Kick members", value=":punch: Yes") if u.server_permissions.mention_everyone: e.add_field(name="Mention everyone", value=":loudspeaker: Yes") try: counter = await scope.shell.client_human.count_messages( scope.server, author=u) e.add_field(name="Total messages", value=str(counter)) except: pass try: counter = await scope.shell.client_human.count_messages( scope.server, author=u, after=datetime.datetime.utcnow() - relativedelta(months=1)) e.add_field(name="Messages last month", value=str(counter)) except: pass roles = [] for r in u.roles: if not r.is_everyone: roles.append(r.name) if len(roles): e.add_field(name="Roles", value=", ".join(roles)) try: profile = await scope.shell.client_human.get_user_profile(u.id) stream = praxisbot.MessageStream(scope) for ca in profile.connected_accounts: url = ca.url if url: e.add_field(name=ca.provider_name, value=url) else: e.add_field(name=ca.provider_name, value=ca.name) except: pass await scope.shell.client.send_message(chan, "", embed=e)
async def execute_roles(self, scope, command, options, lines, **kwargs): """ List all roles. """ parser = argparse.ArgumentParser(description=kwargs["description"], prog=command) args = await self.parse_options(scope, parser, options) if not args: return roles = {} for r in scope.server.roles: if r.is_everyone: continue roles[r.id] = { "id": r.id, "name": r.name, "members": 0, "position": r.position, "type": RoleType.Default, "description": "", "mentionable": r.mentionable, "onlinelist": r.hoist, "autosort": 0, "autosync": 0, "color": r.colour.value } for m in scope.server.members: for r in m.roles: if r.id in roles: roles[r.id]["members"] = roles[r.id]["members"] + 1 with scope.shell.dbcon: c = scope.shell.dbcon.cursor() for row in c.execute( "SELECT discord_rid, type, description, autosync, autosort FROM " + scope.shell.dbtable("role_options") + " WHERE discord_sid = ?", [int(scope.server.id)]): rid = str(row[0]) if rid in roles: roles[rid]["type"] = row[1] roles[rid]["description"] = row[2] roles[rid]["autosync"] = row[3] roles[rid]["autosort"] = row[4] sorted_roles = sorted(roles.values(), key=lambda a: a["position"], reverse=True) stream = praxisbot.MessageStream(scope) await stream.send("__**List of roles**__\n") await stream.send( "\n**Properties:** :medal: visible in member list, :label: invisible in member list, :bell: mentionable, :no_bell: not mentionable, :art: colored, :black_circle: default color\n" ) role_above = 0 for r in sorted_roles: if r["type"] == RoleType.Separator: text = "\n\n**" + r["name"] + "**" if len(r["description"]) > 0: text = text + "\n" + r["description"] if r["autosort"] == 1: text = text + "\n:twisted_rightwards_arrows: Roles in this section are automatically sorted" if r["autosync"] == 1: text = text + "\n:arrows_counterclockwise: Permissions of roles in this section are automatically synced" text = text + "\n" await stream.send(text) else: icon = "" if r["onlinelist"]: icon = icon + ":medal:" else: icon = icon + ":label:" if r["mentionable"]: icon = icon + ":bell:" else: icon = icon + ":no_bell:" if r["color"] == 0: icon = icon + ":black_circle:" else: icon = icon + ":art:" description = "" if len(r["description"]) > 0: description = ": " + r["description"] await stream.send("\n" + icon + " **" + r["name"] + "**, " + str(r["members"]) + " members" + description) await stream.finish()