@@ -9,6 +9,8 @@ chatchart - Generates a pie chart to display chat activity over the last 5000 me
|
||||
|
||||
dungeon - New users with new accounts will be shuffled off to a locked channel on-join to help mitigate raiders. Please see the dungeon_readme.md file on this repo for more information.
|
||||
|
||||
joinleave - Alerts a set channel when an account under a certain age of days joins a server and leaves within the set time... any server the bot can see. This is a global cog with owner only commands. I wrote this for myself so I won't be adding user requests for the most part, and will be using it to combat the recent user scrapers found joining and leaving servers quickly.
|
||||
|
||||
inspirobot - Fetch "inspirational" messages from inspirobot.me with [p]inspireme.
|
||||
|
||||
nolinks - A very blunt hammer to remove anything that looks like a link. Roles can be whitelisted and it can watch multiple channels.
|
||||
|
||||
8
cah/__init__.py
Normal file
8
cah/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from redbot.core import commands, data_manager
|
||||
from .cah import CardsAgainstHumanity
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
n = CardsAgainstHumanity(bot)
|
||||
data_manager.load_bundled_data(n, __file__)
|
||||
bot.add_cog(n)
|
||||
1836
cah/cah.py
Normal file
1836
cah/cah.py
Normal file
File diff suppressed because it is too large
Load Diff
2434
cah/data/deck.json
Normal file
2434
cah/data/deck.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -119,6 +119,10 @@ class Chatchart(BaseCog):
|
||||
msg_data["users"][whole_name]["msgcount"] = 1
|
||||
msg_data["total count"] += 1
|
||||
|
||||
if msg_data['users'] == {}:
|
||||
await em.delete()
|
||||
return await ctx.message.channel.send(f'Only bots have sent messages in {channel.mention}')
|
||||
|
||||
for usr in msg_data["users"]:
|
||||
pd = float(msg_data["users"][usr]["msgcount"]) / float(msg_data["total count"])
|
||||
msg_data["users"][usr]["percent"] = round(pd * 100, 1)
|
||||
|
||||
@@ -75,7 +75,7 @@ class Dungeon(BaseCog):
|
||||
|
||||
@commands.group(autohelp=True)
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_server=True)
|
||||
@checks.admin_or_permissions(manage_guild=True)
|
||||
async def dungeon(self, ctx):
|
||||
"""Main dungeon commands."""
|
||||
pass
|
||||
@@ -380,7 +380,7 @@ class Dungeon(BaseCog):
|
||||
await member.send(auto_ban_msg)
|
||||
except discord.Forbidden:
|
||||
if announce_channel:
|
||||
return await channel_object.send(
|
||||
await channel_object.send(
|
||||
f"I couldn't DM {member} ({member.id}) to let them know they've been banned, they've blocked me."
|
||||
)
|
||||
else:
|
||||
@@ -460,6 +460,8 @@ class Dungeon(BaseCog):
|
||||
await member.add_roles(user_role_obj, reason="Adding member role to new user.")
|
||||
except discord.Forbidden:
|
||||
pass
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _dynamic_time(time):
|
||||
|
||||
5
joinleave/__init__.py
Normal file
5
joinleave/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from .joinleave import JoinLeave
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(JoinLeave(bot))
|
||||
256
joinleave/joinleave.py
Normal file
256
joinleave/joinleave.py
Normal file
@@ -0,0 +1,256 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
import discord
|
||||
import re
|
||||
from redbot.core import Config, commands, checks
|
||||
from redbot.core.utils.chat_formatting import bold
|
||||
|
||||
BaseCog = getattr(commands, "Cog", object)
|
||||
|
||||
|
||||
class JoinLeave(BaseCog):
|
||||
"""Report users that join and leave quickly, with new accounts."""
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.config = Config.get_conf(self, 2713731002, force_registration=True)
|
||||
|
||||
default_global = {
|
||||
"announce_channel": None,
|
||||
"join_days": 7,
|
||||
"toggle": False,
|
||||
"cooldown": 120,
|
||||
"pingrole": None,
|
||||
"pingserver": None,
|
||||
}
|
||||
|
||||
default_user = {"last_join": "2018-01-01 00:00:00.000001", "new": True}
|
||||
|
||||
self.config.register_user(**default_user)
|
||||
self.config.register_global(**default_global)
|
||||
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.is_owner()
|
||||
async def joinleave(self, ctx):
|
||||
"""Main joinleave commands."""
|
||||
pass
|
||||
|
||||
@joinleave.command()
|
||||
async def channel(self, ctx, channel: discord.TextChannel):
|
||||
"""Sets the announcement channel."""
|
||||
await self.config.announce_channel.set(channel.id)
|
||||
announce_channel_id = await self.config.announce_channel()
|
||||
await ctx.send(
|
||||
f"User announcement channel set to: {self.bot.get_channel(announce_channel_id).mention}."
|
||||
)
|
||||
|
||||
@joinleave.command()
|
||||
async def cooldown(self, ctx, cooldown_time: int = 0):
|
||||
"""Set the time window in seconds for a valid join/leave flag.
|
||||
|
||||
Leave time blank to reset to default (2m)."""
|
||||
cooldown = await self.config.cooldown()
|
||||
if not cooldown_time:
|
||||
await self.config.cooldown.set(120)
|
||||
await ctx.send("Join/leave time window reset to 2m.")
|
||||
else:
|
||||
await self.config.cooldown.set(cooldown_time)
|
||||
await ctx.send(
|
||||
f"Join/leave time window set to {self._dynamic_time(int(cooldown_time))}."
|
||||
)
|
||||
|
||||
@joinleave.command()
|
||||
async def days(self, ctx, days: int):
|
||||
"""Set how old an account needs to be a trusted user."""
|
||||
await self.config.join_days.set(days)
|
||||
await ctx.send(f"Users must have accounts older than {days} day(s) to be ignored.")
|
||||
|
||||
@joinleave.command()
|
||||
async def role(self, ctx, *, role_name: discord.Role = None):
|
||||
"""Set the role to ping on a first sighting. Leave blank to turn off."""
|
||||
if not role_name:
|
||||
await self.config.pingrole.set(None)
|
||||
await self.config.pingserver.set(None)
|
||||
return await ctx.send(
|
||||
"Role has been removed. No pinging will occur on a first sighting."
|
||||
)
|
||||
|
||||
await self.config.pingserver.set(ctx.guild.id)
|
||||
await self.config.pingrole.set(role_name.id)
|
||||
role_obj = discord.utils.get(ctx.guild.roles, id=await self.config.pingrole())
|
||||
await ctx.send(f"Pingable role set to: {role_obj.name}.")
|
||||
|
||||
@joinleave.command()
|
||||
async def settings(self, ctx):
|
||||
"""Show the current settings."""
|
||||
data = await self.config.all()
|
||||
|
||||
try:
|
||||
achannel = self.bot.get_channel(data["announce_channel"]).name
|
||||
except AttributeError:
|
||||
achannel = None
|
||||
joinleave_enabled = data["toggle"]
|
||||
join_days = data["join_days"]
|
||||
cooldown = data["cooldown"]
|
||||
pingrole_id = data["pingrole"]
|
||||
ping_guild = self.bot.get_guild(data["pingserver"])
|
||||
if not pingrole_id:
|
||||
pingrole = "None"
|
||||
else:
|
||||
try:
|
||||
pingrole_obj = discord.utils.get(ping_guild.roles, id=pingrole_id)
|
||||
pingrole = pingrole_obj.name
|
||||
except AttributeError:
|
||||
pingrole = "None"
|
||||
|
||||
msg = (
|
||||
"```ini\n---JoinLeave Settings--- \n"
|
||||
f"Announce Channel: [{achannel}]\n"
|
||||
f"Join/Leave Span: [{self._dynamic_time(int(cooldown))}]\n"
|
||||
f"Day Threshold: [{str(join_days)}]\n"
|
||||
f"Ping role: [{pingrole}]\n"
|
||||
f"JoinLeave Active: [{joinleave_enabled}]\n```"
|
||||
)
|
||||
|
||||
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, description=msg)
|
||||
return await ctx.send(embed=embed)
|
||||
|
||||
@joinleave.command()
|
||||
async def toggle(self, ctx):
|
||||
"""Toggle the joinleave on or off. This is global."""
|
||||
joinleave_enabled = await self.config.toggle()
|
||||
announce_channel = await self.config.announce_channel()
|
||||
if not announce_channel:
|
||||
await self.config.announce_channel.set(ctx.message.channel.id)
|
||||
await self.config.toggle.set(not joinleave_enabled)
|
||||
await ctx.send(f"JoinLeave enabled: {not joinleave_enabled}.")
|
||||
if not announce_channel:
|
||||
await ctx.send(f"JoinLeave report channel set to: {ctx.message.channel.mention}.")
|
||||
|
||||
async def on_member_join(self, member):
|
||||
global_data = await self.config.all()
|
||||
if not global_data["toggle"]:
|
||||
return
|
||||
|
||||
join_date = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f")
|
||||
now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
|
||||
since_join = now - join_date
|
||||
|
||||
if since_join.days < global_data["join_days"]:
|
||||
await self.config.user(member).last_join.set(str(now))
|
||||
|
||||
async def on_member_remove(self, member):
|
||||
user_data = await self.config.user(member).all()
|
||||
global_data = await self.config.all()
|
||||
if not global_data["toggle"]:
|
||||
return
|
||||
|
||||
channel_obj = self.bot.get_channel(global_data["announce_channel"])
|
||||
|
||||
if not channel_obj:
|
||||
print("joinleave.py: toggled on but no announce channel")
|
||||
return
|
||||
|
||||
last_time = datetime.datetime.strptime(str(user_data["last_join"]), "%Y-%m-%d %H:%M:%S.%f")
|
||||
|
||||
join_date = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f")
|
||||
now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
|
||||
since_join = now - join_date
|
||||
|
||||
if int((now - last_time).total_seconds()) < global_data["cooldown"]:
|
||||
await channel_obj.send(f"**{member.id}**")
|
||||
msg = f"User: {member} ({member.id})\nServer: {member.guild.name} ({member.guild.id})\nAccount is {self._dynamic_time(int(since_join.total_seconds()))} old"
|
||||
if user_data["new"]:
|
||||
await self.config.user(member).new.set(False)
|
||||
if not global_data["pingrole"]:
|
||||
return await channel_obj.send(f"\N{WARNING SIGN} First sighting\n{msg}")
|
||||
else:
|
||||
ping_guild = self.bot.get_guild(await self.config.pingserver())
|
||||
role_obj = discord.utils.get(ping_guild.roles, id=global_data["pingrole"])
|
||||
try:
|
||||
await role_obj.edit(mentionable=True)
|
||||
await channel_obj.send(
|
||||
f"{role_obj.mention}\n\N{WARNING SIGN} First sighting\n{msg}"
|
||||
)
|
||||
return await role_obj.edit(mentionable=False)
|
||||
except AttributeError:
|
||||
return await channel_obj.send(
|
||||
f"I can't find the role that's set to ping (is it on another server?)\n\N{WARNING SIGN} First sighting\n{msg}"
|
||||
)
|
||||
except discord.errors.Forbidden:
|
||||
return await channel_obj.send(
|
||||
f"I tried to ping for this alert but I don't have permissions to manage roles!\n\N{WARNING SIGN} First sighting\n{msg}"
|
||||
)
|
||||
else:
|
||||
await channel_obj.send(msg)
|
||||
|
||||
async def on_message(self, message):
|
||||
global_data = await self.config.all()
|
||||
if not global_data["toggle"]:
|
||||
return
|
||||
channel_obj = self.bot.get_channel(global_data["announce_channel"])
|
||||
if not channel_obj:
|
||||
return
|
||||
if message.author.bot:
|
||||
return
|
||||
date_join = datetime.datetime.strptime(str(message.author.created_at), "%Y-%m-%d %H:%M:%S.%f")
|
||||
date_now = datetime.datetime.now(datetime.timezone.utc)
|
||||
date_now = date_now.replace(tzinfo=None)
|
||||
since_join = date_now - date_join
|
||||
if since_join.days < global_data["join_days"]:
|
||||
sentence = message.content.split()
|
||||
for word in sentence:
|
||||
if self._match_url(word):
|
||||
await channel_obj.send(bold(f"{message.author.id}"))
|
||||
msg = "**Message posted in** {} ({})\n".format(message.guild.name, message.guild.id)
|
||||
msg += "**Message posted in** {} ({})\n".format(message.channel.mention, message.channel.id)
|
||||
msg += "**Message sent by**: {} ({})\n".format(message.author.name, message.author.id)
|
||||
msg += "**Message content**:\n{}".format(message.content)
|
||||
|
||||
if not global_data["pingrole"]:
|
||||
return await channel_obj.send(f"\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}")
|
||||
else:
|
||||
ping_guild = self.bot.get_guild(await self.config.pingserver())
|
||||
try:
|
||||
role_obj = discord.utils.get(ping_guild.roles, id=global_data["pingrole"])
|
||||
await role_obj.edit(mentionable=True)
|
||||
await channel_obj.send(
|
||||
f"{role_obj.mention}\n\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}"
|
||||
)
|
||||
return await role_obj.edit(mentionable=False)
|
||||
except AttributeError:
|
||||
return await channel_obj.send(
|
||||
f"I can't find the role that's set to ping (is it on another server?)\n\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}"
|
||||
)
|
||||
except discord.errors.Forbidden:
|
||||
return await channel_obj.send(
|
||||
f"I tried to ping for this alert but I don't have permissions to manage roles!\n\N{WARNING SIGN} \N{LINK SYMBOL} New user link post\n{msg}"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _dynamic_time(time):
|
||||
m, s = divmod(time, 60)
|
||||
h, m = divmod(m, 60)
|
||||
d, h = divmod(h, 24)
|
||||
|
||||
if d > 0:
|
||||
msg = "{0}d {1}h"
|
||||
elif d == 0 and h > 0:
|
||||
msg = "{1}h {2}m"
|
||||
elif d == 0 and h == 0 and m > 0:
|
||||
msg = "{2}m {3}s"
|
||||
elif d == 0 and h == 0 and m == 0 and s > 0:
|
||||
msg = "{3}s"
|
||||
else:
|
||||
msg = ""
|
||||
return msg.format(d, h, m, s)
|
||||
|
||||
@staticmethod
|
||||
def _match_url(url):
|
||||
regex = re.compile(
|
||||
"(([\w]+:)?//)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,63}(:[\d]+)?(/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?"
|
||||
)
|
||||
if regex.match(url):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -5,11 +5,11 @@
|
||||
"description": "Posts invites to servers, if the bot is allowed to view them. Does not generate new invites.",
|
||||
"install_msg": "Thanks for installing, have fun.",
|
||||
"permissions" : [
|
||||
"manage_server"
|
||||
"manage_guild"
|
||||
],
|
||||
"short": "Post server invites.",
|
||||
"tags": [
|
||||
"invite"
|
||||
],
|
||||
"type": "COG"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ class Timezone(BaseCog):
|
||||
)
|
||||
|
||||
@time.command()
|
||||
@checks.admin_or_permissions(manage_server=True)
|
||||
@checks.admin_or_permissions(manage_guild=True)
|
||||
async def set(self, ctx, user: discord.Member, *, tz):
|
||||
"""Allows the mods to edit timezones."""
|
||||
author = ctx.message.author
|
||||
|
||||
118
tools/tools.py
118
tools/tools.py
@@ -11,9 +11,9 @@ from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
||||
from tabulate import tabulate
|
||||
from contextlib import suppress as sps
|
||||
|
||||
|
||||
BaseCog = getattr(commands, "Cog", object)
|
||||
|
||||
|
||||
class Tools(BaseCog):
|
||||
"""Mod and Admin tools."""
|
||||
|
||||
@@ -170,7 +170,7 @@ class Tools(BaseCog):
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.command()
|
||||
@checks.mod_or_permissions(manage_server=True)
|
||||
@checks.mod_or_permissions(manage_guild=True)
|
||||
async def banlist(self, ctx):
|
||||
"""Displays the server's banlist."""
|
||||
try:
|
||||
@@ -271,7 +271,7 @@ class Tools(BaseCog):
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.command()
|
||||
@checks.mod_or_permissions(manage_server=True)
|
||||
@checks.mod_or_permissions(manage_guild=True)
|
||||
async def inrole(self, ctx, *, rolename):
|
||||
"""Check members in the role specified."""
|
||||
guild = ctx.guild
|
||||
@@ -359,9 +359,52 @@ class Tools(BaseCog):
|
||||
)
|
||||
await awaiter.edit(embed=embed)
|
||||
|
||||
@commands.command(name='listguilds', aliases=['listservers', 'guildlist', 'serverlist'])
|
||||
@checks.mod_or_permissions()
|
||||
async def listguilds(self, ctx):
|
||||
"""
|
||||
List the guilds|servers the bot is in
|
||||
"""
|
||||
asciidoc = lambda m: "```asciidoc\n{}\n```".format(m)
|
||||
guilds = sorted(self.bot.guilds, key=lambda g: -g.member_count)
|
||||
header = ("```\n"
|
||||
"The bot is in the following {} server{}\n"
|
||||
"```").format(len(guilds), 's' if len(guilds) > 1 else '')
|
||||
|
||||
max_zpadding = max([len(str(g.member_count)) for g in guilds])
|
||||
form = "{gid} :: {mems:0{zpadding}} :: {name}"
|
||||
all_forms = [form.format(gid=g.id, mems=g.member_count, name=g.name, zpadding=max_zpadding) for g in guilds]
|
||||
final = '\n'.join(all_forms)
|
||||
|
||||
await ctx.send(header)
|
||||
for page in cf.pagify(final, delims=['\n'], shorten_by=16):
|
||||
await ctx.send(asciidoc(page))
|
||||
|
||||
@commands.guild_only()
|
||||
@checks.mod_or_permissions(manage_channels=True)
|
||||
@commands.command(name='listchannel', aliases=['channellist'])
|
||||
async def listchannel(self, ctx):
|
||||
"""
|
||||
List the channels of the current server
|
||||
"""
|
||||
asciidoc = lambda m: "```asciidoc\n{}\n```".format(m)
|
||||
channels = ctx.guild.channels
|
||||
top_channels, category_channels = self.sort_channels(ctx.guild.channels)
|
||||
|
||||
topChannels_formed = '\n'.join(self.channels_format(top_channels))
|
||||
categories_formed = '\n\n'.join([self.category_format(tup) for tup in category_channels])
|
||||
|
||||
await ctx.send(f"{ctx.guild.name} has {len(channels)} channel{'s' if len(channels) > 1 else ''}.")
|
||||
|
||||
for page in cf.pagify(topChannels_formed, delims=['\n'], shorten_by=16):
|
||||
await ctx.send(asciidoc(page))
|
||||
|
||||
for page in cf.pagify(categories_formed, delims=['\n\n'], shorten_by=16):
|
||||
await ctx.send(asciidoc(page))
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.command()
|
||||
@checks.mod_or_permissions(manage_server=True)
|
||||
@checks.mod_or_permissions(manage_guild=True)
|
||||
async def newusers(self, ctx, count: int = 5, fm: str = "py"):
|
||||
"""Lists the newest 5 members."""
|
||||
guild = ctx.guild
|
||||
@@ -410,7 +453,7 @@ class Tools(BaseCog):
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.command()
|
||||
@checks.mod_or_permissions(manage_server=True)
|
||||
@checks.mod_or_permissions(manage_guild=True)
|
||||
async def perms(self, ctx, user: discord.Member = None):
|
||||
"""Fetch a specific user's permissions."""
|
||||
if user is None:
|
||||
@@ -641,16 +684,20 @@ class Tools(BaseCog):
|
||||
data += "[ID]: {}\n".format(user.id)
|
||||
data += "[Status]: {}\n".format(user.status)
|
||||
data += "[Servers]: {} shared\n".format(seen)
|
||||
if user.activity is None:
|
||||
act = user.activity
|
||||
if act is None:
|
||||
pass
|
||||
|
||||
elif user.activity.url is None:
|
||||
if user.activity.type == discord.ActivityType.playing:
|
||||
data += "[Playing]: {}\n".format(cf.escape(str(user.activity.name)))
|
||||
elif user.activity.type == discord.ActivityType.listening:
|
||||
data += "[Listening]: {}\n".format(cf.escape(str(user.activity.name)))
|
||||
elif user.activity.type == discord.ActivityType.listening:
|
||||
data += "[Watching]: {}\n".format(cf.escape(str(user.activity.name)))
|
||||
elif act.type == discord.ActivityType.playing:
|
||||
data += "[Playing]: {}\n".format(cf.escape(str(act.name)))
|
||||
elif act.type == discord.ActivityType.listening:
|
||||
if isinstance(act, discord.Spotify):
|
||||
_form = act.title
|
||||
else:
|
||||
_form = act.name
|
||||
data += "[Listening]: {}\n".format(cf.escape(_form))
|
||||
elif act.type == discord.ActivityType.listening:
|
||||
data += "[Watching]: {}\n".format(cf.escape(str(user.activity.name)))
|
||||
else:
|
||||
data += "[Streaming]: [{}]({})\n".format(
|
||||
cf.escape(str(user.activity.name)), cf.escape(user.activity.url)
|
||||
@@ -742,3 +789,48 @@ class Tools(BaseCog):
|
||||
roles = guild.roles
|
||||
role = discord.utils.find(lambda r: r.name.lower() == str(rolename).lower(), roles)
|
||||
return role
|
||||
|
||||
def sort_channels(self, channels):
|
||||
temp = dict()
|
||||
|
||||
channels = sorted(channels, key=lambda c: c.position)
|
||||
|
||||
for c in channels[:]:
|
||||
if isinstance(c, discord.CategoryChannel):
|
||||
channels.pop(channels.index(c))
|
||||
temp[c] = list()
|
||||
|
||||
for c in channels[:]:
|
||||
if c.category:
|
||||
channels.pop(channels.index(c))
|
||||
temp[c.category].append(c)
|
||||
|
||||
category_channels = sorted([(cat, sorted(chans, key=lambda c: c.position)) for cat, chans in temp.items()], key=lambda t: t[0].position)
|
||||
return channels, category_channels
|
||||
|
||||
def channels_format(self, channels: list):
|
||||
if channels == []:
|
||||
return []
|
||||
|
||||
channel_form = "{name} :: {ctype} :: {cid}"
|
||||
|
||||
def type_name(channel):
|
||||
return channel.__class__.__name__[:-7]
|
||||
|
||||
name_justify = max([len(c.name[:24]) for c in channels])
|
||||
type_justify = max([len(type_name(c)) for c in channels])
|
||||
|
||||
return [channel_form.format(name=c.name[:24].ljust(name_justify), ctype=type_name(c).ljust(type_justify), cid=c.id) for c in channels]
|
||||
|
||||
|
||||
def category_format(self, cat_chan_tuple: tuple):
|
||||
|
||||
cat = cat_chan_tuple[0]
|
||||
chs = cat_chan_tuple[1]
|
||||
|
||||
chfs = self.channels_format(chs)
|
||||
if chfs != []:
|
||||
ch_forms = ['\t' + f for f in chfs]
|
||||
return '\n'.join([f'{cat.name} :: {cat.id}'] + ch_forms)
|
||||
else:
|
||||
return '\n'.join([f'{cat.name} :: {cat.id}'] + ['\tNo Channels'])
|
||||
|
||||
@@ -248,7 +248,7 @@ class TrickOrTreat(BaseCog):
|
||||
@commands.guild_only()
|
||||
@commands.cooldown(1, 600, discord.ext.commands.BucketType.user)
|
||||
@commands.command()
|
||||
async def pick(self, ctx):
|
||||
async def pickup(self, ctx):
|
||||
"""Pick up some candy, if there is any."""
|
||||
candies = await self.config.user(ctx.author).candies()
|
||||
to_pick = await self.config.guild(ctx.guild).pick()
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import os
|
||||
import aiohttp
|
||||
import os
|
||||
from redbot.core import Config, commands, checks
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
BaseCog = getattr(commands, "Cog", object)
|
||||
|
||||
|
||||
class Wolfram(BaseCog):
|
||||
"""Ask Wolfram Alpha a question."""
|
||||
"""Ask Wolfram Alpha any question."""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.session = aiohttp.ClientSession()
|
||||
|
||||
default_global = {"WOLFRAM_API_KEY": None}
|
||||
|
||||
@@ -18,21 +21,18 @@ class Wolfram(BaseCog):
|
||||
self.config.register_guild(**default_global)
|
||||
|
||||
@commands.command(name="wolfram", aliases=["ask"])
|
||||
async def _wolfram(self, ctx, *arguments: str):
|
||||
"""
|
||||
Ask Wolfram Alpha any question.
|
||||
"""
|
||||
async def _wolfram(self, ctx, *question: str):
|
||||
"""Ask Wolfram Alpha any question."""
|
||||
|
||||
api_key = await self.config.WOLFRAM_API_KEY()
|
||||
|
||||
if api_key:
|
||||
url = "http://api.wolframalpha.com/v2/query?"
|
||||
query = " ".join(arguments)
|
||||
query = " ".join(question)
|
||||
payload = {"input": query, "appid": api_key}
|
||||
headers = {"user-agent": "Red-cog/2.0.0"}
|
||||
conn = aiohttp.TCPConnector(verify_ssl=False)
|
||||
session = aiohttp.ClientSession(connector=conn)
|
||||
async with session.get(url, params=payload, headers=headers) as r:
|
||||
async with self.session.get(url, params=payload, headers=headers) as r:
|
||||
result = await r.text()
|
||||
session.close()
|
||||
root = ET.fromstring(result)
|
||||
a = []
|
||||
for pt in root.findall(".//plaintext"):
|
||||
@@ -43,17 +43,17 @@ class Wolfram(BaseCog):
|
||||
else:
|
||||
message = "\n".join(a[0:3])
|
||||
else:
|
||||
message = (
|
||||
"No API key set for Wolfram Alpha. Get one at http://products.wolframalpha.com/api/"
|
||||
)
|
||||
await ctx.send("```{0}```".format(message))
|
||||
message = "No API key set for Wolfram Alpha. Get one at http://products.wolframalpha.com/api/"
|
||||
await ctx.send(box(message))
|
||||
|
||||
@commands.command(name="setwolframapi", aliases=["setwolfram"])
|
||||
@checks.is_owner()
|
||||
@commands.command(name="setwolframapi", aliases=["setwolfram"])
|
||||
async def _setwolframapi(self, ctx, key: str):
|
||||
"""
|
||||
Set the api-key.
|
||||
"""
|
||||
"""Set the api-key."""
|
||||
|
||||
if key:
|
||||
await self.config.WOLFRAM_API_KEY.set(key)
|
||||
await ctx.send("Key set.")
|
||||
|
||||
def __unload(self):
|
||||
self.bot.loop.create_task(self.session.close())
|
||||
|
||||
Reference in New Issue
Block a user