Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7fd5930f9 | ||
|
|
fd199aea93 | ||
|
|
e894bf21bc | ||
|
|
9de37b1fd1 | ||
|
|
e31efdba0c | ||
|
|
492e9244d6 | ||
|
|
01aa67fa9a | ||
|
|
adb3efa746 | ||
|
|
2cc04c3ac0 | ||
|
|
b2384eb7df | ||
|
|
4d66912fa2 | ||
|
|
f0f3a4171a | ||
|
|
7f227e762c | ||
|
|
f5b089f3ec | ||
|
|
ea207bccb0 | ||
|
|
cbd9901857 | ||
|
|
74901f5e37 | ||
|
|
d13075f0c6 | ||
|
|
76559c6b25 | ||
|
|
deaba0dde0 | ||
|
|
f33671601b | ||
|
|
7dd97fb2c0 | ||
|
|
eaee1acf21 | ||
|
|
02ebcf7192 | ||
|
|
567fb3077c | ||
|
|
829308f42a | ||
|
|
4e4f26f2db | ||
|
|
2d8cf0a1e4 | ||
|
|
a372ff997e | ||
|
|
f209aa2975 | ||
|
|
f8a501285f | ||
|
|
3112153c57 | ||
|
|
d2291ba7a9 | ||
|
|
2a1231f42f | ||
|
|
2b5e99b403 | ||
|
|
48132fe5b8 | ||
|
|
8f23276ad2 | ||
|
|
ae1567425c | ||
|
|
115144d9e3 | ||
|
|
37c808a9a1 | ||
|
|
fa0b3a6389 | ||
|
|
93465b2140 |
19
README.md
19
README.md
@@ -1,5 +1,12 @@
|
|||||||
# aikaterna-cogs
|
# aikaterna-cogs
|
||||||
Cogs for Red-DiscordBot by Twentysix26.
|
**v2 cogs support has ended. I will still provide bugfixes on these cogs if it is significant enough, but no new features will be added.**
|
||||||
|
|
||||||
|
**Red v3 cogs can be found on the v3 branch of this repo. (https://github.com/aikaterna/aikaterna-cogs/tree/v3)**
|
||||||
|
|
||||||
|
________________
|
||||||
|
|
||||||
|
Cogs for v2 Red-DiscordBot by Twentysix26.
|
||||||
|
|
||||||
|
|
||||||
autoeconomy - New users that join the server will be automatically given a bank account.
|
autoeconomy - New users that join the server will be automatically given a bank account.
|
||||||
|
|
||||||
@@ -15,8 +22,12 @@ hunting - By Paddolicious#8880. It hunts birds... and things that fly.
|
|||||||
|
|
||||||
imgwelcome - Welcome users to your server with a customized image.
|
imgwelcome - Welcome users to your server with a customized image.
|
||||||
|
|
||||||
|
modclean - Clean the last 100 entries in the mod-log of Discord invite names.
|
||||||
|
|
||||||
otherbot - Have multiple Red instances and want to know when one goes offline? Edit this cog and load it on your watcher bot.
|
otherbot - Have multiple Red instances and want to know when one goes offline? Edit this cog and load it on your watcher bot.
|
||||||
|
|
||||||
|
post - Upload a saved audio playlist to the chat channel, or upload a cog. Owner only.
|
||||||
|
|
||||||
pug - Warcraft pug checker. A port of PugBot's module: https://github.com/reznok/PugBot
|
pug - Warcraft pug checker. A port of PugBot's module: https://github.com/reznok/PugBot
|
||||||
|
|
||||||
radio - A hidden unpublished gem from Paddo, with a couple edits. Plays http audio streams like icecast and mp3 streams.
|
radio - A hidden unpublished gem from Paddo, with a couple edits. Plays http audio streams like icecast and mp3 streams.
|
||||||
@@ -27,10 +38,8 @@ seen - By Paddolicious#8880. Check when the user was last active on a server.
|
|||||||
|
|
||||||
serverlimit - Limit the bot to joining servers with over 25 members.
|
serverlimit - Limit the bot to joining servers with over 25 members.
|
||||||
|
|
||||||
|
wolfram - Paddolicious#8880's old wolfram cog.
|
||||||
|
|
||||||
The chatterbot cog that was previously on this repo has been removed in favor of: https://github.com/Nobleasskicker/GrandeCogs/tree/master/chat
|
youtube - Paddolicious#8880's old youtube cog, backported from my v3 version.
|
||||||
|
|
||||||
Q: Why do you have some of Paddo's cogs on your repo?
|
|
||||||
A: He recently made an announcement about finding a new home for a few cogs. I've picked up a couple and I welcome PRs or feature requests. I'm also intending to port these for Red v3 as I can.
|
|
||||||
|
|
||||||
Feel free to join the server for these cogs if you'd like. https://discord.gg/th6eS3T
|
Feel free to join the server for these cogs if you'd like. https://discord.gg/th6eS3T
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ class AutoEconomy:
|
|||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.settings = dataIO.load_json('data/autoeconomy/settings.json')
|
self.settings = dataIO.load_json('data/autoeconomy/settings.json')
|
||||||
self.banksettings = dataIO.load_json('data/economy/settings.json')
|
self.version = "0.1.2"
|
||||||
self.version = "0.1.1b"
|
|
||||||
|
|
||||||
async def save_settings(self):
|
async def save_settings(self):
|
||||||
dataIO.save_json('data/autoeconomy/settings.json', self.settings)
|
dataIO.save_json('data/autoeconomy/settings.json', self.settings)
|
||||||
@@ -85,31 +84,64 @@ class AutoEconomy:
|
|||||||
"""Displays the autoeconomy version."""
|
"""Displays the autoeconomy version."""
|
||||||
await self.bot.say("autoeconomy version {}.".format(self.version))
|
await self.bot.say("autoeconomy version {}.".format(self.version))
|
||||||
|
|
||||||
async def on_member_join(self, member):
|
@autoeconomy.command(name="massregister", pass_context=True, no_pm=True)
|
||||||
|
async def massregister(self, ctx):
|
||||||
|
"""Mass register existing users."""
|
||||||
|
econ_cog = self.bot.get_cog('Economy')
|
||||||
|
if not econ_cog:
|
||||||
|
return await self.bot.say("This requires economy to be loaded.")
|
||||||
|
server = ctx.message.server
|
||||||
|
if server.id not in econ_cog.bank.accounts:
|
||||||
|
return await self.bot.say(
|
||||||
|
"I can't register people for a bank that doesn't exist yet."
|
||||||
|
)
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
for member in server.members:
|
||||||
|
init_balance = econ_cog.settings[server.id].get("REGISTER_CREDITS", 0)
|
||||||
|
try:
|
||||||
|
econ_cog.bank.create_account(member, initial_balance=init_balance)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
await self.bot.say(
|
||||||
|
"I've opened up new economy entries for "
|
||||||
|
"{}/{} members.".format(count, len(server.members))
|
||||||
|
)
|
||||||
|
|
||||||
|
async def on_member_join(self, member, mass_register=False):
|
||||||
server = member.server
|
server = member.server
|
||||||
|
|
||||||
if server.id not in self.settings:
|
if server.id not in self.settings:
|
||||||
self.settings[server.id] = deepcopy(default_settings)
|
self.settings[server.id] = deepcopy(default_settings)
|
||||||
await self.save_settings()
|
await self.save_settings()
|
||||||
if not self.settings[server.id]["TOGGLE"]:
|
if not (self.settings[server.id]["TOGGLE"] or mass_register):
|
||||||
return
|
return
|
||||||
|
|
||||||
channel = self.settings[server.id]["CHANNEL"]
|
channel = self.settings[server.id]["CHANNEL"]
|
||||||
channel_object = self.bot.get_channel(channel)
|
channel_object = self.bot.get_channel(channel)
|
||||||
econ_cog = self.bot.get_cog('Economy')
|
econ_cog = self.bot.get_cog('Economy')
|
||||||
|
|
||||||
|
if server.id not in econ_cog.bank.accounts:
|
||||||
|
return
|
||||||
if not econ_cog:
|
if not econ_cog:
|
||||||
return
|
return
|
||||||
|
|
||||||
bank = self.bot.get_cog('Economy').bank
|
bank = self.bot.get_cog('Economy').bank
|
||||||
|
init_balance = econ_cog.settings[server.id].get("REGISTER_CREDITS", 0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bank.create_account(member)
|
bank.create_account(member, initial_balance=init_balance)
|
||||||
except Exception:
|
except Exception:
|
||||||
if self.settings[server.id]["DEBUG"]:
|
if self.settings[server.id]["DEBUG"] and not mass_register:
|
||||||
await self.bot.send_message(channel_object, "Economy account already exists for {}.".format(member.name))
|
await self.bot.send_message(channel_object, "Economy account already exists for {}.".format(member.name))
|
||||||
return
|
return False
|
||||||
if self.banksettings[server.id]["REGISTER_CREDITS"]:
|
else:
|
||||||
reg_credits = self.banksettings[server.id]["REGISTER_CREDITS"]
|
if self.settings[server.id]["DEBUG"] and not mass_register:
|
||||||
bank.deposit_credits(member, reg_credits)
|
|
||||||
if self.settings[server.id]["DEBUG"]:
|
|
||||||
await self.bot.send_message(channel_object, "Bank account opened for {} and initial credits given.".format(member.name))
|
await self.bot.send_message(channel_object, "Bank account opened for {} and initial credits given.".format(member.name))
|
||||||
return
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check_folders():
|
def check_folders():
|
||||||
|
|||||||
@@ -20,67 +20,83 @@ class ChatChart:
|
|||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
def create_chart(self, top, others):
|
def create_chart(self, top, others, channel):
|
||||||
plt.clf()
|
plt.clf()
|
||||||
sizes = [x[1] for x in top]
|
sizes = [x[1] for x in top]
|
||||||
labels = ["{} {:g}%".format(x[0], x[1]) for x in top]
|
labels = ["{} {:g}%".format(x[0], x[1]) for x in top]
|
||||||
if len(top) >= 10:
|
if len(top) >= 20:
|
||||||
sizes = sizes + [others]
|
sizes = sizes + [others]
|
||||||
labels = labels + ["Others {:g}%".format(others)]
|
labels = labels + ["Others {:g}%".format(others)]
|
||||||
|
if len(channel.name) >= 19:
|
||||||
title = plt.title('User activity in the last 5000 messages')
|
channel_name = '{}...'.format(channel.name[:19])
|
||||||
|
else:
|
||||||
|
channel_name = channel.name
|
||||||
|
title = plt.title("Stats in #{}".format(channel_name), color="white")
|
||||||
title.set_va("top")
|
title.set_va("top")
|
||||||
title.set_ha("left")
|
title.set_ha("center")
|
||||||
plt.gca().axis("equal")
|
plt.gca().axis("equal")
|
||||||
colors = ['r', 'darkorange', 'gold', 'y', 'olivedrab', 'green', 'darkcyan', 'mediumblue', 'darkblue', 'blueviolet', 'indigo']
|
colors = ['r', 'darkorange', 'gold', 'y', 'olivedrab', 'green', 'darkcyan', 'mediumblue', 'darkblue', 'blueviolet', 'indigo', 'orchid', 'mediumvioletred', 'crimson', 'chocolate', 'yellow', 'limegreen','forestgreen','dodgerblue','slateblue','gray']
|
||||||
pie = plt.pie(sizes, colors=colors, startangle=0)
|
pie = plt.pie(sizes, colors=colors, startangle=0)
|
||||||
plt.legend(pie[0], labels, bbox_to_anchor=(0.7, 0.5), loc="center", fontsize=10,
|
plt.legend(pie[0], labels, bbox_to_anchor=(0.7, 0.5), loc="center", fontsize=10,
|
||||||
bbox_transform=plt.gcf().transFigure)
|
bbox_transform=plt.gcf().transFigure, facecolor='#ffffff')
|
||||||
plt.subplots_adjust(left=0.0, bottom=0.1, right=0.45)
|
plt.subplots_adjust(left=0.0, bottom=0.1, right=0.45)
|
||||||
image_object = BytesIO()
|
image_object = BytesIO()
|
||||||
plt.savefig(image_object, format='PNG')
|
plt.savefig(image_object, format='PNG', facecolor='#36393E')
|
||||||
image_object.seek(0)
|
image_object.seek(0)
|
||||||
return image_object
|
return image_object
|
||||||
|
|
||||||
@commands.command(pass_context=True)
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
@commands.cooldown(1, 10, commands.BucketType.channel)
|
@commands.cooldown(1, 10, commands.BucketType.channel)
|
||||||
async def chatchart(self, ctx):
|
async def chatchart(self, ctx, channel: discord.Channel=None):
|
||||||
"""
|
"""
|
||||||
Generates a pie chart, representing the last 5000 messages in this channel.
|
Generates a pie chart, representing the last 5000 messages in the specified channel.
|
||||||
"""
|
"""
|
||||||
channel = ctx.message.channel
|
|
||||||
e = discord.Embed(description="Loading...", colour=0x00ccff)
|
e = discord.Embed(description="Loading...", colour=0x00ccff)
|
||||||
e.set_thumbnail(url="https://i.imgur.com/vSp4xRk.gif")
|
e.set_thumbnail(url="https://i.imgur.com/vSp4xRk.gif")
|
||||||
em = await self.bot.say(embed=e)
|
em = await self.bot.say(embed=e)
|
||||||
|
|
||||||
|
if channel is None:
|
||||||
|
channel = ctx.message.channel
|
||||||
history = []
|
history = []
|
||||||
async for msg in self.bot.logs_from(channel, 5000):
|
if not channel.permissions_for(ctx.message.author).read_messages == True:
|
||||||
history.append(msg)
|
await self.bot.delete_message(em)
|
||||||
|
return await self.bot.say("You're not allowed to access that channel.")
|
||||||
|
try:
|
||||||
|
async for msg in self.bot.logs_from(channel, 5000):
|
||||||
|
history.append(msg)
|
||||||
|
except discord.errors.Forbidden:
|
||||||
|
await self.bot.delete_message(em)
|
||||||
|
return await self.bot.say("No permissions to read that channel.")
|
||||||
msg_data = {'total count': 0, 'users': {}}
|
msg_data = {'total count': 0, 'users': {}}
|
||||||
|
|
||||||
for msg in history:
|
for msg in history:
|
||||||
|
if len(msg.author.name) >= 20:
|
||||||
|
short_name = '{}...'.format(msg.author.name[:20]).replace("$", "\$")
|
||||||
|
else:
|
||||||
|
short_name = msg.author.name.replace("$", "\$")
|
||||||
|
whole_name = '{}#{}'.format(short_name, msg.author.discriminator)
|
||||||
if msg.author.bot:
|
if msg.author.bot:
|
||||||
pass
|
pass
|
||||||
elif msg.author.name in msg_data['users']:
|
elif whole_name in msg_data['users']:
|
||||||
msg_data['users'][msg.author.name]['msgcount'] += 1
|
msg_data['users'][whole_name]['msgcount'] += 1
|
||||||
msg_data['total count'] += 1
|
msg_data['total count'] += 1
|
||||||
else:
|
else:
|
||||||
msg_data['users'][msg.author.name] = {}
|
msg_data['users'][whole_name] = {}
|
||||||
msg_data['users'][msg.author.name]['msgcount'] = 1
|
msg_data['users'][whole_name]['msgcount'] = 1
|
||||||
msg_data['total count'] += 1
|
msg_data['total count'] += 1
|
||||||
|
|
||||||
for usr in msg_data['users']:
|
for usr in msg_data['users']:
|
||||||
pd = float(msg_data['users'][usr]['msgcount']) / float(msg_data['total count'])
|
pd = float(msg_data['users'][usr]['msgcount']) / float(msg_data['total count'])
|
||||||
msg_data['users'][usr]['percent'] = round(pd * 100, 1)
|
msg_data['users'][usr]['percent'] = round(pd * 100, 1)
|
||||||
|
|
||||||
top_ten = heapq.nlargest(10, [(x, msg_data['users'][x][y])
|
top_ten = heapq.nlargest(20, [(x, msg_data['users'][x][y])
|
||||||
for x in msg_data['users']
|
for x in msg_data['users']
|
||||||
for y in msg_data['users'][x]
|
for y in msg_data['users'][x]
|
||||||
if y == 'percent'], key=lambda x: x[1])
|
if y == 'percent'], key=lambda x: x[1])
|
||||||
others = 100 - sum(x[1] for x in top_ten)
|
others = 100 - sum(x[1] for x in top_ten)
|
||||||
img = self.create_chart(top_ten, others)
|
img = self.create_chart(top_ten, others, channel)
|
||||||
await self.bot.delete_message(em)
|
await self.bot.delete_message(em)
|
||||||
await self.bot.send_file(channel, img, filename="chart.png")
|
await self.bot.send_file(ctx.message.channel, img, filename="chart.png")
|
||||||
|
|
||||||
|
|
||||||
def check_folders():
|
def check_folders():
|
||||||
|
|||||||
@@ -55,7 +55,11 @@ class ImgWelcome:
|
|||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.settings = dataIO.load_json('data/imgwelcome/settings.json')
|
self.settings = dataIO.load_json('data/imgwelcome/settings.json')
|
||||||
self.version = "0.1.6"
|
self.version = "0.1.8"
|
||||||
|
self.session = aiohttp.ClientSession()
|
||||||
|
|
||||||
|
def __unload(self):
|
||||||
|
self.session.close()
|
||||||
|
|
||||||
async def save_settings(self):
|
async def save_settings(self):
|
||||||
dataIO.save_json('data/imgwelcome/settings.json', self.settings)
|
dataIO.save_json('data/imgwelcome/settings.json', self.settings)
|
||||||
@@ -152,7 +156,7 @@ class ImgWelcome:
|
|||||||
drawtwo.text((152, 70), uname, font=name_font_small, fill=(fontcolor))
|
drawtwo.text((152, 70), uname, font=name_font_small, fill=(fontcolor))
|
||||||
|
|
||||||
if len(uname) >= 33:
|
if len(uname) >= 33:
|
||||||
drawtwo.text((152, 73), uname, 1, name_font_smallest, (textoutline))
|
_outline((152, 73), uname, 1, name_font_smallest, (textoutline))
|
||||||
drawtwo.text((152, 73), uname, font=name_font_smallest, fill=(fontcolor))
|
drawtwo.text((152, 73), uname, font=name_font_smallest, fill=(fontcolor))
|
||||||
|
|
||||||
if test_member_number is None:
|
if test_member_number is None:
|
||||||
@@ -220,7 +224,7 @@ class ImgWelcome:
|
|||||||
await self.save_settings()
|
await self.save_settings()
|
||||||
|
|
||||||
async def _get_profile(self, url):
|
async def _get_profile(self, url):
|
||||||
async with aiohttp.get(url) as r:
|
async with self.session.get(url) as r:
|
||||||
image = await r.content.read()
|
image = await r.content.read()
|
||||||
with open('data/imgwelcome/profilepic.png', 'wb') as f:
|
with open('data/imgwelcome/profilepic.png', 'wb') as f:
|
||||||
f.write(image)
|
f.write(image)
|
||||||
@@ -407,7 +411,7 @@ class ImgWelcome:
|
|||||||
|
|
||||||
if success:
|
if success:
|
||||||
try:
|
try:
|
||||||
async with aiohttp.get(bg_url) as r:
|
async with self.session.get(bg_url) as r:
|
||||||
image = await r.content.read()
|
image = await r.content.read()
|
||||||
if not os.path.exists('data/imgwelcome/{}'.format(server.id)):
|
if not os.path.exists('data/imgwelcome/{}'.format(server.id)):
|
||||||
os.makedirs('data/imgwelcome/{}'.format(server.id))
|
os.makedirs('data/imgwelcome/{}'.format(server.id))
|
||||||
@@ -587,14 +591,14 @@ class ImgWelcome:
|
|||||||
await self.bot.send_typing(channel_object)
|
await self.bot.send_typing(channel_object)
|
||||||
image_object = await self._create_welcome(member, member.avatar_url)
|
image_object = await self._create_welcome(member, member.avatar_url)
|
||||||
await self.bot.send_file(channel_object, image_object, filename="welcome.png")
|
await self.bot.send_file(channel_object, image_object, filename="welcome.png")
|
||||||
if (len(member.server.members) % 100) == 0 or (len(member.server.members) == 1337) and self.settings[server.id]["SPECIAL_USERS"]:
|
if ((len(member.server.members) % 100) == 0 or (len(member.server.members) == 1337)) and self.settings[server.id]["BONUSES"]["SPECIAL_USERS"]:
|
||||||
msg = "\N{PARTY POPPER} Thanks <@" + member.id + ">, you're the ***" + str(len(member.server.members)) + "*** th user on this server! \N{PARTY POPPER}"
|
msg = "\N{PARTY POPPER} Thanks <@" + member.id + ">, you're the ***" + str(len(member.server.members)) + "*** th user on this server! \N{PARTY POPPER}"
|
||||||
await self.bot.send_message(channel_object, msg)
|
await self.bot.send_message(channel_object, msg)
|
||||||
date_join = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f")
|
date_join = datetime.datetime.strptime(str(member.created_at), "%Y-%m-%d %H:%M:%S.%f")
|
||||||
date_now = datetime.datetime.now(datetime.timezone.utc)
|
date_now = datetime.datetime.now(datetime.timezone.utc)
|
||||||
date_now = date_now.replace(tzinfo=None)
|
date_now = date_now.replace(tzinfo=None)
|
||||||
since_join = date_now - date_join
|
since_join = date_now - date_join
|
||||||
if since_join.days < 7 and self.settings[server.id]["ACCOUNT_WARNINGS"]:
|
if since_join.days < 7 and self.settings[server.id]["BONUSES"]["ACCOUNT_WARNINGS"]:
|
||||||
await self.bot.send_message(channel_object, "\N{WARNING SIGN} This account was created less than a week ago (" + str(since_join.days) + " days ago)")
|
await self.bot.send_message(channel_object, "\N{WARNING SIGN} This account was created less than a week ago (" + str(since_join.days) + " days ago)")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
8
modclean/info.json
Normal file
8
modclean/info.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"AUTHOR" : "aikaterna and sitryk",
|
||||||
|
"INSTALL_MSG" : "Use `[p]modclean #mod-log` to clean your mod log channel. Edits out Discord invite links from banned or kicked users.",
|
||||||
|
"NAME" : "modclean",
|
||||||
|
"SHORT" : "Clean your mod log channel of Discord invite names.",
|
||||||
|
"DESCRIPTION" : "Clean your mod log channel of Discord invite names.",
|
||||||
|
"TAGS": ["modlog"]
|
||||||
|
}
|
||||||
40
modclean/modclean.py
Normal file
40
modclean/modclean.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import discord
|
||||||
|
import re
|
||||||
|
from cogs.utils import checks
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
|
||||||
|
class ModClean:
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
@commands.command(no_pm=True, pass_context=True)
|
||||||
|
@checks.is_owner()
|
||||||
|
async def modclean(self, ctx, modchannel: discord.Channel = None):
|
||||||
|
"""Clean a v2 mod-log channel of invite names."""
|
||||||
|
if not modchannel:
|
||||||
|
return await self.bot.say(
|
||||||
|
"Please use the mod channel in the command. ({}modclean #channelname)".format(
|
||||||
|
ctx.prefix
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
IL_raw = r"(discordapp.com/invite|discord.me|discord.gg)(?:/#)?(?:/invite)?/([a-z0-9\-]+)"
|
||||||
|
InvLink = re.compile(IL_raw, re.I)
|
||||||
|
|
||||||
|
try:
|
||||||
|
async for m in self.bot.logs_from(modchannel, 100):
|
||||||
|
if not (m.author == ctx.message.server.me):
|
||||||
|
continue
|
||||||
|
elif InvLink.search(m.content) is None:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
new_cont = InvLink.sub("[REMOVED LINK]", m.content)
|
||||||
|
await self.bot.edit_message(m, new_cont)
|
||||||
|
except discord.errors.Forbidden:
|
||||||
|
return await self.bot.say("No permissions to read that channel.")
|
||||||
|
await self.bot.say("Done.")
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
bot.add_cog(ModClean(bot))
|
||||||
@@ -109,24 +109,24 @@ class PicWelcome:
|
|||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
serverimage = Image
|
serverimage = Image
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
try:
|
try:
|
||||||
async with aiohttp.get(bg_url) as r:
|
async with aiohttp.get(bg_url) as r:
|
||||||
image = await r.content.read()
|
image = await r.content.read()
|
||||||
if not os.path.exists('data/picwelcome/{}'.format(server.id)):
|
if not os.path.exists('data/picwelcome/{}'.format(server.id)):
|
||||||
os.makedirs('data/picwelcome/{}'.format(server.id))
|
os.makedirs('data/picwelcome/{}'.format(server.id))
|
||||||
serverbg = 'data/picwelcome/{}/serverpic.png'.format(server.id)
|
file_suffix = bg_url.rsplit('.', 1)[1]
|
||||||
|
serverbg = 'data/picwelcome/{}/serverpic.{}'.format(server.id, file_suffix)
|
||||||
with open(serverbg, 'wb') as f:
|
with open(serverbg, 'wb') as f:
|
||||||
f.write(image)
|
f.write(image)
|
||||||
serverimage = Image.open(serverbg).convert('RGBA')
|
serverimage = Image.open(serverbg).convert('RGBA')
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
success = False
|
success = False
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
self.settings[server.id]['PICTURE'] = "data/picwelcome/" + ctx.message.server.id + "/serverpic.png"
|
self.settings[server.id]['PICTURE'] = "data/picwelcome/{}/serverpic.{}".format(ctx.message.server.id, file_suffix)
|
||||||
await self.save_settings()
|
await self.save_settings()
|
||||||
await self.bot.say('Welcome image for this server set to uploaded file.')
|
await self.bot.say('Welcome image for this server set to uploaded file.')
|
||||||
else:
|
else:
|
||||||
@@ -152,12 +152,10 @@ class PicWelcome:
|
|||||||
serverpicture = self.settings[server.id]["PICTURE"]
|
serverpicture = self.settings[server.id]["PICTURE"]
|
||||||
await self.bot.send_file(channel_object, serverpicture)
|
await self.bot.send_file(channel_object, serverpicture)
|
||||||
|
|
||||||
|
|
||||||
def check_folders():
|
def check_folders():
|
||||||
if not os.path.exists('data/picwelcome/'):
|
if not os.path.exists('data/picwelcome/'):
|
||||||
os.mkdir('data/picwelcome/')
|
os.mkdir('data/picwelcome/')
|
||||||
|
|
||||||
|
|
||||||
def check_files():
|
def check_files():
|
||||||
if not dataIO.is_valid_json('data/picwelcome/settings.json'):
|
if not dataIO.is_valid_json('data/picwelcome/settings.json'):
|
||||||
defaults = {}
|
defaults = {}
|
||||||
|
|||||||
31
post/post.py
Normal file
31
post/post.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from discord.ext import commands
|
||||||
|
from .utils import checks
|
||||||
|
|
||||||
|
class Post:
|
||||||
|
def __init__(self,bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
@commands.command(no_pm=True, pass_context=True)
|
||||||
|
@checks.is_owner()
|
||||||
|
async def postsongs(self, ctx, playlist):
|
||||||
|
"""Posts a playlist."""
|
||||||
|
try:
|
||||||
|
await self.bot.send_file(ctx.message.channel, 'data/audio/playlists/{}/{}.txt'.format(ctx.message.server.id, playlist))
|
||||||
|
except FileNotFoundError:
|
||||||
|
try:
|
||||||
|
await self.bot.send_file(ctx.message.channel, 'data/audio/playlists/{}.txt'.format(playlist))
|
||||||
|
except FileNotFoundError:
|
||||||
|
await self.bot.say("No playlist named {}.".format(playlist))
|
||||||
|
|
||||||
|
@commands.command(no_pm=True, pass_context=True)
|
||||||
|
@checks.is_owner()
|
||||||
|
async def postcog(self, ctx, cogname):
|
||||||
|
"""Posts a cog."""
|
||||||
|
try:
|
||||||
|
await self.bot.send_file(ctx.message.channel, 'cogs/{}.py'.format(cogname))
|
||||||
|
except FileNotFoundError:
|
||||||
|
await self.bot.say("No cog named {}.".format(cogname))
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
n = Post(bot)
|
||||||
|
bot.add_cog(n)
|
||||||
@@ -44,13 +44,18 @@ class Radio:
|
|||||||
async def _list(self, ctx):
|
async def _list(self, ctx):
|
||||||
"""List saved stream URLs."""
|
"""List saved stream URLs."""
|
||||||
server = ctx.message.server
|
server = ctx.message.server
|
||||||
message = '```\n'
|
message_list = []
|
||||||
message += '{:<30}{}\n\n'.format('NAME', 'URL')
|
|
||||||
if server.id in self.memory:
|
if server.id in self.memory:
|
||||||
for stream in self.memory[server.id]:
|
for stream in self.memory[server.id]:
|
||||||
message += '{:<30}{}\n'.format(stream, self.memory[server.id][stream])
|
message = '{:<30}{}\n'.format(stream, self.memory[server.id][stream])
|
||||||
message += '```'
|
message_list.append(message)
|
||||||
await self.bot.say(message)
|
sorted_list = sorted(message_list, key=str.lower)
|
||||||
|
msg = '```'
|
||||||
|
msg += '{:<30}{}\n\n'.format('NAME', 'URL')
|
||||||
|
for sorted_msg in sorted_list:
|
||||||
|
msg += sorted_msg
|
||||||
|
msg += '```'
|
||||||
|
await self.bot.say(msg)
|
||||||
|
|
||||||
@_radio.command(no_pm=True, pass_context=True, name='add')
|
@_radio.command(no_pm=True, pass_context=True, name='add')
|
||||||
async def _add(self, ctx, name: str, url: str):
|
async def _add(self, ctx, name: str, url: str):
|
||||||
@@ -75,6 +80,13 @@ class Radio:
|
|||||||
else:
|
else:
|
||||||
await self.bot.say('Nothing in memory yet')
|
await self.bot.say('Nothing in memory yet')
|
||||||
|
|
||||||
|
@_radio.command(no_pm=True, pass_context=True, name='remove')
|
||||||
|
async def _remove(self, ctx, name: str):
|
||||||
|
"""Remove a saved radio stream."""
|
||||||
|
server = ctx.message.server
|
||||||
|
await self.remove_from_memory(server, name)
|
||||||
|
await self.bot.say('Removed {} from memory.'.format(name))
|
||||||
|
|
||||||
async def save_memory(self):
|
async def save_memory(self):
|
||||||
dataIO.save_json(self.memory_path, self.memory)
|
dataIO.save_json(self.memory_path, self.memory)
|
||||||
|
|
||||||
@@ -84,6 +96,10 @@ class Radio:
|
|||||||
self.memory[server.id][name.lower()] = url
|
self.memory[server.id][name.lower()] = url
|
||||||
await self.save_memory()
|
await self.save_memory()
|
||||||
|
|
||||||
|
async def remove_from_memory(self, server, name):
|
||||||
|
del self.memory[server.id][name.lower()]
|
||||||
|
await self.save_memory()
|
||||||
|
|
||||||
async def join_voice_channel(self, channel):
|
async def join_voice_channel(self, channel):
|
||||||
try:
|
try:
|
||||||
await self.bot.join_voice_channel(channel)
|
await self.bot.join_voice_channel(channel)
|
||||||
|
|||||||
9
tools/info.json
Normal file
9
tools/info.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"AUTHOR" : "aikaterna, Sitryk, and Axas",
|
||||||
|
"INSTALL_MSG" : "Thanks for installing.",
|
||||||
|
"NAME" : "tools",
|
||||||
|
"SHORT" : "A collection of tools for mods.",
|
||||||
|
"DESCRIPTION" : "A collection of channel, user, and server tools for mods.",
|
||||||
|
"REQUIREMENTS": ["tabulate"],
|
||||||
|
"TAGS": ["tools"]
|
||||||
|
}
|
||||||
813
tools/tools.py
Normal file
813
tools/tools.py
Normal file
@@ -0,0 +1,813 @@
|
|||||||
|
# Most of these tools are thanks to Sitryk.
|
||||||
|
# Credit for the findcog/cmd_lookup command belongs to Axas, thanks for the inspiration for
|
||||||
|
# the findcog command in Red v3.
|
||||||
|
|
||||||
|
from discord.ext import commands
|
||||||
|
from .utils.chat_formatting import pagify, box, escape_mass_mentions
|
||||||
|
from .utils.dataIO import dataIO
|
||||||
|
from .utils import checks
|
||||||
|
from __main__ import send_cmd_help
|
||||||
|
from tabulate import tabulate
|
||||||
|
import discord
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import asyncio
|
||||||
|
import discord
|
||||||
|
import random
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
ini = "```ini\n{0}\n```"
|
||||||
|
|
||||||
|
|
||||||
|
class Tools:
|
||||||
|
"""Mod and Admin tools."""
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
@commands.group(pass_context=True, no_pm=True)
|
||||||
|
async def access(self, ctx):
|
||||||
|
"""Check channel access."""
|
||||||
|
if ctx.invoked_subcommand is None:
|
||||||
|
await send_cmd_help(ctx)
|
||||||
|
return
|
||||||
|
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
@access.command(pass_context=True)
|
||||||
|
async def compare(self, ctx, user: discord.User, server: discord.Server = None):
|
||||||
|
"""Compare channel access with [user]"""
|
||||||
|
author = ctx.message.author
|
||||||
|
if user is None:
|
||||||
|
return
|
||||||
|
if server is None:
|
||||||
|
server = ctx.message.server
|
||||||
|
|
||||||
|
text_channels = [c for c in server.channels if str(c.type) == "text"]
|
||||||
|
voice_channels = [c for c in server.channels if str(c.type) == "voice"]
|
||||||
|
|
||||||
|
author_text_channels = [
|
||||||
|
c.name for c in text_channels if c.permissions_for(author).read_messages is True
|
||||||
|
]
|
||||||
|
author_voice_channels = [
|
||||||
|
c.name for c in voice_channels if c.permissions_for(author).connect is True
|
||||||
|
]
|
||||||
|
|
||||||
|
user_text_channels = [
|
||||||
|
c.name for c in text_channels if c.permissions_for(user).read_messages is True
|
||||||
|
]
|
||||||
|
user_voice_channels = [
|
||||||
|
c.name for c in voice_channels if c.permissions_for(user).connect is True
|
||||||
|
]
|
||||||
|
|
||||||
|
author_only_t = set(author_text_channels) - set(
|
||||||
|
user_text_channels
|
||||||
|
) # text channels only the author has access to
|
||||||
|
author_only_v = set(author_voice_channels) - set(
|
||||||
|
user_voice_channels
|
||||||
|
) # voice channels only the author has access to
|
||||||
|
|
||||||
|
user_only_t = set(user_text_channels) - set(
|
||||||
|
author_text_channels
|
||||||
|
) # text channels only the user has access to
|
||||||
|
user_only_v = set(user_voice_channels) - set(
|
||||||
|
author_voice_channels
|
||||||
|
) # voice channels only the user has access to
|
||||||
|
|
||||||
|
common_t = list(
|
||||||
|
set(text_channels) - author_only_t - user_only_t
|
||||||
|
) # text channels that author and user have in common
|
||||||
|
common_v = list(
|
||||||
|
set(voice_channels) - author_only_v - user_only_v
|
||||||
|
) # voice channels that author and user have in common
|
||||||
|
|
||||||
|
msg = "```ini\n"
|
||||||
|
msg += "{} [TEXT CHANNELS IN COMMON]:\n\n{}\n\n".format(
|
||||||
|
len(common_t), ", ".join([c.name for c in common_t])
|
||||||
|
)
|
||||||
|
msg += "{} [TEXT CHANNELS {} HAS ACCESS TO]:\n\n{}\n\n".format(
|
||||||
|
len(user_only_t), user.name.upper(), ", ".join(list(user_only_t))
|
||||||
|
)
|
||||||
|
msg += "{} [TEXT CHANNELS YOU HAVE ACCESS TO]:\n\n{}\n\n".format(
|
||||||
|
len(author_only_t), ", ".join(list(author_only_t))
|
||||||
|
)
|
||||||
|
msg += "{} [VOICE CHANNELS IN COMMON]:\n\n{}\n\n".format(
|
||||||
|
len(common_v), ", ".join([c.name for c in common_v])
|
||||||
|
)
|
||||||
|
msg += "{} [VOICE CHANNELS {} HAS ACCESS TO]:\n\n{}\n\n".format(
|
||||||
|
len(user_only_v), user.name.upper(), ", ".join(list(user_only_v))
|
||||||
|
)
|
||||||
|
msg += "{} [VOICE CHANNELS YOU HAVE ACCESS TO]:\n\n{}\n\n".format(
|
||||||
|
len(author_only_v), ", ".join(list(author_only_v))
|
||||||
|
)
|
||||||
|
msg += "```"
|
||||||
|
await self.bot.say(msg)
|
||||||
|
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
@access.command(pass_context=True)
|
||||||
|
async def text(self, ctx, user: discord.Member = None, server: discord.Server = None):
|
||||||
|
"""Fetch which text channels you have access to."""
|
||||||
|
author = ctx.message.author
|
||||||
|
if server is None:
|
||||||
|
server = ctx.message.server
|
||||||
|
if user is None:
|
||||||
|
user = author
|
||||||
|
|
||||||
|
can_access = [
|
||||||
|
c.name
|
||||||
|
for c in server.channels
|
||||||
|
if c.permissions_for(user).read_messages == True and str(c.type) == "text"
|
||||||
|
]
|
||||||
|
text_channels = [c.name for c in server.channels if str(c.type) == "text"]
|
||||||
|
|
||||||
|
prefix = "You have" if user.id == author.id else user.name + " has"
|
||||||
|
msg = "```ini\n[{} access to {} out of {} text channels]\n\n".format(
|
||||||
|
prefix, len(can_access), len(text_channels)
|
||||||
|
)
|
||||||
|
|
||||||
|
msg += "[ACCESS]:\n{}\n\n".format(", ".join(can_access))
|
||||||
|
msg += "[NO ACCESS]:\n{}\n```".format(
|
||||||
|
", ".join(list(set(text_channels) - set(can_access)))
|
||||||
|
)
|
||||||
|
await self.bot.say(msg)
|
||||||
|
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
@access.command(pass_context=True)
|
||||||
|
async def voice(self, ctx, user: discord.Member = None, server: discord.Server = None):
|
||||||
|
"""Fetch which voice channels you have access to."""
|
||||||
|
author = ctx.message.author
|
||||||
|
if server is None:
|
||||||
|
server = ctx.message.server
|
||||||
|
if user is None:
|
||||||
|
user = author
|
||||||
|
|
||||||
|
can_access = [
|
||||||
|
c.name
|
||||||
|
for c in server.channels
|
||||||
|
if c.permissions_for(user).connect is True and str(c.type) == "voice"
|
||||||
|
]
|
||||||
|
voice_channels = [c.name for c in server.channels if str(c.type) == "voice"]
|
||||||
|
|
||||||
|
prefix = "You have" if user.id == author.id else user.name + " has"
|
||||||
|
msg = "```ini\n[{} access to {} out of {} voice channels]\n\n".format(
|
||||||
|
prefix, len(can_access), len(voice_channels)
|
||||||
|
)
|
||||||
|
|
||||||
|
msg += "[ACCESS]:\n{}\n\n".format(", ".join(can_access))
|
||||||
|
msg += "[NO ACCESS]:\n{}\n```".format(
|
||||||
|
", ".join(list(set(voice_channels) - set(can_access)))
|
||||||
|
)
|
||||||
|
await self.bot.say(msg)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
@checks.admin_or_permissions(manage_server=True)
|
||||||
|
async def banlist(self, ctx):
|
||||||
|
"""Displays the server's banlist."""
|
||||||
|
try:
|
||||||
|
banlist = await self.bot.get_bans(ctx.message.server)
|
||||||
|
except discord.errors.Forbidden:
|
||||||
|
await self.bot.say("I do not have the `Ban Members` permission.")
|
||||||
|
return
|
||||||
|
bancount = len(banlist)
|
||||||
|
if bancount == 0:
|
||||||
|
banlist = "No users are banned from this server."
|
||||||
|
else:
|
||||||
|
banlist = ", ".join(map(str, banlist))
|
||||||
|
|
||||||
|
for page in pagify(banlist, ["\n"], shorten_by=13, page_length=2000):
|
||||||
|
await self.bot.say(box(page, "ini"))
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
|
async def cid(self, ctx, channel: discord.Channel = None):
|
||||||
|
"""Shows the channel ID."""
|
||||||
|
if not channel:
|
||||||
|
channel = ctx.message.channel
|
||||||
|
await self.bot.say("**#{0.name} ID:** {0.id}".format(channel))
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def cinfo(self, ctx, channel: discord.Channel = None):
|
||||||
|
"""Shows channel information. Defaults to current text channel."""
|
||||||
|
yesno = {True: "Yes", False: "No"}
|
||||||
|
if not channel:
|
||||||
|
channel = ctx.message.channel
|
||||||
|
|
||||||
|
load = "```\nLoading channel info...```"
|
||||||
|
waiting = await self.bot.say(load)
|
||||||
|
|
||||||
|
try:
|
||||||
|
caller = inspect.currentframe().f_back.f_code.co_name
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
data = "```ini\n"
|
||||||
|
if caller == "whatis":
|
||||||
|
data == "[Server]: {}\n".format(channel.server.name)
|
||||||
|
data += "[Name]: {}\n".format(escape_mass_mentions(str(channel)))
|
||||||
|
data += "[ID]: {}\n".format(channel.id)
|
||||||
|
data += "[Default]: {}\n".format(yesno[channel.is_default])
|
||||||
|
data += "[Private]: {}\n".format(yesno[channel.is_private])
|
||||||
|
if str(channel.type) == "text" and channel.topic != "":
|
||||||
|
data += "[Topic]: {}\n".format(channel.topic)
|
||||||
|
data += "[Position]: {}\n".format(channel.position)
|
||||||
|
data += "[Created]: {} ago\n".format(self._dynamic_time(channel.created_at))
|
||||||
|
data += "[Type]: {}\n".format(channel.type)
|
||||||
|
if str(channel.type) == "voice":
|
||||||
|
data += "[Users]: {}\n".format(len(channel.voice_members))
|
||||||
|
data += "[User limit]: {}\n".format(channel.user_limit)
|
||||||
|
data += "[Bitrate]: {}\n".format(channel.bitrate)
|
||||||
|
data += "```"
|
||||||
|
await asyncio.sleep(2)
|
||||||
|
await self.bot.edit_message(waiting, data)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
@checks.is_owner()
|
||||||
|
async def ecogs(self, ctx):
|
||||||
|
"""Lists status of installed cogs"""
|
||||||
|
owner_cog = self.bot.get_cog("Owner")
|
||||||
|
total_cogs = owner_cog._list_cogs()
|
||||||
|
loaded = [c.__module__.split(".")[1] for c in self.bot.cogs.values()]
|
||||||
|
unloaded = [c.split(".")[1] for c in total_cogs if c.split(".")[1] not in loaded]
|
||||||
|
if not unloaded:
|
||||||
|
unloaded = ["None"]
|
||||||
|
|
||||||
|
items = {
|
||||||
|
0: {
|
||||||
|
"cogs": sorted(loaded),
|
||||||
|
"msg": "**{} loaded:**\n".format(len(loaded)),
|
||||||
|
"colour": discord.Colour.dark_green(),
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
"cogs": sorted(unloaded),
|
||||||
|
"msg": "**{} unloaded:**\n".format(len(unloaded)),
|
||||||
|
"colour": discord.Colour.dark_red(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for index, em in enumerate(items):
|
||||||
|
e = discord.Embed(
|
||||||
|
description=items[index]["msg"] + ", ".join(items[index]["cogs"]),
|
||||||
|
colour=items[index]["colour"],
|
||||||
|
)
|
||||||
|
await self.bot.say(embed=e)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def eid(self, ctx, emoji):
|
||||||
|
"""Get an id for a custom emoji."""
|
||||||
|
if emoji[0] != "<":
|
||||||
|
await self.bot.say(
|
||||||
|
"I could not an ID for this emoji, this may be because it is not a custom emoji."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
id = emoji.split(":")[2][:-1]
|
||||||
|
await self.bot.say(id)
|
||||||
|
|
||||||
|
@checks.is_owner()
|
||||||
|
@commands.command(aliases=["find", "cmd_lookup"])
|
||||||
|
async def findcog(self, command: str):
|
||||||
|
"""Cog search by command.
|
||||||
|
This is only applicable for loaded cogs that were installed through [p]cog install."""
|
||||||
|
try:
|
||||||
|
cog_name = self.bot.get_cog(self.bot.get_command(command).cog_name).__module__[5:]
|
||||||
|
except:
|
||||||
|
await self.bot.say(
|
||||||
|
"Either that command doesn't exist, or the cog this command belongs to wasn't added through the downloader cog."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
repos = dataIO.load_json("data/downloader/repos.json")
|
||||||
|
cog_path = (
|
||||||
|
lambda x: "\n".join(
|
||||||
|
[
|
||||||
|
filename
|
||||||
|
for filename in glob.iglob("data/downloader/**/*.py", recursive=True)
|
||||||
|
if "{}.py".format(x) == filename[((len("{}.py".format(x))) * -1) :]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)(cog_name)
|
||||||
|
if not cog_path:
|
||||||
|
await self.bot.say("This is a command that's in a cog that's not published in a repo.")
|
||||||
|
return
|
||||||
|
if os.name == "nt":
|
||||||
|
repo = cog_path.split(os.sep)[1]
|
||||||
|
else:
|
||||||
|
repo = cog_path.split(os.sep)[2]
|
||||||
|
if "url" not in repos[repo]:
|
||||||
|
with open("data/downloader/" + repo + "/.git/config", "r") as f:
|
||||||
|
url = re.findall(r"(http(s)?:\/\/[a-zA-Z0-9\:\.\-\_\/\?\=\%]*)", f.read())[0][0]
|
||||||
|
else:
|
||||||
|
url = repos[repo]["url"]
|
||||||
|
await self.bot.say(
|
||||||
|
box(
|
||||||
|
"Command name: {}\nMade by: {}\nRepo: {}\nCog Name: {}.py".format(
|
||||||
|
command, url.split("/")[3], url, cog_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@checks.admin_or_permissions(manage_roles=True)
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def inrole(self, ctx, *, rolename):
|
||||||
|
"""Check members in the role specified."""
|
||||||
|
await self.bot.send_typing(ctx.message.channel)
|
||||||
|
role = discord.utils.find(
|
||||||
|
lambda r: r.name.lower() == rolename.lower(), ctx.message.server.roles
|
||||||
|
)
|
||||||
|
|
||||||
|
if role is None:
|
||||||
|
roles = []
|
||||||
|
for r in ctx.message.server.roles:
|
||||||
|
if rolename.lower() in r.name.lower():
|
||||||
|
roles.append(r)
|
||||||
|
|
||||||
|
if len(roles) == 1:
|
||||||
|
role = roles[0]
|
||||||
|
elif len(roles) < 1:
|
||||||
|
await self.bot.say("no roles found")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
msg = "**Roles found with** {} **in the name.**\n\n".format(rolename)
|
||||||
|
tbul8 = []
|
||||||
|
for num, role in enumerate(roles):
|
||||||
|
tbul8.append([num + 1, role.name])
|
||||||
|
m1 = await self.bot.say(msg + tabulate(tbul8, tablefmt="plain"))
|
||||||
|
response = await self.bot.wait_for_message(
|
||||||
|
author=ctx.message.author, channel=ctx.message.channel, timeout=25
|
||||||
|
)
|
||||||
|
if response is None:
|
||||||
|
await self.bot.delete_message(m1)
|
||||||
|
return
|
||||||
|
elif response.content.isdigit():
|
||||||
|
await self.bot.delete_message(m1)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
response = int(response.content)
|
||||||
|
|
||||||
|
if response not in range(0, len(roles) + 1):
|
||||||
|
await self.bot.delete_message(m1)
|
||||||
|
return
|
||||||
|
elif response == 0:
|
||||||
|
await self.bot.delete_message(m1)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
role = roles[response - 1]
|
||||||
|
|
||||||
|
if (
|
||||||
|
role is not None
|
||||||
|
and len([m for m in ctx.message.server.members if role in m.roles]) < 50
|
||||||
|
):
|
||||||
|
awaiter = await self.bot.say(
|
||||||
|
embed=discord.Embed(description="Getting member names...")
|
||||||
|
)
|
||||||
|
await asyncio.sleep(2.5)
|
||||||
|
role_member = discord.Embed(
|
||||||
|
description="**{1} users found in the {0} role.**\n".format(
|
||||||
|
role.name, len([m for m in ctx.message.server.members if role in m.roles])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
role_users = [m.display_name for m in ctx.message.server.members if role in m.roles]
|
||||||
|
if not role_users:
|
||||||
|
role_member.add_field(name="Users", value="None.")
|
||||||
|
else:
|
||||||
|
role_member.add_field(name="Users", value="\n".join(role_users))
|
||||||
|
await self.bot.edit_message(awaiter, embed=role_member)
|
||||||
|
|
||||||
|
elif len([m for m in ctx.message.server.members if role in m.roles]) > 50:
|
||||||
|
awaiter = await self.bot.say(
|
||||||
|
embed=discord.Embed(description="Getting member names...")
|
||||||
|
)
|
||||||
|
await asyncio.sleep(2.5)
|
||||||
|
await self.bot.edit_message(
|
||||||
|
awaiter,
|
||||||
|
embed=discord.Embed(
|
||||||
|
description="List is too long for **{0}** role, **{1}** members found.\n".format(
|
||||||
|
role.name, len([m.mention for m in server.members if role in m.roles])
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
embed = discord.Embed(description="Role was not found.")
|
||||||
|
await self.bot.edit_message(embed=embed)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
async def newusers(self, ctx, count: int = 5, server: discord.Server = None):
|
||||||
|
"""Lists the newest 5 members."""
|
||||||
|
if server is None:
|
||||||
|
server = ctx.message.server
|
||||||
|
count = max(min(count, 25), 5)
|
||||||
|
members = sorted(server.members, key=lambda m: m.joined_at, reverse=True)[:count]
|
||||||
|
e = discord.Embed(title="New Members")
|
||||||
|
for member in members:
|
||||||
|
msg = "**Joined Server:** {} ago\n**Account created:** {} ago".format(
|
||||||
|
self._dynamic_time(member.joined_at), self._dynamic_time(member.created_at)
|
||||||
|
)
|
||||||
|
e.add_field(
|
||||||
|
name="{0.display_name} (ID: {0.id})".format(member), value=msg, inline=False
|
||||||
|
)
|
||||||
|
await self.bot.say(embed=e)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
|
async def sid(self, ctx):
|
||||||
|
"""Shows the server ID."""
|
||||||
|
await self.bot.say("**{0.name} ID:** {0.id}".format(ctx.message.server))
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
async def userstats(self, ctx, this_server: bool = False):
|
||||||
|
"""A small amount of user stats."""
|
||||||
|
embeds = {}
|
||||||
|
if this_server:
|
||||||
|
members = set([x for x in ctx.message.server.members])
|
||||||
|
else:
|
||||||
|
members = set([x for x in self.bot.get_all_members()])
|
||||||
|
|
||||||
|
items = {
|
||||||
|
2: {
|
||||||
|
"users": len([e.name for e in members if e.status == discord.Status.idle]),
|
||||||
|
"colour": discord.Colour.orange(),
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
"users": len([e.name for e in members if e.status == discord.Status.dnd]),
|
||||||
|
"colour": discord.Colour.red(),
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
"users": len([e.name for e in members if e.status == discord.Status.offline]),
|
||||||
|
"colour": discord.Colour.dark_grey(),
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
"users": len([e.name for e in members if e.status == discord.Status.online]),
|
||||||
|
"colour": discord.Colour.green(),
|
||||||
|
},
|
||||||
|
0: {
|
||||||
|
"users": len([e.name for e in members if e.game and e.game.url]),
|
||||||
|
"colour": discord.Colour.dark_purple(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
embeds[item] = discord.Embed(
|
||||||
|
description="Users: {}".format(items[item]["users"]), colour=items[item]["colour"]
|
||||||
|
)
|
||||||
|
for i, em in enumerate(embeds):
|
||||||
|
await self.bot.say(embed=embeds[i])
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
|
async def sinfo(self, ctx, server: discord.Server = None):
|
||||||
|
"""Shows server information."""
|
||||||
|
if server is None:
|
||||||
|
server = ctx.message.server
|
||||||
|
online = str(
|
||||||
|
len(
|
||||||
|
[
|
||||||
|
m.status
|
||||||
|
for m in server.members
|
||||||
|
if str(m.status) == "online" or str(m.status) == "idle"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
total_users = str(len(server.members))
|
||||||
|
text_channels = [x for x in server.channels if str(x.type) == "text"]
|
||||||
|
voice_channels = [x for x in server.channels if str(x.type) == "voice"]
|
||||||
|
|
||||||
|
load = "```\nLoading server info...```"
|
||||||
|
waiting = await self.bot.say(load)
|
||||||
|
|
||||||
|
data = "```ini\n"
|
||||||
|
data += "[Name]: {}\n".format(server.name)
|
||||||
|
data += "[ID]: {}\n".format(server.id)
|
||||||
|
data += "[Region]: {}\n".format(server.region)
|
||||||
|
data += "[Owner]: {}\n".format(server.owner)
|
||||||
|
data += "[Users]: {}/{}\n".format(online, total_users)
|
||||||
|
data += "[Text]: {} channels\n".format(len(text_channels))
|
||||||
|
data += "[Voice]: {} channels\n".format(len(voice_channels))
|
||||||
|
data += "[Emojis]: {}\n".format(len(server.emojis))
|
||||||
|
data += "[Roles]: {} \n".format(len(server.roles))
|
||||||
|
data += "[Created]: {} ago\n```".format(self._dynamic_time(server.created_at))
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
await self.bot.edit_message(waiting, data)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
async def perms(self, ctx, user: discord.Member = None):
|
||||||
|
"""Fetch a specific user's permissions."""
|
||||||
|
if user is None:
|
||||||
|
user = ctx.message.author
|
||||||
|
|
||||||
|
perms = iter(ctx.message.channel.permissions_for(user))
|
||||||
|
perms_we_have = "```diff\n"
|
||||||
|
perms_we_dont = ""
|
||||||
|
for x in perms:
|
||||||
|
if "True" in str(x):
|
||||||
|
perms_we_have += "+\t{0}\n".format(str(x).split("'")[1])
|
||||||
|
else:
|
||||||
|
perms_we_dont += "-\t{0}\n".format(str(x).split("'")[1])
|
||||||
|
await self.bot.say("{0}{1}```".format(perms_we_have, perms_we_dont))
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def rid(self, ctx, rolename):
|
||||||
|
"""Shows the id of a role, use quotes on the role."""
|
||||||
|
await self.bot.send_typing(ctx.message.channel)
|
||||||
|
if rolename is discord.Role:
|
||||||
|
role = rolename
|
||||||
|
else:
|
||||||
|
role = self._role_from_string(ctx.message.server, rolename)
|
||||||
|
if role is None:
|
||||||
|
return await self.bot.say(embed=discord.Embed(description="Cannot find role."))
|
||||||
|
await self.bot.say(
|
||||||
|
embed=discord.Embed(description="**{}** ID: {}".format(rolename, role.id))
|
||||||
|
)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def rinfo(self, ctx, rolename):
|
||||||
|
"""Shows role info, use quotes on the role."""
|
||||||
|
server = ctx.message.server
|
||||||
|
colour = str(random.randint(0, 0xFFFFFF))
|
||||||
|
colour = int(colour, 16)
|
||||||
|
await self.bot.send_typing(ctx.message.channel)
|
||||||
|
|
||||||
|
try:
|
||||||
|
caller = inspect.currentframe().f_back.f_code.co_name
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if type(rolename) is not discord.Role:
|
||||||
|
role = discord.utils.find(
|
||||||
|
lambda r: r.name.lower() == rolename.lower(), ctx.message.server.roles
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
role = rolename
|
||||||
|
if role is None:
|
||||||
|
await self.bot.say("That role cannot be found.")
|
||||||
|
return
|
||||||
|
if role is not None:
|
||||||
|
perms = iter(role.permissions)
|
||||||
|
perms_we_have = ""
|
||||||
|
perms_we_dont = ""
|
||||||
|
for x in perms:
|
||||||
|
if "True" in str(x):
|
||||||
|
perms_we_have += "{0}\n".format(str(x).split("'")[1])
|
||||||
|
else:
|
||||||
|
perms_we_dont += "{0}\n".format(str(x).split("'")[1])
|
||||||
|
msg = discord.Embed(description="Gathering role stats...", colour=role.color)
|
||||||
|
if role.color is None:
|
||||||
|
role.color = discord.Colour(value=colour)
|
||||||
|
msg2 = await self.bot.say(embed=msg)
|
||||||
|
em = discord.Embed(colour=role.colour)
|
||||||
|
if caller == "whatis":
|
||||||
|
em.add_field(name="Server", value=role.server.name)
|
||||||
|
em.add_field(name="Role Name", value=role.name)
|
||||||
|
em.add_field(name="Created", value=self._dynamic_time(role.created_at))
|
||||||
|
em.add_field(
|
||||||
|
name="Users in Role",
|
||||||
|
value=len([m for m in ctx.message.server.members if role in m.roles]),
|
||||||
|
)
|
||||||
|
em.add_field(name="Id", value=role.id)
|
||||||
|
em.add_field(name="Color", value=role.color)
|
||||||
|
em.add_field(name="Position", value=role.position)
|
||||||
|
em.add_field(name="Valid Permissons", value="{}".format(perms_we_have))
|
||||||
|
em.add_field(name="Invalid Permissons", value="{}".format(perms_we_dont))
|
||||||
|
em.set_thumbnail(url=role.server.icon_url)
|
||||||
|
try:
|
||||||
|
await self.bot.edit_message(msg2, embed=em)
|
||||||
|
except discord.HTTPException:
|
||||||
|
perms_msg = "```diff\n"
|
||||||
|
role = discord.utils.find(
|
||||||
|
lambda r: r.name.lower() == rolename.lower(), ctx.message.server.roles
|
||||||
|
)
|
||||||
|
if role is None:
|
||||||
|
await bot.say("That role cannot be found.")
|
||||||
|
return
|
||||||
|
if role is not None:
|
||||||
|
perms = iter(role.permissions)
|
||||||
|
perms_we_have2 = ""
|
||||||
|
perms_we_dont2 = ""
|
||||||
|
for x in perms:
|
||||||
|
if "True" in str(x):
|
||||||
|
perms_we_have2 += "+{0}\n".format(str(x).split("'")[1])
|
||||||
|
else:
|
||||||
|
perms_we_dont2 += "-{0}\n".format(str(x).split("'")[1])
|
||||||
|
await self.bot.say(
|
||||||
|
"{}Name: {}\nCreated: {}\nUsers in Role : {}\nId : {}\nColor : {}\nPosition : {}\nValid Perms : \n{}\nInvalid Perms : \n{}```".format(
|
||||||
|
perms_msg,
|
||||||
|
role.name,
|
||||||
|
self._dynamic_time(role.created_at),
|
||||||
|
len([m for m in server.members if role in m.roles]),
|
||||||
|
role.id,
|
||||||
|
role.color,
|
||||||
|
role.position,
|
||||||
|
perms_we_have2,
|
||||||
|
perms_we_dont2,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
await self.bot.delete_message(msg2)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, hidden=True)
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
|
async def sharedservers(self, ctx, user: discord.Member = None):
|
||||||
|
"""Shows shared server info. Defaults to author."""
|
||||||
|
author = ctx.message.author
|
||||||
|
server = ctx.message.server
|
||||||
|
if not user:
|
||||||
|
user = author
|
||||||
|
seen = len(
|
||||||
|
set(
|
||||||
|
[
|
||||||
|
member.server.name
|
||||||
|
for member in self.bot.get_all_members()
|
||||||
|
if member.name == user.name
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sharedservers = str(
|
||||||
|
set(
|
||||||
|
[
|
||||||
|
member.server.name
|
||||||
|
for member in self.bot.get_all_members()
|
||||||
|
if member.name == user.name
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for shared in sharedservers:
|
||||||
|
shared = "".strip("'").join(sharedservers).strip("'")
|
||||||
|
shared = shared.strip("{").strip("}")
|
||||||
|
|
||||||
|
data = "[Servers]: {} shared\n".format(seen)
|
||||||
|
data += "[In Servers]: {}\n".format(shared)
|
||||||
|
|
||||||
|
for page in pagify(data, ["\n"], shorten_by=13, page_length=2000):
|
||||||
|
await self.bot.say(box(page, "ini"))
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def uinfo(self, ctx, user: discord.Member = None):
|
||||||
|
"""Shows user information. Defaults to author."""
|
||||||
|
if not user:
|
||||||
|
user = ctx.message.author
|
||||||
|
try:
|
||||||
|
caller = inspect.currentframe().f_back.f_code.co_name
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
roles = [x.name for x in user.roles if x.name != "@everyone"]
|
||||||
|
if not roles:
|
||||||
|
roles = ["None"]
|
||||||
|
seen = str(
|
||||||
|
len(
|
||||||
|
set(
|
||||||
|
[
|
||||||
|
member.server.name
|
||||||
|
for member in self.bot.get_all_members()
|
||||||
|
if member.id == user.id
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
load = "```\nLoading user info...```"
|
||||||
|
waiting = await self.bot.say(load)
|
||||||
|
|
||||||
|
data = "```ini\n"
|
||||||
|
data += "[Name]: {}\n".format(escape_mass_mentions(str(user)))
|
||||||
|
data += "[Nickname]: {}\n".format(escape_mass_mentions(str(user.nick)))
|
||||||
|
data += "[ID]: {}\n".format(user.id)
|
||||||
|
data += "[Status]: {}\n".format(user.status)
|
||||||
|
data += "[Servers]: {} shared\n".format(seen)
|
||||||
|
if user.game is None:
|
||||||
|
pass
|
||||||
|
elif user.game.url is None:
|
||||||
|
data += "[Playing]: {}\n".format(escape_mass_mentions(str(user.game)))
|
||||||
|
else:
|
||||||
|
data += "[Streaming]: [{}]({})\n".format(
|
||||||
|
escape_mass_mentions(str(user.game)), escape_mass_mentions(user.game.url)
|
||||||
|
)
|
||||||
|
passed = (ctx.message.timestamp - user.created_at).days
|
||||||
|
data += "[Created]: {} ago\n".format(self._dynamic_time(user.created_at))
|
||||||
|
joined_at = self.fetch_joined_at(user, ctx.message.server)
|
||||||
|
if caller != "whatis":
|
||||||
|
data += "[Joined]: {} ago\n".format(self._dynamic_time(joined_at))
|
||||||
|
data += "[Roles]: {}\n".format(", ".join(roles))
|
||||||
|
data += "[In Voice]: {}\n".format(str(user.voice_channel))
|
||||||
|
data += "[AFK]: {}\n".format(user.is_afk)
|
||||||
|
data += "```"
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
await self.bot.edit_message(waiting, data)
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def whatis(self, ctx, id):
|
||||||
|
"""What is it?"""
|
||||||
|
server = ctx.message.server
|
||||||
|
channel = ctx.message.channel
|
||||||
|
author = ctx.message.author
|
||||||
|
|
||||||
|
it_is = False
|
||||||
|
msg = False
|
||||||
|
|
||||||
|
if server.id == id:
|
||||||
|
it_is = server
|
||||||
|
elif channel.id == id:
|
||||||
|
it_is = channel
|
||||||
|
elif author.id == id:
|
||||||
|
it_is = author
|
||||||
|
|
||||||
|
if not it_is:
|
||||||
|
for server in self.bot.servers:
|
||||||
|
if server.id == id:
|
||||||
|
it_is = server
|
||||||
|
break
|
||||||
|
if not it_is:
|
||||||
|
for emoji in self.bot.get_all_emojis():
|
||||||
|
if emoji.id == id:
|
||||||
|
it_is = emoji
|
||||||
|
break
|
||||||
|
if not it_is:
|
||||||
|
for server in self.bot.servers:
|
||||||
|
for role in server.roles:
|
||||||
|
if role.id == id:
|
||||||
|
it_is = role
|
||||||
|
break
|
||||||
|
if not it_is:
|
||||||
|
for member in self.bot.get_all_members():
|
||||||
|
if member.id == id:
|
||||||
|
it_is = member
|
||||||
|
break
|
||||||
|
if not it_is:
|
||||||
|
for channel in self.bot.get_all_channels():
|
||||||
|
if channel.id == id:
|
||||||
|
it_is = channel
|
||||||
|
break
|
||||||
|
|
||||||
|
if not msg:
|
||||||
|
if type(it_is) == discord.Channel:
|
||||||
|
await ctx.invoke(self.cinfo, it_is)
|
||||||
|
elif type(it_is) == discord.Server:
|
||||||
|
await ctx.invoke(self.sinfo, it_is)
|
||||||
|
elif type(it_is) == discord.User or type(it_is) == discord.Member:
|
||||||
|
await ctx.invoke(self.uinfo, it_is)
|
||||||
|
elif type(it_is) == discord.Role:
|
||||||
|
await ctx.invoke(self.roleinfo, it_is)
|
||||||
|
elif type(it_is) == discord.Emoji:
|
||||||
|
await self.bot.say(
|
||||||
|
"<:{0.name}:{0.id}>\n```ini\n[NAME]: {0.name}\n[SERVER]: {0.server}\n[URL]: {0.url}```".format(
|
||||||
|
it_is
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await self.bot.say(
|
||||||
|
"I could not find anything for this ID, I do not support Message IDs"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await self.bot.say("```\nNothing found for this ID```")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _dynamic_time(time):
|
||||||
|
date_join = datetime.datetime.strptime(str(time), "%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
|
||||||
|
|
||||||
|
m, s = divmod(int(since_join.total_seconds()), 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)
|
||||||
|
|
||||||
|
def fetch_joined_at(self, user, server):
|
||||||
|
return user.joined_at
|
||||||
|
|
||||||
|
def _role_from_string(self, server, rolename, roles=None):
|
||||||
|
if roles is None:
|
||||||
|
roles = server.roles
|
||||||
|
role = discord.utils.find(lambda r: r.name.lower() == rolename.lower(), roles)
|
||||||
|
return role
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
cmds = [
|
||||||
|
"access",
|
||||||
|
"banlist",
|
||||||
|
"cid",
|
||||||
|
"cinfo",
|
||||||
|
"ecogs",
|
||||||
|
"eid",
|
||||||
|
"findcog",
|
||||||
|
"inrole",
|
||||||
|
"newusers",
|
||||||
|
"perms",
|
||||||
|
"rid",
|
||||||
|
"rinfo",
|
||||||
|
"sid",
|
||||||
|
"sinfo",
|
||||||
|
"uinfo",
|
||||||
|
"userstatst",
|
||||||
|
"whatis",
|
||||||
|
]
|
||||||
|
for cmd in cmds:
|
||||||
|
bot.remove_command(cmd)
|
||||||
|
bot.add_cog(Tools(bot))
|
||||||
7
wolfram/info.json
Normal file
7
wolfram/info.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"AUTHOR" : "Paddolicious#8880",
|
||||||
|
"NAME" : "wolfram",
|
||||||
|
"SHORT" : "Query Wolfram|Alpha.",
|
||||||
|
"DESCRIPTION" : "A cog to query Wolfram|Alpha.",
|
||||||
|
"TAGS": ["wolfram"]
|
||||||
|
}
|
||||||
82
wolfram/wolfram.py
Normal file
82
wolfram/wolfram.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import os
|
||||||
|
import aiohttp
|
||||||
|
from discord.ext import commands
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from cogs.utils.dataIO import dataIO
|
||||||
|
from .utils import checks
|
||||||
|
from .utils.chat_formatting import escape_mass_mentions
|
||||||
|
from .utils.chat_formatting import box
|
||||||
|
from __main__ import send_cmd_help
|
||||||
|
|
||||||
|
|
||||||
|
class Wolfram:
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.settings = dataIO.load_json("data/wolfram/settings.json")
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, name="wolfram", aliases=["ask"])
|
||||||
|
async def _wolfram(self, ctx, *arguments: str):
|
||||||
|
"""
|
||||||
|
Ask Wolfram Alpha any question
|
||||||
|
"""
|
||||||
|
api_key = self.settings["WOLFRAM_API_KEY"]
|
||||||
|
if api_key:
|
||||||
|
url = "http://api.wolframalpha.com/v2/query?"
|
||||||
|
query = " ".join(arguments)
|
||||||
|
payload = {"input": query, "appid": api_key}
|
||||||
|
headers = {"user-agent": "Red-cog/1.0.0"}
|
||||||
|
conn = aiohttp.TCPConnector(verify_ssl=False)
|
||||||
|
session = aiohttp.ClientSession(connector=conn)
|
||||||
|
async with 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"):
|
||||||
|
if pt.text:
|
||||||
|
a.append(pt.text.capitalize())
|
||||||
|
if len(a) < 1:
|
||||||
|
message = "There is as yet insufficient data for a meaningful answer."
|
||||||
|
else:
|
||||||
|
message = "\n".join(a[0:3])
|
||||||
|
else:
|
||||||
|
message = (
|
||||||
|
"No API key set for Wolfram Alpha. Get one at http://products.wolframalpha.com/api/"
|
||||||
|
)
|
||||||
|
message = escape_mass_mentions(message)
|
||||||
|
await self.bot.say(box(message))
|
||||||
|
|
||||||
|
@commands.command(pass_context=True, name="setwolframapi", aliases=["setwolfram"])
|
||||||
|
@checks.is_owner()
|
||||||
|
async def _setwolframapi(self, ctx, key: str):
|
||||||
|
"""
|
||||||
|
Set the api-key
|
||||||
|
"""
|
||||||
|
if key:
|
||||||
|
self.settings["WOLFRAM_API_KEY"] = key
|
||||||
|
dataIO.save_json("data/wolfram/settings.json", self.settings)
|
||||||
|
await self.bot.say("Key set.")
|
||||||
|
else:
|
||||||
|
await send_cmd_help(ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def check_folder():
|
||||||
|
if not os.path.exists("data/wolfram"):
|
||||||
|
print("Creating data/wolfram folder...")
|
||||||
|
os.makedirs("data/wolfram")
|
||||||
|
|
||||||
|
|
||||||
|
def check_file():
|
||||||
|
data = {}
|
||||||
|
data["WOLFRAM_API_KEY"] = False
|
||||||
|
f = "data/wolfram/settings.json"
|
||||||
|
if not dataIO.is_valid_json(f):
|
||||||
|
print("Creating default settings.json...")
|
||||||
|
dataIO.save_json(f, data)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
check_folder()
|
||||||
|
check_file()
|
||||||
|
n = Wolfram(bot)
|
||||||
|
bot.add_cog(n)
|
||||||
7
youtube/info.json
Normal file
7
youtube/info.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"AUTHOR" : "Paddolicious#8880 and aikaterna#1393",
|
||||||
|
"NAME" : "youtube",
|
||||||
|
"SHORT" : "Look up videos on YouTube.",
|
||||||
|
"DESCRIPTION" : "Look up videos on YouTube.",
|
||||||
|
"TAGS": ["youtube"]
|
||||||
|
}
|
||||||
41
youtube/youtube.py
Normal file
41
youtube/youtube.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
from discord.ext import commands
|
||||||
|
import aiohttp
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class YouTube:
|
||||||
|
"""Le YouTube Cog"""
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.session = aiohttp.ClientSession()
|
||||||
|
|
||||||
|
async def _youtube_results(self, query: str):
|
||||||
|
try:
|
||||||
|
headers = {"user-agent": "Red-cog/2.0"}
|
||||||
|
async with self.session.get("https://www.youtube.com/results", params={"search_query": query}, headers=headers) as r:
|
||||||
|
result = await r.text()
|
||||||
|
yt_find = re.findall(r"{\"videoId\":\"(.{11})", result)
|
||||||
|
url_list = []
|
||||||
|
for track in yt_find:
|
||||||
|
url = "https://www.youtube.com/watch?v={}".format(track)
|
||||||
|
if url not in url_list:
|
||||||
|
url_list.append(url)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
url_list = ["Something went terribly wrong! [{}]".format(e)]
|
||||||
|
|
||||||
|
return url_list
|
||||||
|
|
||||||
|
@commands.command(pass_context=True)
|
||||||
|
async def youtube(self, ctx, *, query: str):
|
||||||
|
"""Search on Youtube."""
|
||||||
|
result = await self._youtube_results(query)
|
||||||
|
if result:
|
||||||
|
await self.bot.say(result[0])
|
||||||
|
else:
|
||||||
|
await self.bot.say("Nothing found. Try again later.")
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
n = YouTube(bot)
|
||||||
|
bot.add_cog(n)
|
||||||
Reference in New Issue
Block a user