1
0
Fork 0
mirror of https://github.com/myned/modufur.git synced 2024-11-01 21:02:38 +00:00

Merge branch 'dev'

This commit is contained in:
Myned 2017-10-11 03:12:54 -04:00
commit 046a897458
9 changed files with 838 additions and 302 deletions

View file

@ -1,48 +1,44 @@
import json
try:
with open('global_blacklist.json') as infile:
global_blacklist = json.load(infile)
print('\"global_blacklist.json\" loaded.')
with open('blacklists.json') as infile:
blacklists = json.load(infile)
print('\"blacklists.json\" loaded.')
except FileNotFoundError:
with open('global_blacklist.json', 'w+') as iofile:
print('Blacklist file not found: \"global_blacklist.json\" created.')
json.dump([], iofile, indent=4, sort_keys=True)
with open('blacklists.json', 'w+') as iofile:
print('Blacklists file not found: \"blacklists.json\" created and loaded.')
json.dump({'global_blacklist': [], 'guild_blacklist': {}, 'user_blacklist': {}}, iofile, indent=4, sort_keys=True)
iofile.seek(0)
global_blacklist = json.load(iofile)
blacklists = json.load(iofile)
try:
with open('guild_blacklist.json') as infile:
guild_blacklist = json.load(infile)
print('\"guild_blacklist.json\" loaded.')
with open('aliases.json') as infile:
aliases = json.load(infile)
print('\"aliases.json\" loaded.')
except FileNotFoundError:
with open('guild_blacklist.json', 'w+') as iofile:
print('Blacklist file not found: \"guild_blacklist.json\" created.')
json.dump({}, iofile, indent=4, sort_keys=True)
with open('aliases.json', 'w+') as iofile:
print('Aliases file not found: \"aliases.json\" created and loaded.')
json.dump({'global_blacklist': {}, 'guild_blacklist': {}, 'user_blacklist': {}}, iofile, indent=4, sort_keys=True)
iofile.seek(0)
guild_blacklist = json.load(iofile)
try:
with open('user_blacklist.json') as infile:
user_blacklist = json.load(infile)
print('\"user_blacklist.json\" loaded.')
except FileNotFoundError:
with open('user_blacklist.json', 'w+') as iofile:
print('Blacklist file not found: \"user_blacklist.json\" created.')
json.dump({}, iofile, indent=4, sort_keys=True)
iofile.seek(0)
user_blacklist = json.load(iofile)
aliases = json.load(iofile)
import asyncio
import discord
import discord as d
import requests
import traceback
import traceback as tb
import discord as d
from discord import reaction
from discord.ext import commands
from discord.ext.commands import errors
from discord.ext.commands import errors as errext
from discord import errors as err
from cogs import tools
from misc import checks
from misc import exceptions as exc
from utils import formatter, scraper
from utils import utils as u
last_command = {}
HEADERS = {'user-agent': 'Modumind/0.0.1 (Myned)'}
# temp_urls = {}
class MsG:
@ -69,8 +65,23 @@ class MsG:
except exc.ImageError:
await ctx.send('' + ctx.message.author.mention + ' **No image found.**')
except Exception:
await ctx.send(exc.base)
traceback.print_exc(limit=1)
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
# Tag aliases
@commands.command(aliases=['alias', 'a'], brief='e621 Tag aliases', description='e621 | NSFW\nSearch aliases for given tag')
@checks.del_ctx()
async def aliases(self, ctx, tag):
global HEADERS
aliases = []
try:
alias_request = requests.get('https://e621.net/tag_alias/index.json?aliased_to=' + tag + '&approved=true', headers=HEADERS).json()
for dic in alias_request:
aliases.append(dic['name'])
await ctx.send('✅ `' + tag + '` **aliases:**\n```' + formatter.tostring(aliases) + '```')
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
# Reverse image searches a linked image using the public iqdb
@commands.command(name='reverse', aliases=['rev', 'ris'], brief='e621 Reverse image search', description='e621 | NSFW\nReverse-search an image with given URL')
@ -78,106 +89,201 @@ class MsG:
async def reverse_image_search(self, ctx, url):
try:
await ctx.trigger_typing()
await ctx.send('' + ctx.message.author.mention + ' **Probable match:**\n' + scraper.check_match('http://iqdb.harry.lu/?url=' + url))
await ctx.send('' + ctx.message.author.mention + ' **Probable match:**\n' + scraper.check_match('http://iqdb.harry.lu/?url={}'.format(url)))
except exc.MatchError:
await ctx.send('' + ctx.message.author.mention + ' **No probable match.**')
await ctx.send('' + ctx.message.author.mention + ' **No probable match.**', delete_after=10)
except Exception:
await ctx.send(exc.base)
traceback.print_exc(limit=1)
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@commands.command(name='e621p', aliases=['e6p', '6p'])
@checks.del_ctx()
@checks.is_nsfw()
async def e621_paginator(self, ctx, *args):
def react(reaction, user):
if reaction.emoji == '' and reaction.message.content == paginator.content and user is ctx.message.author: raise exc.Left
elif reaction.emoji == '🚫' and reaction.message.content == paginator.content and user is ctx.message.author: raise exc.Abort
elif reaction.emoji == '📁' and reaction.message.content == paginator.content and user is ctx.message.author: raise exc.Save
elif reaction.emoji == '' and reaction.message.content == paginator.content and user is ctx.message.author: raise exc.Right
else: return False
user = ctx.message.author
args = list(args)
limit = 100
try:
await ctx.trigger_typing()
c = 1
posts = self.check_return_posts(ctx=ctx, booru='e621', tags=args, limit=limit)
starred = []
embed = d.Embed(title='/post/{}'.format(list(posts.keys())[c-1]), url='https://e621.net/post/show/{}'.format(list(posts.keys())[c-1]), color=ctx.me.color).set_image(url=list(posts.values())[c-1])
embed.set_author(name=formatter.tostring(args, random=True), url='https://e621.net/post?tags={}'.format(','.join(args)), icon_url=user.avatar_url)
embed.set_footer(text='e621', icon_url='http://ndl.mgccw.com/mu3/app/20141013/18/1413204353554/icon/icon_xl.png')
paginator = await ctx.send(embed=embed)
await paginator.add_reaction('')
await paginator.add_reaction('🚫')
await paginator.add_reaction('📁')
await paginator.add_reaction('')
await asyncio.sleep(1)
while True:
try:
await self.bot.wait_for('reaction_add', check=react, timeout=5*60)
except exc.Left:
if c > 1:
c -= 1
embed.title = '/post/{}'.format(list(posts.keys())[c-1])
embed.url = 'https://e621.net/post/show/{}'.format(list(posts.keys())[c-1])
embed.set_image(url=list(posts.values())[c-1])
await paginator.edit(embed=embed)
except exc.Save:
if list(posts.values())[c-1] not in starred:
starred.append(list(posts.values())[c-1])
except exc.Right:
if c % limit == 0:
await ctx.trigger_typing()
try: posts.update(self.check_return_posts(ctx=ctx, booru='e621', tags=args, limit=limit, previous=posts))
except exc.NotFound:
await paginator.edit(content='❌ **No more images found.**')
c += 1
embed.title = '/post/{}'.format(list(posts.keys())[c-1])
embed.url = 'https://e621.net/post/show/{}'.format(list(posts.keys())[c-1])
embed.set_image(url=list(posts.values())[c-1])
await paginator.edit(embed=embed)
except exc.Abort: await paginator.edit(content='🚫 **Exited paginator.**')
except exc.TagBlacklisted as e: await ctx.send('❌ `{}` **blacklisted.**'.format(e), delete_after=10)
except exc.TagBoundsError as e: await ctx.send('❌ `{}` **out of bounds.** Tags limited to 5, currently.'.format(e), delete_after=10)
except exc.Timeout: await ctx.send('❌ **Request timed out.**')
except asyncio.TimeoutError: await paginator.edit(content='❌ **Paginator timed out.**')
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
finally:
if starred:
for url in starred: await user.send(url)
@e621_paginator.error
async def e621_paginator_error(self, ctx, error):
if isinstance(error, errext.CheckFailure):
return await ctx.send('❌ <#' + str(ctx.message.channel.id) + '> **is not an NSFW channel.**', delete_after=10)
# Searches for and returns images from e621.net given tags when not blacklisted
@commands.command(aliases=['e6', '6'], brief='e621 | NSFW', description='e621 | NSFW\nTag-based search for e621.net\n\nYou can only search 5 tags and 6 images at once for now.\ne6 [tags...] ([# of images])')
@checks.del_ctx()
@checks.is_nsfw()
async def e621(self, ctx, *args):
global global_blacklist, guild_blacklist, user_blacklist
# global temp_urls
args = list(args)
limit = 1
try:
await ctx.trigger_typing()
await self.check_send_urls(ctx, 'e621', args)
except exc.TagBlacklisted as e:
await ctx.send('❌ `' + str(e) + '` **blacklisted.**', delete_after=10)
except exc.BoundsError as e:
await ctx.send('❌ `' + str(e) + '` **out of bounds.**', delete_after=10)
except exc.TagBoundsError as e:
await ctx.send('❌ `' + str(e) + '` **out of bounds.** Tags limited to 5, currently.', delete_after=10)
# Checks for, defines, and removes limit from args
for arg in args:
if len(arg) == 1:
if int(arg) <= 6 and int(arg) >= 1:
limit = int(arg)
args.remove(arg)
else: raise exc.BoundsError(arg)
posts = self.check_return_posts(ctx=ctx, booru='e621', tags=args, limit=limit)#, previous=temp_urls.get(ctx.message.author.id, []))
for ident, url in posts.items():
embed = d.Embed(title='/post/{}'.format(ident), url='https://e621.net/post/show/{}'.format(ident), color=ctx.me.color).set_image(url=url)
embed.set_author(name=formatter.tostring(args, random=True), url='https://e621.net/post?tags={}'.format(','.join(args)), icon_url=ctx.message.author.avatar_url)
embed.set_footer(text='e621', icon_url='http://ndl.mgccw.com/mu3/app/20141013/18/1413204353554/icon/icon_xl.png')
await ctx.send(embed=embed)
# temp_urls.setdefault(ctx.message.author.id, []).extend(posts.values())
except exc.TagBlacklisted as e: await ctx.send('❌ `' + str(e) + '` **blacklisted.**', delete_after=10)
except exc.BoundsError as e: await ctx.send('❌ `' + str(e) + '` **out of bounds.**', delete_after=10)
except exc.TagBoundsError as e: await ctx.send('❌ `' + str(e) + '` **out of bounds.** Tags limited to 5, currently.', delete_after=10)
except exc.NotFound as e: await ctx.send('❌ `' + str(e) + '` **not found.**', delete_after=10)
except exc.Timeout: await ctx.send('❌ **Request timed out.**')
except Exception:
await ctx.send(exc.base)
traceback.print_exc()
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
tools.command_dict.setdefault(str(ctx.message.author.id), {}).update({'command': ctx.command, 'args': ctx.args})
@e621.error
async def e621_error(self, ctx, error):
if isinstance(error, errors.CheckFailure):
if isinstance(error, errext.CheckFailure):
return await ctx.send('❌ <#' + str(ctx.message.channel.id) + '> **is not an NSFW channel.**', delete_after=10)
# Searches for and returns images from e926.net given tags when not blacklisted
@commands.command(aliases=['e9', '9'], brief='e926 | SFW', description='e926 | SFW\nTag-based search for e926.net\n\nYou can only search 5 tags and 6 images at once for now.\ne9 [tags...] ([# of images])')
@checks.del_ctx()
async def e926(self, ctx, *args):
global global_blacklist, guild_blacklist, user_blacklist
# global temp_urls
args = list(args)
limit = 1
try:
await ctx.trigger_typing()
await self.check_send_urls(ctx, 'e926', args)
except exc.TagBlacklisted as e:
await ctx.send('❌ `' + str(e) + '` **blacklisted.**', delete_after=10)
except exc.BoundsError as e:
await ctx.send('❌ `' + str(e) + '` **out of bounds.**', delete_after=10)
except exc.TagBoundsError as e:
await ctx.send('❌ `' + str(e) + '` **out of bounds.** Tags limited to 5, currently.', delete_after=10)
# Checks for, defines, and removes limit from args
for arg in args:
if len(arg) == 1:
if int(arg) <= 6 and int(arg) >= 1:
limit = int(arg)
args.remove(arg)
else: raise exc.BoundsError(arg)
posts = self.check_return_posts(ctx=ctx, booru='e926', tags=args, limit=limit)#, previous=temp_urls.get(ctx.message.author.id, []))
for ident, url in posts.items():
embed = d.Embed(title='/post/{}'.format(ident), url='https://e926.net/post/show/{}'.format(ident), color=ctx.me.color).set_image(url=url)
embed.set_author(name=formatter.tostring(args, random=True), url='https://e621.net/post?tags={}'.format(','.join(args)), icon_url=ctx.message.author.avatar_url)
embed.set_footer(text='e926', icon_url='http://ndl.mgccw.com/mu3/app/20141013/18/1413204353554/icon/icon_xl.png')
await ctx.send(embed=embed)
# temp_urls.setdefault(ctx.message.author.id, []).extend(posts.values())
except exc.TagBlacklisted as e: await ctx.send('❌ `' + str(e) + '` **blacklisted.**', delete_after=10)
except exc.BoundsError as e: await ctx.send('❌ `' + str(e) + '` **out of bounds.**', delete_after=10)
except exc.TagBoundsError as e: await ctx.send('❌ `' + str(e) + '` **out of bounds.** Tags limited to 5, currently.', delete_after=10)
except exc.NotFound as e: await ctx.send('❌ `' + str(e) + '` **not found.**', delete_after=10)
except exc.Timeout: await ctx.send('❌ **Request timed out.**')
except Exception:
await ctx.send(exc.base)
traceback.print_exc(limit=1)
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
# Messy code that checks image limit and tags in blacklists
async def check_send_urls(self, ctx, booru, args):
global global_blacklist, guild_blacklist, user_blacklist
if isinstance(ctx.message.guild, discord.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
def check_return_posts(self, *, ctx, booru='e621', tags=[], limit=1, previous=[]):
global blacklists, aliases, HEADERS
if isinstance(ctx.message.guild, d.Guild): guild = ctx.message.guild
else: guild = ctx.message.channel
channel = ctx.message.channel
user = ctx.message.author
urls = []
limit = 1
# Checks if tags are in the file blacklists
if args:
for tag in args:
if tag == 'swf' or tag == 'webm' or tag in global_blacklist or tag in guild_blacklist.get(str(guild.id), {}).get(str(channel.id), []) or tag in user_blacklist.get(str(user.id), []):
raise exc.TagBlacklisted(tag)
if len(args) > 5:
raise exc.TagBoundsError(formatter.tostring(args[5:]))
# Checks for, defines, and removes limit from end of args
if args and len(args[-1]) == 1:
if int(args[-1]) <= 6 and int(args[-1]) >= 1:
limit = int(args[-1])
args.pop()
else:
raise exc.BoundsError(args[-1])
blacklist = []
# Creates temp blacklist based on context
for k, v in aliases['global_blacklist'].items(): blacklist.extend([k] + v)
for k, v in aliases['guild_blacklist'].get(str(guild.id), {}).get(str(channel.id), {}).items(): blacklist.extend([k] + v)
for k, v in aliases['user_blacklist'].get(str(user.id), {}).items(): blacklist.extend([k] + v)
# Checks if tags are in local blacklists
if tags:
if len(tags) > 5: raise exc.TagBoundsError(formatter.tostring(tags[5:]))
for tag in tags:
if tag == 'swf' or tag == 'webm' or tag in blacklist: raise exc.TagBlacklisted(tag)
# Checks for blacklisted tags in endpoint blacklists - try/except is for continuing the parent loop
while len(urls) < limit:
request = requests.get('https://' + booru + '.net/post/index.json?limit=6&tags=order:random' + formatter.tostring_commas(args)).json()
posts = {}
c = 0
while len(posts) < limit:
if c == 50 + limit: raise exc.Timeout
request = requests.get('https://{}.net/post/index.json?tags={}'.format(booru, ','.join(['order:random'] + tags)), headers=HEADERS).json()
if len(request) == 0: raise exc.NotFound(formatter.tostring(tags))
if len(request) < limit: limit = len(request)
for post in request:
if 'swf' in post['file_ext'] or 'webm' in post['file_ext']:
continue
if 'swf' in post['file_ext'] or 'webm' in post['file_ext']: continue
try:
for tag in global_blacklist:
if tag in post['tags']:
raise exc.Continue
for tag in guild_blacklist.get(str(guild.id), {}).get(str(channel.id), []):
if tag in post['tags']:
raise exc.Continue
for tag in user_blacklist.get(str(user.id), []):
if tag in post['tags']:
raise exc.Continue
except exc.Continue:
continue
if post['file_url'] not in urls:
urls.append(post['file_url'])
if len(urls) == limit:
break
for url in urls:
await ctx.send('`' + formatter.tostring(args) + '`\n' + url)
for tag in blacklist:
if tag in post['tags']: raise exc.Continue
except exc.Continue: continue
if post['file_url'] not in posts.values() and post['file_url'] not in previous: posts[post['id']] = post['file_url']
if len(posts) == limit: break
c += 1
return posts
# Umbrella command structure to manage global, channel, and user blacklists
@commands.group(aliases=['bl', 'b'], brief='Manage blacklists', description='Blacklist base command for managing blacklists\n\n`bl get [blacklist]` to show a blacklist\n`bl set [blacklist] [tags]` to replace a blacklist\n`bl clear [blacklist]` to clear a blacklist\n`bl add [blacklist] [tags]` to add tags to a blacklist\n`bl remove [blacklist] [tags]` to remove tags from a blacklist', usage='[flag] [blacklist] ([tags])')
@ -185,238 +291,254 @@ class MsG:
async def blacklist(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Use a flag to manage blacklists.**\n*Type* `' + ctx.prefix + 'help bl` *for more info.*', delete_after=10)
@blacklist.error
async def blacklist_error(self, ctx, error):
if isinstance(error, commands.CheckFailure):
return await ctx.send('❌ **Insufficient permissions.**', delete_after=10)
if isinstance(error, exc.TagExists):
return await ctx.send('❌ `' + str(exc.TagExists) + '` **already in blacklist.**', delete_after=10)
if isinstance(error, exc.TagError):
return await ctx.send('❌ `' + str(exc.TagError) + '` **not in blacklist.**', delete_after=10)
return await ctx.send('❌ **Insufficient permissions.**')
if isinstance(error, KeyError):
return await ctx.send('❌ **Blacklist does not exist.**', delete_after=10)
@blacklist.command(name='update', aliases=['upd', 'up'])
async def _update_blacklists(self, ctx):
global global_blacklist, guild_blacklist, user_blacklist
with open('global_blacklist.json', 'w') as outfile:
json.dump(global_blacklist, outfile, indent=4, sort_keys=True)
with open('guild_blacklist.json', 'w') as outfile:
json.dump(guild_blacklist, outfile, indent=4, sort_keys=True)
with open('user_blacklist.json', 'w') as outfile:
json.dump(user_blacklist, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Blacklists updated.**')
@blacklist.group(name='get', aliases=['g'])
async def _get_blacklist(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Invalid blacklist.**')
@_get_blacklist.command(name='global', aliases=['gl', 'g'])
async def __get_global_blacklist(self, ctx):
global global_blacklist
await ctx.send('🚫 **Global blacklist:**\n```' + formatter.tostring(global_blacklist) + '```')
global blacklists
await ctx.send('🚫 **Global blacklist:**\n```' + formatter.tostring(blacklists['global_blacklist']) + '```')
@_get_blacklist.command(name='channel', aliases=['ch', 'c'])
async def __get_channel_blacklist(self, ctx):
global guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
global blacklists
if isinstance(ctx.message.guild, d.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
channel = ctx.message.channel
await ctx.send('🚫 <#' + str(channel.id) + '> **blacklist:**\n```' + formatter.tostring(guild_blacklist.get(str(guild.id), {}).get(str(channel.id), [])) + '```')
await ctx.send('🚫 <#' + str(channel.id) + '> **blacklist:**\n```' + formatter.tostring(blacklists['guild_blacklist'].get(str(guild.id), {}).get(str(channel.id), [])) + '```')
@_get_blacklist.command(name='me', aliases=['m'])
async def __get_user_blacklist(self, ctx):
global user_blacklist
global blacklists
user = ctx.message.author
await ctx.send('🚫 ' + user.mention + '**\'s blacklist:**\n```' + formatter.tostring(user_blacklist.get(str(user.id), [])) + '```', delete_after=10)
await ctx.send('🚫 ' + user.mention + '**\'s blacklist:**\n```' + formatter.tostring(blacklists['user_blacklist'].get(str(user.id), [])) + '```', delete_after=10)
@_get_blacklist.command(name='here', aliases=['h'])
async def __get_here_blacklists(self, ctx):
global global_blacklist, guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
global blacklists
if isinstance(ctx.message.guild, d.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
channel = ctx.message.channel
await ctx.send('🚫 **__Blacklisted:__**\n\n**Global:**\n```' + formatter.tostring(global_blacklist) + '```\n**<#' + str(channel.id) + '>:**\n```' + formatter.tostring(guild_blacklist.get(str(guild.id), {}).get(str(channel.id), [])) + '```')
await ctx.send('🚫 **__Blacklisted:__**\n\n**Global:**\n```' + formatter.tostring(blacklists['global_blacklist']) + '```\n**<#' + str(channel.id) + '>:**\n```' + formatter.tostring(blacklists['guild_blacklist'].get(str(guild.id), {}).get(str(channel.id), [])) + '```')
@_get_blacklist.group(name='all', aliases=['a'])
async def __get_all_blacklists(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Invalid blacklist.**')
@__get_all_blacklists.command(name='guild', aliases=['g'])
@commands.has_permissions(manage_channels=True)
async def ___get_all_guild_blacklists(self, ctx):
global guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
global blacklists
if isinstance(ctx.message.guild, d.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
await ctx.send('🚫 **__' + guild.name + ' blacklists:__**\n\n' + formatter.dict_tostring(guild_blacklist.get(str(guild.id), {})))
await ctx.send('🚫 **__' + guild.name + ' blacklists:__**\n\n' + formatter.dict_tostring(blacklists['guild_blacklist'].get(str(guild.id), {})))
@__get_all_blacklists.command(name='user', aliases=['u', 'member', 'm'])
@commands.is_owner()
async def ___get_all_user_blacklists(self, ctx):
global user_blacklist
await ctx.send('🚫 **__User blacklists:__**\n\n' + formatter.dict_tostring(user_blacklist))
global blacklists
await ctx.send('🚫 **__User blacklists:__**\n\n' + formatter.dict_tostring(blacklists['user_blacklist']))
@blacklist.group(name='add', aliases=['a'])
async def _add_tags(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Invalid blacklist.**')
@_add_tags.command(name='global', aliases=['gl', 'g'])
@commands.is_owner()
async def __add_global_tags(self, ctx, *tags):
global global_blacklist
global blacklists, aliases, HEADERS
try:
for tag in tags:
if tag in global_blacklist:
if tag in blacklists['global_blacklist']:
raise exc.TagExists(tag)
global_blacklist.extend(tags)
with open('global_blacklist.json', 'w') as outfile:
json.dump(global_blacklist, outfile, indent=4, sort_keys=True)
blacklists['global_blacklist'].extend(tags)
for tag in tags:
alias_request = requests.get('https://e621.net/tag_alias/index.json?aliased_to=' + tag + '&approved=true', headers=HEADERS).json()
for dic in alias_request:
aliases['global_blacklist'].setdefault(tag, []).append(dic['name'])
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Added to global blacklist:**\n```' + formatter.tostring(tags) + '```', delete_after=5)
except exc.TagExists as e:
await ctx.send('❌ `' + str(e) + '` **already in blacklist.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@_add_tags.command(name='channel', aliases=['ch', 'c'])
@commands.has_permissions(manage_channels=True)
async def __add_channel_tags(self, ctx, *tags):
global guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
global blacklists, aliases, HEADERS
if isinstance(ctx.message.guild, d.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
channel = ctx.message.channel
try:
for tag in tags:
if tag in guild_blacklist.get(str(guild.id), {}).get(str(channel.id), []):
if tag in blacklists['guild_blacklist'].get(str(guild.id), {}).get(str(channel.id), []):
raise exc.TagExists(tag)
guild_blacklist.setdefault(str(guild.id), {}).setdefault(str(channel.id), []).extend(tags)
with open('guild_blacklist.json', 'w') as outfile:
json.dump(guild_blacklist, outfile, indent=4, sort_keys=True)
blacklists['guild_blacklist'].setdefault(str(guild.id), {}).setdefault(str(channel.id), []).extend(tags)
for tag in tags:
alias_request = requests.get('https://e621.net/tag_alias/index.json?aliased_to=' + tag + '&approved=true', headers=HEADERS).json()
for dic in alias_request:
aliases['guild_blacklist'].setdefault(str(guild.id), {}).setdefault(str(channel.id), {}).setdefault(tag, []).append(dic['name'])
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Added to** <#' + str(channel.id) + '> **blacklist:**\n```' + formatter.tostring(tags) + '```', delete_after=5)
except exc.TagExists as e:
await ctx.send('❌ `' + str(e) + '` **already in blacklist.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@_add_tags.command(name='me', aliases=['m'])
async def __add_user_tags(self, ctx, *tags):
global user_blacklist
global blacklists, aliases, HEADERS
user = ctx.message.author
try:
for tag in tags:
if tag in user_blacklist.get(str(user.id), []):
if tag in blacklists['user_blacklist'].get(str(user.id), []):
raise exc.TagExists(tag)
user_blacklist.setdefault(str(user.id), []).extend(tags)
with open('user_blacklist.json', 'w') as outfile:
json.dump(user_blacklist, outfile, indent=4, sort_keys=True)
blacklists['user_blacklist'].setdefault(str(user.id), []).extend(tags)
for tag in tags:
alias_request = requests.get('https://e621.net/tag_alias/index.json?aliased_to=' + tag + '&approved=true', headers=HEADERS).json()
for dic in alias_request:
aliases['user_blacklist'].setdefault(str(user.id), {}).setdefault(tag, []).append(dic['name'])
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('' + user.mention + ' **added:**\n```' + formatter.tostring(tags) + '```', delete_after=5)
except exc.TagExists as e:
await ctx.send('❌ `' + str(e) + '` **already in blacklist.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@blacklist.group(name='remove', aliases=['rm', 'r'])
async def _remove_tags(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Invalid blacklist.**')
@_remove_tags.command(name='global', aliases=['gl', 'g'])
@commands.is_owner()
async def __remove_global_tags(self, ctx, *tags):
global global_blacklist
global blacklists, aliases
try:
for tag in tags:
if tag in global_blacklist:
global_blacklist.remove(tag)
if tag in blacklists['global_blacklist']:
blacklists['global_blacklist'].remove(tag)
del aliases['global_blacklist'][tag]
else:
raise exc.TagError(tag)
with open('global_blacklist.json', 'w') as outfile:
json.dump(global_blacklist, outfile, indent=4, sort_keys=True)
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Removed from global blacklist:**\n```' + formatter.tostring(tags) + '```', delete_after=5)
except exc.TagError as e:
await ctx.send('❌ `' + str(e) + '` **not in blacklist.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@_remove_tags.command(name='channel', aliases=['ch', 'c'])
@commands.has_permissions(manage_channels=True)
async def __remove_channel_tags(self, ctx, *tags):
global guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
global blacklists, aliases
if isinstance(ctx.message.guild, d.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
channel = ctx.message.channel
try:
for tag in tags:
if tag in guild_blacklist.get(str(guild.id), {}).get(str(channel.id), []):
guild_blacklist.get(str(guild.id), {})[str(channel.id)].remove(tag)
if tag in blacklists['guild_blacklist'][str(guild.id)][str(channel.id)]:
blacklists['guild_blacklist'][str(guild.id)][str(channel.id)].remove(tag)
del aliases['guild_blacklist'][str(guild.id)][str(channel.id)][tag]
else:
raise exc.TagError(tag)
with open('guild_blacklist.json', 'w') as outfile:
json.dump(guild_blacklist, outfile, indent=4, sort_keys=True)
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Removed from** <#' + str(channel.id) + '> **blacklist:**\n```' + formatter.tostring(tags) + '```', delete_after=5)
except exc.TagError as e:
await ctx.send('❌ `' + str(e) + '` **not in blacklist.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@_remove_tags.command(name='me', aliases=['m'])
async def __remove_user_tags(self, ctx, *tags):
global user_blacklist
global blacklists, aliases
user = ctx.message.author
try:
for tag in tags:
if tag in user_blacklist.get(str(user.id), []):
user_blacklist.get[str(user.id)].remove(tag)
if tag in blacklists['user_blacklist'][str(user.id)]:
blacklists['user_blacklist'][str(user.id)].remove(tag)
del aliases['user_blacklist'][str(user.id)][tag]
else:
raise exc.TagError(tag)
with open('user_blacklist.json', 'w') as outfile:
json.dump(user_blacklist, outfile, indent=4, sort_keys=True)
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('' + user.mention + ' **removed:**\n```' + formatter.tostring(tags) + '```', delete_after=5)
@blacklist.group(name='set', aliases=['s'])
async def _set_blacklist(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Invalid blacklist.**')
@_set_blacklist.command(name='global', aliases=['gl', 'g'])
@commands.is_owner()
async def __set_global_blacklist(self, ctx, *tags):
global global_blacklist
global_blacklist = tags[:]
with open('global_blacklist.json', 'w') as outfile:
json.dump(global_blacklist, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Global blacklist set to:**\n```' + formatter.tostring(global_blacklist) + '```', delete_after=10)
@_set_blacklist.command(name='channel', aliases=['ch', 'c'])
@commands.has_permissions(manage_channels=True)
async def __set_channel_blacklist(self, ctx, *tags):
global guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
channel = ctx.message.channel
guild_blacklist.setdefault(str(guild.id), {})[str(channel.id)] = tags[:]
with open('guild_blacklist.json', 'w') as outfile:
json.dump(guild_blacklist, outfile, indent=4, sort_keys=True)
await ctx.send('✅ <#' + str(channel.id) + '> **blacklist set to:**\n```' + formatter.tostring(guild_blacklist.get(str(guild.id), {}).get(str(channel.id), [])) + '```', delete_after=10)
@_set_blacklist.command(name='me', aliases=['m'])
async def __set_user_blacklist(self, ctx, *tags):
global user_blacklist
user = ctx.message.author
user_blacklist[str(user.id)] = tags[:]
with open('user_blacklist.json', 'w') as outfile:
json.dump(user_blacklist, outfile, indent=4, sort_keys=True)
await ctx.send('' + user.mention + '**\'s blacklist set to:**\n```' + formatter.tostring(user_blacklist.get(str(user.id), [])) + '```', delete_after=10)
except exc.TagError as e:
await ctx.send('❌ `' + str(e) + '` **not in blacklist.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc()
@blacklist.group(name='clear', aliases=['cl', 'c'])
async def _clear_blacklist(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('❌ **Invalid blacklist.**')
@_clear_blacklist.command(name='global', aliases=['gl', 'g'])
@commands.is_owner()
async def __clear_global_blacklist(self, ctx):
global global_blacklist
del global_blacklist
with open('global_blacklist.json', 'w') as outfile:
json.dump(global_blacklist, outfile, indent=4, sort_keys=True)
global blacklists, aliases
del blacklists['global_blacklist']
del aliases['global_blacklist']
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('✅ **Global blacklist cleared.**', delete_after=5)
@_clear_blacklist.command(name='channel', aliases=['ch', 'c'])
@commands.has_permissions(manage_channels=True)
async def __clear_channel_blacklist(self, ctx):
global guild_blacklist
if isinstance(ctx.message.guild, discord.Guild):
global blacklists, aliases
if isinstance(ctx.message.guild, d.Guild):
guild = ctx.message.guild
else:
guild = ctx.message.channel
channel = ctx.message.channel
del guild_blacklist.get(str(guild.id), {})[str(channel.id)]
with open('guild_blacklist.json', 'w') as outfile:
json.dump(guild_blacklist, outfile, indent=4, sort_keys=True)
del blacklists['guild_blacklist'][str(guild.id)][str(channel.id)]
del aliases['guild_blacklist'][str(guild.id)][str(channel.id)]
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('✅ <#' + str(channel.id) + '> **blacklist cleared.**', delete_after=5)
@_clear_blacklist.command(name='me', aliases=['m'])
async def __clear_user_blacklist(self, ctx):
global user_blacklist
global blacklists, aliases
user = ctx.message.author
del user_blacklist[str(user.id)]
with open('user_blacklist.json', 'w') as outfile:
json.dump(user_blacklist, outfile, indent=4, sort_keys=True)
del blacklists['user_blacklist'][str(user.id)]
del aliases['user_blacklist'][str(user.id)]
with open('blacklists.json', 'w') as outfile:
json.dump(blacklists, outfile, indent=4, sort_keys=True)
with open('aliases.json', 'w') as outfile:
json.dump(aliases, outfile, indent=4, sort_keys=True)
await ctx.send('' + user.mention + '**\'s blacklist cleared.**', delete_after=5)

176
src/main/cogs/management.py Normal file
View file

@ -0,0 +1,176 @@
import asyncio
import discord as d
import traceback
from discord.ext import commands
from misc import checks
from misc import exceptions as exc
from utils import utils as u
RATE_LIMIT = 2.1
class Administration:
def __init__(self, bot):
self.bot = bot
self.queue = asyncio.Queue()
if u.background.get('management', {}):
if u.background['management'].get('auto_delete', {}):
for channel in u.background['management']['auto_delete']:
temp = self.bot.get_channel(channel)
self.bot.loop.create_task(self.on_message(temp))
self.bot.loop.create_task(self.delete())
print('Looping {}'.format(temp.id))
# @commands.group(aliases=['pr', 'clear', 'cl'])
# @commands.is_owner()
# @checks.del_ctx()
# async def prune(self, ctx):
# pass
#
# @prune.group(name='all', aliases=['a'])
# async def _all(self, ctx):
# pass
# @_all.group(name='user')
# async def __user(self, ctx, user: d.Member):
# channels = ctx.message.guild.text_channels
# bulk_history = {}
# bulk = {}
# history = []
# c = 0
# if ctx.invoked_subcommand is None:
# for channel in channels:
# bulk_history[channel] = await channel.history(limit=None, after=dt.datetime.utcnow() - dt.timedelta(days=14)).flatten()
# await ch_sent.edit(content='🗄 **Cached** `' + str(channels.index(channel) + 1) + '/' + str(len(channels)) + '` **channels.**')
# await asyncio.sleep(RATE_LIMIT)
# for channel, messages in bulk_history.items():
# bulk[channel] = [message for message in messages if message.author.id == int(uid)]
# for channel, messages in bulk_history.items():
# bulk[channel] = [bulk[channel][i:i+100] for i in range(0, len(bulk[channel]), 100)]
# await ctx.send('⏱ **Estimated time to delete `bulk-history`:** `' + str(int(RATE_LIMIT * sum([len(v) for v in bulk.values()]) / 60)) + ' mins ' + str(int(RATE_LIMIT * sum([len(v) for v in bulk.values()]) % 60)) + ' secs`')
# check = await ctx.send(ctx.author.mention + ' **Continue?** `Y` or `N`')
# await self.bot.wait_for('message', check=yes, timeout=60)
# del_sent = await ctx.send('🗑 **Deleting messages...**')
# for channel, messages in bulk.items():
# for chunk in messages:
# c += len(chunk)
# await channel.delete_messages(chunk)
# await del_sent.edit(content='🗑 **Deleted** `' + str(c) + '/' + str(sum([len(v) for v in bulk.values()])) + '` **messages.**')
# await asyncio.sleep(5)
# await ctx.send('✅ `' + str(sum([len(v) for v in bulk.values()])) + '` **of** <@' + uid + '>**\'s messages deleted from** ' + ctx.message.guild.name + '**.**')
# for channel in channels:
# history.extend(await channel.history(limit=None, before=dt.datetime.utcnow() - dt.timedelta(days=14)).flatten())
# await ch_sent.edit(content='🗄 **Cached** `' + str(channels.index(channel) + 1) + '/' + str(len(channels)) + '` **channels.**')
# await asyncio.sleep(RATE_LIMIT)
@commands.command(name=',prunefromguild', aliases=[',pfg', ',prunefromserver', ',pfs'], brief='Prune a user\'s messages from the guild', description='about flag centers on message 50 of 101 messages\n\npfg \{user id\} [before|after|about] [\{message id\}]\n\nExample:\npfg \{user id\} before \{message id\}')
@commands.is_owner()
@checks.del_ctx()
async def prune_all_user(self, ctx, uid, when=None, reference=None):
global RATE_LIMIT
def yes(msg):
if msg.content.lower() == 'y' and msg.channel is ctx.message.channel and msg.author is ctx.message.author:
return True
elif msg.content.lower() == 'n' and msg.channel is ctx.message.channel and msg.author is ctx.message.author:
raise exc.CheckFail
else:
return False
channels = ctx.message.guild.text_channels
if reference is not None:
for channel in channels:
try:
ref = await channel.get_message(reference)
except d.errors.NotFound:
continue
history = []
try:
pru_sent = await ctx.send('⌛️ **Pruning** <@{}>**\'s messages will take some time.**'.format(uid))
ch_sent = await ctx.send('🗄 **Caching channels...**')
if when is None:
for channel in channels:
history.extend(await channel.history(limit=None).flatten())
await ch_sent.edit(content='🗄 **Cached** `{}/{}` **channels.**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(RATE_LIMIT)
elif when =='before':
for channel in channels:
history.extend(await channel.history(limit=None, before=ref.created_at).flatten())
await ch_sent.edit(content='🗄 **Cached** `{}/{}` **channels.**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(RATE_LIMIT)
elif when == 'after':
for channel in channels:
history.extend(await channel.history(limit=None, after=ref.created_at).flatten())
await ch_sent.edit(content='🗄 **Cached** `{}/{}` **channels.**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(RATE_LIMIT)
elif when == 'about':
for channel in channels:
history.extend(await channel.history(limit=101, about=ref.created_at).flatten())
await ch_sent.edit(content='🗄 **Cached** `{}/{}` **channels.**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(RATE_LIMIT)
history = [message for message in history if message.author.id == int(uid)]
est_sent = await ctx.send('⏱ **Estimated time to delete history:** `{}m {}s`'.format(int(RATE_LIMIT * len(history) / 60), int(RATE_LIMIT * len(history) % 60)))
cont_sent = await ctx.send('{} **Continue?** `Y` or `N`'.format(ctx.author.mention))
await self.bot.wait_for('message', check=yes, timeout=60)
await cont_sent.delete()
del_sent = await ctx.send('🗑 **Deleting messages...**')
for message in history:
try: await message.delete()
except d.NotFound: pass
# print('Deleted {}/{} messages.'.format(history.index(message) + 1, len(history)))
await del_sent.edit(content='🗑 **Deleted** `{}/{}` **messages.**'.format(history.index(message) + 1, len(history)))
await asyncio.sleep(RATE_LIMIT)
await del_sent.edit(content='🗑 `{}` **of** <@{}>**\'s messages deleted from** {}**.**'.format(len(history), uid, ctx.message.guild.name))
except exc.CheckFail:
await ctx.send('❌ **Deletion aborted.**', delete_after=10)
except TimeoutError:
await ctx.send('❌ **Deletion timed out.**', delete_after=10)
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, traceback.format_exc(limit=1)))
traceback.print_exc(limit=1)
async def delete(self):
while True:
message = await self.queue.get()
await asyncio.sleep(RATE_LIMIT)
await message.delete()
async def on_message(self, channel):
def check(msg):
if msg.content == 'stop' and msg.channel is channel and msg.author.guild_permissions.administrator:
raise exc.Abort
elif msg.channel is channel and not msg.pinned:
return True
else:
return False
try:
while True:
message = await self.bot.wait_for('message', check=check)
await self.queue.put(message)
except d.errors.NotFound:
pass
except exc.Abort:
u.background['management']['auto_delete'].remove(channel.id)
u.update(u.background, 'background.json')
print('Stopped looping {}'.format(channel.id))
await channel.send('✅ **Stopped deleting messages in** {}**.**'.format(channel.mention), delete_after=5)
except AttributeError:
pass
except Exception:
await channel.send(exc.base + '\n```' + traceback.format_exc(limit=1) + '```')
traceback.print_exc(limit=1)
@commands.command(name='autodelete', aliases=['autodel', 'ad'])
@commands.has_permissions(administrator=True)
@checks.del_ctx()
async def auto_delete(self, ctx):
channel = ctx.message.channel
u.background.setdefault('management', {}).setdefault('auto_delete', []).append(channel.id)
u.update(u.background, 'background.json')
self.bot.loop.create_task(self.on_message(channel))
self.bot.loop.create_task(self.delete())
print('Looping {}'.format(channel.id))
await ctx.send('✅ **Auto-deleting all messages in this channel.**', delete_after=5)

98
src/main/cogs/owner.py Normal file
View file

@ -0,0 +1,98 @@
import asyncio
import code
import io
import pyrasite as pyr
import re
import sys
import traceback as tb
import discord as d
from discord.ext import commands
from misc import checks
from misc import exceptions as exc
nl = re.compile('\n')
class Tools:
def __init__(self, bot):
self.bot = bot
def format(self, i='', o=''):
if len(o) > 1: return '>>> {}\n{}'.format(i, o)
else: return '>>> {}'.format(i)
async def generate(self, d, i='', o=''):
return await d.send('```python\n{}```'.format(self.format(i, o)))
async def refresh(self, m, i='', o=''):
global nl
output = m.content[10:-3]
if len(nl.findall(output)) <= 20: await m.edit(content='```python\n{}\n{}\n>>>```'.format(output, self.format(i, o)))
else: await m.edit(content='```python\n{}```'.format(self.format(i, o)))
async def generate_err(self, d, o=''):
return await d.send('```\n{}```'.format(o))
async def refresh_err(self, m, o=''):
await m.edit(content='```\n{}```'.format(o))
@commands.command(name=',console', aliases=[',con', ',c'], hidden=True)
@commands.is_owner()
@checks.del_ctx()
async def console(self, ctx):
def execute(msg):
if msg.content == ',exit' and msg.author is ctx.message.author:
raise exc.CheckFail
elif msg.author is ctx.message.author and msg.channel is ctx.message.channel: return True
else: return False
try:
console = await self.generate(ctx)
exception = await self.generate_err(ctx)
while True:
exe = await self.bot.wait_for('message', check=execute)
await exe.delete()
sys.stdout = io.StringIO()
sys.stderr = io.StringIO()
try: exec(exe.content)
except Exception: tb.print_exc(limit=1)
await self.refresh(console, exe.content, sys.stdout.getvalue())
await self.refresh_err(exception, sys.stderr.getvalue())
await ctx.send(console.content[10:-3])
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
except exc.CheckFail:
await ctx.send('↩️ **Exited console.**')
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc(limit=1, file=sys.__stderr__)
finally:
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
print('Reset sys output.')
@commands.command(name='arbitrary', aliases=[',arbit', ',ar'])
@commands.is_owner()
@checks.del_ctx()
async def arbitrary(self, ctx, *, exe):
try:
sys.stdout = io.StringIO()
exec(exe)
await self.generate(ctx, exe, sys.stdout.getvalue())
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, tb.format_exc(limit=1)))
tb.print_exc(limit=1)
finally:
sys.stdout = sys.__stdout__
print('Reset stdout.')
@commands.group(aliases=[',db'], hidden=True)
@commands.is_owner()
@checks.del_ctx()
async def debug(self, ctx):
console = await self.generate(ctx)
@debug.command(name='inject', aliases=['inj'])
async def _inject(self, ctx, *, input_):
pass
@debug.command(name='inspect', aliases=['ins'])
async def _inspect(self, ctx, *, input_):
pass

View file

@ -1,58 +1,116 @@
import asyncio
import datetime as dt
import discord
import httplib2
import mimetypes
import os
import requests_oauthlib as ro
import tempfile
import traceback
import webbrowser
from discord.ext import commands
#from run import config
from cogs import booru
from misc import checks
from misc import exceptions as exc
from utils import formatter
from apiclient.discovery import build
from apiclient import http
from oauth2client.client import flow_from_clientsecrets
youtube = None
tempfile.tempdir = os.getcwd()
command_dict = {}
class Utils:
def __init__(self, bot):
self.bot = bot
def last():
pass
@commands.command(name='last', aliases=['l', ','], brief='Reinvokes last command', description='Reinvokes previous command executed', hidden=True)
async def last_command(self, ctx):
global command_dict
try:
# await ctx.invoke(command, args)
await ctx.send('`' + booru.last_command[ctx.message.author.id] + '`')
if command_dict.get(str(ctx.message.author.id), {}).get('args', None) is not None:
args = command_dict.get(str(ctx.message.author.id), {})['args']
print(command_dict)
await ctx.invoke(command_dict.get(str(ctx.message.author.id), {}).get('command', None), args)
except Exception:
await ctx.send(exceptions.base)
await ctx.send(exc.base + '\n```' + traceback.format_exc(limit=1) + '```')
traceback.print_exc(limit=1)
# [prefix]ping -> Pong!
@commands.command(aliases=['p'], brief='Pong!', description='Returns latency from bot to Discord servers, not to user')
@checks.del_ctx()
async def ping(self, ctx):
global command_dict
try:
await ctx.send(ctx.message.author.mention + ' 🏓 `' + str(int(self.bot.latency * 1000)) + 'ms`', delete_after=5)
except Exception:
await ctx.send(exceptions.base)
await ctx.send(exc.base + '\n```' + traceback.format_exc(limit=1) + '```')
traceback.print_exc(limit=1)
command_dict.setdefault(str(ctx.message.author.id), {}).update({'command': ctx.command})
@commands.command(aliases=['pre'], brief='List bot prefixes', description='Shows all used prefixes')
@checks.del_ctx()
async def prefix(self, ctx):
try:
await ctx.send('**Prefix:** `,` or ' + ctx.me.mention)
await ctx.send('**Prefix:** `,`')
except Exception:
await ctx.send(exceptions.base)
await ctx.send(exc.base + '\n```' + traceback.format_exc(limit=1) + '```')
traceback.print_exc(limit=1)
@commands.group(name=',send', aliases=[',s'], hidden=True)
@commands.is_owner()
@checks.del_ctx()
async def send(self, ctx):
pass
@send.command(name='guild', aliases=['g', 'server', 's'])
@checks.del_ctx()
async def send_guild(self, ctx, guild, channel, *message):
await discord.utils.get(self.bot.get_all_channels(), guild__name=guild, name=channel).send(formatter.tostring(message))
@send.command(name='user', aliases=['u', 'member', 'm'])
@checks.del_ctx()
async def send_user(self, ctx, user, *message):
await discord.utils.get(self.bot.get_all_members(), id=int(user)).send(formatter.tostring(message))
@commands.command(aliases=['authenticateupload', 'authupload', 'authup', 'auth'])
async def authenticate_upload(self, ctx):
global youtube
flow = flow_from_clientsecrets('client_secrets.json', scope='https://www.googleapis.com/auth/youtube.upload', login_hint='botmyned@gmail.com', redirect_uri='urn:ietf:wg:oauth:2.0:oob')
flow.params['access_type'] = 'offline'
webbrowser.open_new_tab(flow.step1_get_authorize_url())
credentials = flow.step2_exchange(input('Authorization code: '))
youtube = build('youtube', 'v3', http=credentials.authorize(http.build_http()))
print('Service built.')
@commands.command(aliases=['up', 'u', 'vid', 'v'])
@checks.is_listed()
async def upload(self, ctx):
global youtube
attachments = ctx.message.attachments
try:
if not attachments:
raise exc.MissingAttachment
if len(attachments) > 1:
raise exc.TooManyAttachments(len(attachments))
mime = mimetypes.guess_type(attachments[0].filename)[0]
if 'video/' in mime:
with tempfile.NamedTemporaryFile() as temp:
await attachments[0].save(temp)
else:
raise exc.InvalidVideoFile(mime)
print('https://www.youtube.com/watch?v=' + youtube.videos().insert(part='snippet', body={'categoryId': '24', 'title': 'Test'}, media_body=http.MediaFileUpload(temp.name, chunksize=-1)))
except exc.InvalidVideoFile as e:
await ctx.send('❌ `' + str(e) + '` **not valid video type.**', delete_after=10)
except exc.TooManyAttachments as e:
await ctx.send('❌ `' + str(e) + '` **too many attachments.** Only one attachment is permitted to upload.', delete_after=10)
except exc.MissingAttachment:
await ctx.send('❌ **Missing attachment.**', delete_after=10)
except Exception:
await ctx.send(exc.base + '\n```' + traceback.format_exc(limit=1) + '```')
traceback.print_exc(limit=1)
@upload.error
async def upload_error(self, ctx, error):
pass
# http.

View file

@ -9,6 +9,7 @@ with open('config.json') as infile:
config = json.load(infile)
owner_id = config['owner_id']
listed_ids = config['listed_ids']
def is_owner():
async def predicate(ctx):
@ -22,6 +23,10 @@ def is_mod():
def predicate(ctx):
return ctx.message.author.guild_permissions.ban_members
return commands.check(predicate)
def is_listed():
def predicate(ctx):
return ctx.message.author.id in listed_ids
return commands.check(predicate)
def owner(ctx):
return ctx.message.author.id == owner_id

View file

@ -1,24 +1,23 @@
base = ' **An internal error has occurred.** Please notify my master! 🐺'
base = ' **An internal error has occurred.** Please notify my master! 🐺'
class PostError(Exception):
pass
class ImageError(Exception):
pass
class MatchError(Exception):
pass
class TagBlacklisted(Exception):
pass
class BoundsError(Exception):
pass
class TagBoundsError(Exception):
pass
class TagExists(Exception):
pass
class TagError(Exception):
pass
class FlagError(Exception):
pass
class BlacklistError(Exception):
pass
class Continue(Exception):
pass
class Left(Exception): pass
class Right(Exception): pass
class Save(Exception): pass
class PostError(Exception): pass
class ImageError(Exception): pass
class MatchError(Exception): pass
class TagBlacklisted(Exception): pass
class BoundsError(Exception): pass
class TagBoundsError(Exception): pass
class TagExists(Exception): pass
class TagError(Exception): pass
class FlagError(Exception): pass
class BlacklistError(Exception): pass
class NotFound(Exception): pass
class Timeout(Exception): pass
class InvalidVideoFile(Exception): pass
class MissingAttachment(Exception): pass
class TooManyAttachments(Exception): pass
class CheckFail(Exception): pass
class Abort(Exception): pass
class Continue(Exception): pass

View file

@ -6,76 +6,114 @@ try:
print('\"config.json\" loaded.')
except FileNotFoundError:
with open('config.json', 'w') as outfile:
json.dump({'client_id': 0, 'owner_id': 0, 'permissions': 388160, 'prefix': ',', 'shutdown_channel': 0, 'startup_channel': 0, 'token': 'str'}, outfile, indent=4, sort_keys=True)
json.dump({'client_id': 0, 'listed_ids': [0], 'owner_id': 0, 'permissions': 388160, 'prefix': ',', 'shutdown_channel': 0, 'startup_channel': 0, 'token': 'str'}, outfile, indent=4, sort_keys=True)
raise FileNotFoundError('Config file not found: \"config.json\" created with abstract values. Restart \"run.py\" with correct values.')
import asyncio
import discord
import datetime as dt
import discord as d
import os
import subprocess
import sys
import traceback
from discord import utils
from discord.ext import commands
from cogs import booru, info, tools
from cogs import booru, info, owner, management, tools
from misc import checks
from misc import exceptions as exc
from utils import utils as u
bot = commands.Bot(command_prefix=commands.when_mentioned_or(config['prefix']), description='Experimental booru bot')
import logging
logging.basicConfig(level=logging.INFO)
print('PID {}'.format(os.getpid()))
bot = commands.Bot(command_prefix=config['prefix'], description='Experimental booru bot')
# Send and print ready message to #testing and console after logon
@bot.event
async def on_ready():
if isinstance(bot.get_channel(config['startup_channel']), discord.TextChannel):
await bot.get_channel(config['startup_channel']).send('Hello how are? **Have day.** 🌈\n<embed>[STARTUP-INFO]</embed>')
print('Connected.')
print('Username: ' + bot.user.name)
global bot
bot.add_cog(tools.Utils(bot))
bot.add_cog(owner.Tools(bot))
bot.add_cog(management.Administration(bot))
bot.add_cog(info.Info(bot))
bot.add_cog(booru.MsG(bot))
# bot.loop.create_task(u.clear(booru.temp_urls, 30*60))
if isinstance(bot.get_channel(config['startup_channel']), d.TextChannel):
await bot.get_channel(config['startup_channel']).send('**Started.** ☀️')
print('CONNECTED')
print(bot.user.name)
print('-------')
# Close connection to Discord - immediate offline
@bot.command(name=',die', aliases=[',d', ',close', ',kill'], brief='Kills the bot', description='BOT OWNER ONLY\nCloses the connection to Discord', hidden=True)
@checks.del_ctx()
@bot.command(name=',die', aliases=[',d'], brief='Kills the bot', description='BOT OWNER ONLY\nCloses the connection to Discord', hidden=True)
@commands.is_owner()
@checks.del_ctx()
async def die(ctx):
try:
await bot.get_channel(config['shutdown_channel']).send('Am go bye. **Have night.** 💤\n<embed>[SHUTDOWN-INFO]</embed>')
if isinstance(bot.get_channel(config['startup_channel']), d.TextChannel):
await bot.get_channel(config['shutdown_channel']).send('**Shutting down...** 🌙')
await bot.close()
print('-------')
print('Closed.')
print('CLOSED')
except Exception:
await ctx.send(exc.base)
await ctx.send(exc.base + '\n```' + traceback.format_exc(limit=1) + '```')
traceback.print_exc(limit=1)
@bot.command(name=',restart', aliases=[',res', ',r'], hidden=True)
@commands.is_owner()
@checks.del_ctx()
async def restart(ctx):
try:
print('RESTARTING')
print('-------')
if isinstance(bot.get_channel(config['startup_channel']), d.TextChannel):
await bot.get_channel(config['shutdown_channel']).send('**Restarting...** 💤')
os.execl(sys.executable, 'python3', 'run.py')
except Exception:
await ctx.send('{}\n```{}```'.format(exc.base, traceback.format_exc(limit=1)))
traceback.print_exc(limit=1)
# Invite bot to bot owner's server
@bot.command(name=',invite', aliases=[',inv', ',link'], brief='Invite the bot', description='BOT OWNER ONLY\nInvite the bot to a server (Requires admin)', hidden=True)
@checks.del_ctx()
@commands.is_owner()
@checks.del_ctx()
async def invite(ctx):
try:
await ctx.send('🔗 https://discordapp.com/oauth2/authorize?&client_id=' + str(config['client_id']) + '&scope=bot&permissions=' + str(config['permissions']))
await ctx.send('🔗 https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}'.format(config['client_id'], config['permissions']), delete_after=10)
except Exception:
await ctx.send(exc.base)
await ctx.send('{}\n```{}```'.format(exc.base, traceback.format_exc(limit=1)))
traceback.print_exc(limit=1)
@bot.command(brief='[IN TESTING]', description='[IN TESTING]', hidden=True)
async def hi(ctx):
user = ctx.message.author
try:
hello = 'Hello, ' + ctx.message.author.mention + '.'
if ctx.message.author.id == checks.owner_id:
hello = 'Hewwo, {}.'.format(user.mention)
if user.id == checks.owner_id:
hello += '.. ***Master.*** uwu'
elif ctx.message.author.guild_permissions.administrator:
hello = hello[:7] + '**Admin** ' + hello[7:]
elif ctx.message.author.guild_permissions.ban_members:
hello = hello[:7] + '**Mod** ' + hello[7:]
elif user.guild_permissions.administrator:
hello = '{} **Admin** {}'.format(hello[:7], hello[7:])
elif user.guild_permissions.ban_members:
hello = '{} **Mod** {}'.format(hello[:7], hello[7:])
await ctx.send(hello)
except Exception:
await ctx.send(exc.base)
await ctx.send('{}\n```{}```'.format(exc.base, traceback.format_exc(limit=1)))
traceback.print_exc(limit=1)
@bot.command(hidden=True)
@bot.command(name=',test', hidden=True)
@commands.is_owner()
@checks.del_ctx()
async def test(ctx):
pass
bot.add_cog(info.Info(bot))
bot.add_cog(tools.Utils(bot))
bot.add_cog(booru.MsG(bot))
embed = d.Embed(title='/post/xxxxxx', url='https://static1.e621.net/data/4b/3e/4b3ec0c2e8580f418e4ce019dfd5ac32.png', timestamp=dt.datetime.utcnow(), color=ctx.me.color)
embed.set_image(url='https://static1.e621.net/data/27/0f/270fd28caa5e6d8bf542a76515848e02.png')
embed.set_footer(text='e621', icon_url='http://ndl.mgccw.com/mu3/app/20141013/18/1413204353554/icon/icon_xl.png')
embed.set_author(name='tags', url=ctx.message.author.avatar_url, icon_url=ctx.message.author.avatar_url)
embed.add_field(name='Link', value='https://static1.e621.net/data/c2/55/c255792b5a307ee6efa51d6bb3edf878.jpg')
await ctx.send(embed=embed)
bot.run(config['token'])

View file

@ -1,9 +1,13 @@
def tostring(i):
o = ' '
def tostring(i, *, random=False):
o = ''
if i:
for v in i:
o += v + ' '
o = o[1:-1]
o = o[:-1]
elif random is True:
o += 'order:random'
else:
o = ' '
return o
def tostring_commas(i):

36
src/main/utils/utils.py Normal file
View file

@ -0,0 +1,36 @@
import json
try:
with open('background.json') as infile:
background = json.load(infile)
print('\"background.json\" loaded.')
except FileNotFoundError:
with open('background.json', 'w+') as iofile:
print('Background file not found: \"background.json\" created and loaded.')
json.dump({}, iofile, indent=4, sort_keys=True)
iofile.seek(0)
background = json.load(iofile)
with open('config.json') as infile:
config = json.load(infile)
def update(out, file):
with open(file, 'w') as outfile:
json.dump(out, outfile, indent=4, sort_keys=True)
import asyncio
async def clear(obj, interval=10*60, replace=None):
if replace is None:
if type(obj) is list:
replace = []
elif type(obj) is dict:
replace = {}
elif type(obj) is int:
replace = 0
elif type(obj) is str:
replace = ''
while True:
obj = replace
asyncio.sleep(interval)