1
0
Fork 0
mirror of https://github.com/myned/modufur.git synced 2024-12-25 06:37:29 +00:00

Merge branch 'dev'

This commit is contained in:
Myned 2017-12-31 21:56:23 -05:00
commit 523ab37fe6
9 changed files with 2021 additions and 1868 deletions

View file

@ -55,6 +55,11 @@ class MsG:
print('STARTED : auto-reversifying in #{}'.format(temp.name)) print('STARTED : auto-reversifying in #{}'.format(temp.name))
self.reversifying = True self.reversifying = True
self.bot.loop.create_task(self._reversify()) self.bot.loop.create_task(self._reversify())
if u.tasks['auto_hrt']:
for channel in u.tasks['auto_hrt']:
temp = self.bot.get_channel(channel)
self.bot.loop.create_task(self.queue_for_hearts(channel=temp))
print(f'STARTED : auto-hearting in #{temp.name}')
# if not self.updating: # if not self.updating:
# self.updating = True # self.updating = True
# self.bot.loop.create_task(self._update_suggested()) # self.bot.loop.create_task(self._update_suggested())
@ -124,32 +129,92 @@ class MsG:
while self.hearting: while self.hearting:
temp = await self.heartqueue.get() temp = await self.heartqueue.get()
if isinstance(temp[1], d.Embed):
await temp[0].send(embed=temp[1]) await temp[0].send(embed=temp[1])
await asyncio.sleep(self.RATE_LIMIT) await asyncio.sleep(self.RATE_LIMIT)
elif isinstance(temp[1], d.Message):
for match in re.finditer('(https?:\/\/[^ ]*\.(?:gif|png|jpg|jpeg))', temp[1].content):
await temp[0].send(match)
await asyncio.sleep(self.RATE_LIMIT)
for attachment in temp[1].attachments:
await temp[0].send(attachment.url)
await asyncio.sleep(self.RATE_LIMIT)
print('STOPPED : hearting') print('STOPPED : hearting')
async def queue_for_hearts(self, *, message, send): async def queue_for_hearts(self, *, message=None, send=None, channel=None, reaction=True, timeout=60 * 60):
def on_reaction(reaction, user): def on_reaction(reaction, user):
if reaction.emoji == '\N{HEAVY BLACK HEART}' and reaction.message.id == message.id: if reaction.emoji == '\N{HEAVY BLACK HEART}' and reaction.message.id == message.id:
raise exc.Save(user) raise exc.Save(user)
return False return False
def on_message(msg):
if 'stop h' in msg.content.lower():
raise exc.Abort
return msg.channel.id == channel.id and (re.search('(https?:\/\/[^ ]*\.(?:gif|png|jpg|jpeg))', msg.content) or msg.attachments)
if message:
try: try:
if reaction:
await message.add_reaction('\N{HEAVY BLACK HEART}') await message.add_reaction('\N{HEAVY BLACK HEART}')
await asyncio.sleep(1) await asyncio.sleep(1)
while self.hearting: while self.hearting:
try: try:
await asyncio.gather(*[self.bot.wait_for('reaction_add', check=on_reaction, timeout=60 * 60), await self.bot.wait_for('reaction_add', check=on_reaction, timeout=timeout)
self.bot.wait_for('reaction_remove', check=on_reaction, timeout=60 * 60)])
except exc.Save as e: except exc.Save as e:
await self.heartqueue.put((e.user, send)) await self.heartqueue.put((e.user, send if send else message))
except asyncio.TimeoutError: except asyncio.TimeoutError:
await message.add_reaction('\N{WHITE HEAVY CHECK MARK}') await message.add_reaction('\N{WHITE HEAVY CHECK MARK}')
else:
try:
async for message in channel.history(limit=300):
if re.search('(https?:\/\/[^ ]*\.(?:gif|png|jpg|jpeg))', message.content) or message.attachments:
self.bot.loop.create_task(self._wait_for_reaction(message))
while self.hearting:
message = await self.bot.wait_for('message', check=on_message)
self.bot.loop.create_task(self._wait_for_reaction(message))
except exc.Abort:
u.tasks['auto_hrt'].remove(channel.id)
u.dump(u.tasks, 'cogs/tasks.pkl')
print('STOPPED : auto-hearting in #{}'.format(channel.name))
await channel.send('**Stopped queueing messages for hearting in** {}'.format(channel.mention), delete_after=5)
async def _wait_for_reaction(self, message):
def on_reaction(reaction, user):
if reaction.emoji == '\N{HEAVY BLACK HEART}' and reaction.message.id == message.id:
raise exc.Save(user)
return False
while self.hearting:
try:
await self.bot.wait_for('reaction_add', check=on_reaction)
except exc.Save as e:
await self.heartqueue.put((e.user, message))
@cmds.command(name='autoheart', aliases=['autohrt'])
@cmds.has_permissions(administrator=True)
async def auto_heart(self, ctx):
try:
if ctx.channel.id not in u.tasks['auto_hrt']:
u.tasks['auto_hrt'].append(ctx.channel.id)
u.dump(u.tasks, 'cogs/tasks.pkl')
self.bot.loop.create_task(self.queue_for_hearts(channel=ctx.channel))
print('STARTED : auto-hearting in #{}'.format(ctx.channel.name))
await ctx.send('**Auto-hearting all messages in {}**'.format(ctx.channel.mention), delete_after=5)
else:
raise exc.Exists
except exc.Exists:
await ctx.send('**Already auto-hearting in {}.** Type `stop h(earting)` to stop.'.format(ctx.channel.mention), delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
# @cmds.command() # @cmds.command()
# async def auto_post(self, ctx): # async def auto_post(self, ctx):
@ -261,7 +326,7 @@ class MsG:
embed = d.Embed( embed = d.Embed(
title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else u.color) title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else u.color)
embed.set_thumbnail(url=post['file_url']) embed.set_thumbnail(url=post['file_url'])
embed.set_author(name=f'{u.get_aspectratio(post["width"], post["height"])} \N{ZERO WIDTH SPACE} {post["width"]} x {post["height"]}', embed.set_author(name=f'{post["width"]} x {post["height"]}',
url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=ctx.author.avatar_url) url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=ctx.author.avatar_url)
embed.set_footer(text=post['score'], embed.set_footer(text=post['score'],
icon_url=self._get_score(post['score'])) icon_url=self._get_score(post['score']))
@ -373,7 +438,7 @@ class MsG:
embed = d.Embed( embed = d.Embed(
title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else u.color) title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else u.color)
embed.set_image(url=post['file_url']) embed.set_image(url=post['file_url'])
embed.set_author(name=f'{u.get_aspectratio(post["width"], post["height"])} \N{ZERO WIDTH SPACE} {post["width"]} x {post["height"]}', embed.set_author(name=f'{post["width"]} x {post["height"]}',
url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=ctx.author.avatar_url) url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=ctx.author.avatar_url)
embed.set_footer(text=post['score'], embed.set_footer(text=post['score'],
icon_url=self._get_score(post['score'])) icon_url=self._get_score(post['score']))
@ -436,7 +501,7 @@ class MsG:
embed = d.Embed( embed = d.Embed(
title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else u.color) title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=ctx.me.color if isinstance(ctx.channel, d.TextChannel) else u.color)
embed.set_image(url=post['file_url']) embed.set_image(url=post['file_url'])
embed.set_author(name=f'{u.get_aspectratio(post["width"], post["height"])} \N{ZERO WIDTH SPACE} {post["width"]} x {post["height"]}', embed.set_author(name=f'{post["width"]} x {post["height"]}',
url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=ctx.author.avatar_url) url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=ctx.author.avatar_url)
embed.set_footer( embed.set_footer(
text=post['score'], icon_url=self._get_score(post['score'])) text=post['score'], icon_url=self._get_score(post['score']))
@ -492,33 +557,35 @@ class MsG:
embed = d.Embed( embed = d.Embed(
title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=message.channel.guild.me.color if isinstance(message.channel, d.TextChannel) else u.color) title=', '.join(post['artist']), url=f'https://e621.net/post/show/{post["id"]}', color=message.channel.guild.me.color if isinstance(message.channel, d.TextChannel) else u.color)
embed.set_image(url=post['file_url']) embed.set_image(url=post['file_url'])
embed.set_author(name=f'{u.get_aspectratio(post["width"], post["height"])} \N{ZERO WIDTH SPACE} {post["width"]} x {post["height"]}', embed.set_author(name=f'{post["width"]} x {post["height"]}',
url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=message.author.avatar_url) url=f'https://e621.net/post?tags=ratio:{post["width"]/post["height"]:.2f}', icon_url=message.author.avatar_url)
embed.set_footer(text=post['score'], embed.set_footer(text=post['score'],
icon_url=self._get_score(post['score']['score'])) icon_url=self._get_score(post['score']))
await message.channel.send('**Probable match from** {}'.format(message.author.display_name), embed=embed) await message.channel.send('**Probable match from** {}'.format(message.author.display_name), embed=embed)
await message.add_reaction('\N{WHITE HEAVY CHECK MARK}') await message.add_reaction('\N{WHITE HEAVY CHECK MARK}')
await asyncio.sleep(self.RATE_LIMIT)
with suppress(err.NotFound):
await message.delete()
except exc.MatchError as e: except exc.MatchError as e:
await message.channel.send('**No probable match for:** `{}`'.format(e), delete_after=7) await message.channel.send('**No probable match for:** `{}`'.format(e), delete_after=7)
await message.add_reaction('\N{CROSS MARK}') await message.add_reaction('\N{CROSS MARK}')
except exc.SizeError as e: except exc.SizeError as e:
await message.channel.send(f'`{e}` **too large.** Maximum is 8 MB', delete_after=7) await message.channel.send(f'`{e}` **too large.** Maximum is 8 MB', delete_after=7)
await message.add_reaction('\N{CROSS MARK}') await message.add_reaction('\N{CROSS MARK}')
except Exception:
finally: await message.channel.send(f'**An unknown error occurred.**', delete_after=7)
await asyncio.sleep(self.RATE_LIMIT) await message.add_reaction('\N{WARNING SIGN}')
with suppress(err.NotFound):
await message.delete()
print('STOPPED : reversifying') print('STOPPED : reversifying')
async def queue_for_reversification(self, channel): async def queue_for_reversification(self, channel):
def check(msg): def check(msg):
if msg.content.lower() == 'stop' and msg.channel is channel and msg.author.guild_permissions.administrator: if 'stop r' in msg.content.lower() and msg.channel is channel and msg.author.guild_permissions.administrator:
raise exc.Abort raise exc.Abort
elif msg.channel is channel and msg.author.id != self.bot.user.id and (re.search('(https?:\/\/[^ ]*\.(?:gif|png|jpg|jpeg))', msg.content) is not None or msg.attachments or msg.embeds): elif msg.channel is channel and msg.author.id != self.bot.user.id and (re.search('(https?:\/\/[^ ]*\.(?:gif|png|jpg|jpeg))', msg.content) is not None or msg.attachments or msg.embeds):
return True return True
@ -553,7 +620,7 @@ class MsG:
print('STARTED : auto-reversifying in #{}'.format(ctx.channel.name)) print('STARTED : auto-reversifying in #{}'.format(ctx.channel.name))
await ctx.send('**Auto-reversifying all images in** {}'.format(ctx.channel.mention), delete_after=5) await ctx.send('**Auto-reversifying all images in** {}'.format(ctx.channel.mention), delete_after=5)
else: else:
await ctx.send('**Already auto-reversifying in {}.** Type `stop` to stop.'.format(ctx.channel.mention), delete_after=7) await ctx.send('**Already auto-reversifying in {}.** Type `stop r(eversifying)` to stop.'.format(ctx.channel.mention), delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
async def _get_pool(self, ctx, *, destination, booru='e621', query=[]): async def _get_pool(self, ctx, *, destination, booru='e621', query=[]):

View file

@ -116,6 +116,10 @@ class Administration:
await ctx.send('**Deletion timed out**', delete_after=7) await ctx.send('**Deletion timed out**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@cmds.group(aliases=['task', 'tsk'])
async def tasks(self):
pass
async def delete(self): async def delete(self):
while self.deleting: while self.deleting:
message = await self.queue.get() message = await self.queue.get()
@ -128,7 +132,7 @@ class Administration:
async def queue_for_deletion(self, channel): async def queue_for_deletion(self, channel):
def check(msg): def check(msg):
if msg.content.lower() == 'stop' and msg.channel is channel and msg.author.guild_permissions.administrator: if 'stop d' in msg.content.lower() and msg.channel is channel and msg.author.guild_permissions.administrator:
raise exc.Abort raise exc.Abort
elif msg.channel is channel and not msg.pinned: elif msg.channel is channel and not msg.pinned:
return True return True
@ -136,7 +140,7 @@ class Administration:
try: try:
async for message in channel.history(limit=None): async for message in channel.history(limit=None):
if message.content.lower() == 'stop' and message.author.guild_permissions.administrator: if 'stop d' in message.content.lower() and message.author.guild_permissions.administrator:
raise exc.Abort raise exc.Abort
if not message.pinned: if not message.pinned:
await self.queue.put(message) await self.queue.put(message)
@ -170,7 +174,7 @@ class Administration:
raise exc.Exists raise exc.Exists
except exc.Exists: except exc.Exists:
await ctx.send('**Already auto-deleting in {}.** Type `stop` to stop.'.format(ctx.channel.mention), delete_after=7) await ctx.send('**Already auto-deleting in {}.** Type `stop d(eleting)` to stop.'.format(ctx.channel.mention), delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
@cmds.group(aliases=['setting', 'set', 's']) @cmds.group(aliases=['setting', 'set', 's'])
@ -179,7 +183,7 @@ class Administration:
pass pass
@settings.command(name='deletecommands', aliases=['delcmds', 'delcmd']) @settings.command(name='deletecommands', aliases=['delcmds', 'delcmd'])
async def _settings_delete_commands(self, ctx): async def _settings_deletecommands(self, ctx):
if ctx.guild.id not in u.settings['del_ctx']: if ctx.guild.id not in u.settings['del_ctx']:
u.settings['del_ctx'].append(ctx.guild.id) u.settings['del_ctx'].append(ctx.guild.id)
else: else:
@ -197,3 +201,13 @@ class Administration:
del u.settings['prefixes'][ctx.guild.id] del u.settings['prefixes'][ctx.guild.id]
await ctx.send(f'**Prefix set to:** `{"` or `".join(prefixes if ctx.guild.id in u.settings["prefixes"] else u.config["prefix"])}`') await ctx.send(f'**Prefix set to:** `{"` or `".join(prefixes if ctx.guild.id in u.settings["prefixes"] else u.config["prefix"])}`')
@settings.command(name='deleteresponses', aliases=['delresps', 'delresp'])
async def _settings_deleteresponses(self, ctx):
if ctx.guild.id not in u.settings['del_resp']:
u.settings['del_resp'].append(ctx.guild.id)
else:
u.settings['del_resp'].remove(ctx.guild.id)
u.dump(u.settings, 'settings.pkl')
await ctx.send(f'**Delete command responses:** `{ctx.guild.id in u.settings["del_resp"]}`')

57
src/cogs/music.py Normal file
View file

@ -0,0 +1,57 @@
import asyncio
import json
from datetime import datetime as dt
from urllib import parse
import re
from pprint import pprint
import discord as d
from discord import errors as err
from discord.ext import commands as cmds
from discord.ext.commands import errors as errext
import gmusicapi as gpm
import googleapiclient as gapic
import apiclient as apic
from misc import exceptions as exc
from misc import checks
from utils import utils as u
class Music:
def __init__(self, bot):
self.bot = bot
self.yt_service = apic.discovery.build('youtube', 'v3', developerKey=u.secrets['client_secrets']['client_secret'])
@cmds.group(aliases=['pl'], brief='(G) Play music', description='Play music from YouTube, Soundcloud, or Google Play Music')
async def play(self, ctx):
print(ctx.invoked_subcommand)
@play.command(name='youtube', aliases=['you', 'tube', 'yt', 'y'])
async def _play_youtube(self, ctx, *videos):
try:
if not videos:
raise exc.MissingArgument
vids = []
for video in videos:
if 'http' in video and 'youtube' in video:
vids.append(parse.parse_qs(parse.urlparse(video).query)['v'][0])
else:
vids.append(video)
print(vids)
response = self.yt_service.videos().list(part='snippet', id=','.join(vids)).execute()
pprint(response)
except exc.MissingArgument:
await ctx.send('**Invalid youtube url or ID**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
@play.command(name='googleplaymusic', aliases=['googleplay', 'googlemusic', 'playmusic', 'play', 'gpm'])
async def _play_googleplaymusic(self, ctx, query):
pass

View file

@ -23,3 +23,11 @@ class Post:
async def _check_posts(self, user, channel): async def _check_posts(self, user, channel):
pass pass
@cmds.group(aliases=['update', 'up', 'u'])
async def updates(self, ctx):
pass
@updates.command(name='googleplaymusic', aliases=['googlemusic', 'playmusic', 'music', 'gpm'])
async def _updates_googleplaymusic(self, ctx):
pass

View file

@ -39,9 +39,9 @@ class Right(Exception):
class Save(Exception): class Save(Exception):
def __init__(self, user=None): def __init__(self, user=None, message=None):
self.user = user self.user = user
self.message = message
class GoTo(Exception): class GoTo(Exception):
pass pass

View file

@ -70,9 +70,11 @@ async def test(ctx):
@bot.event @bot.event
async def on_ready(): async def on_ready():
if not checks.ready: if not checks.ready:
from cogs import booru, info, management, owner, tools # d.opus.load_opus('opuslib')
for cog in (tools.Utils(bot), owner.Bot(bot), owner.Tools(bot), management.Administration(bot), info.Info(bot), booru.MsG(bot)): from cogs import booru, info, management, music, owner, tools
for cog in (tools.Utils(bot), owner.Bot(bot), owner.Tools(bot), management.Administration(bot), music.Music(bot), info.Info(bot), booru.MsG(bot)):
bot.add_cog(cog) bot.add_cog(cog)
print(f'COG : {type(cog).__name__}') print(f'COG : {type(cog).__name__}')
@ -157,6 +159,11 @@ async def on_command_error(ctx, error):
await ctx.message.add_reaction('\N{WARNING SIGN}') await ctx.message.add_reaction('\N{WARNING SIGN}')
# u.notify('C O M M A N D E R R O R') # u.notify('C O M M A N D E R R O R')
# @bot.event
# async def on_command(ctx):
# if ctx.guild.id in u.settings['del_resp']:
# pass
@bot.event @bot.event
async def on_command_completion(ctx): async def on_command_completion(ctx):
with suppress(err.NotFound): with suppress(err.NotFound):
@ -183,8 +190,6 @@ async def on_guild_remove(guild):
print(f'STOPPED : {task} in #{channel.id}') print(f'STOPPED : {task} in #{channel.id}')
u.dump(u.tasks, 'cogs/tasks.pkl') u.dump(u.tasks, 'cogs/tasks.pkl')
# d.opus.load_opus('opus')
async def wait(voice): async def wait(voice):
asyncio.sleep(5) asyncio.sleep(5)

0
src/temp/__init__.py Normal file
View file

View file

@ -15,6 +15,7 @@ async def get_post(url):
filesize = int(image.headers['Content-Length']) filesize = int(image.headers['Content-Length'])
if filesize > 8192 * 1024: if filesize > 8192 * 1024:
raise exc.SizeError(size(filesize, system=alternative)) raise exc.SizeError(size(filesize, system=alternative))
except ValueError: except ValueError:
raise exc.MissingArgument raise exc.MissingArgument

View file

@ -82,9 +82,10 @@ def dump(obj, filename, *, json=False):
jsn.dump(obj, outfile, indent=4, sort_keys=True) jsn.dump(obj, outfile, indent=4, sort_keys=True)
settings = setdefault('misc/settings.pkl', {'del_ctx': [], 'prefixes': {}}) settings = setdefault('misc/settings.pkl', {'del_ctx': [], 'del_resp': [], 'prefixes': {}})
tasks = setdefault('cogs/tasks.pkl', {'auto_del': [], 'auto_rev': [], 'periodic_gpm': []}) tasks = setdefault('cogs/tasks.pkl', {'auto_del': [], 'auto_hrt': [], 'auto_rev': [], 'periodic_gpm': []})
temp = setdefault('temp/temp.pkl', {'startup': ()}) temp = setdefault('temp/temp.pkl', {'startup': ()})
secrets = setdefault('secrets.json', {'client_secrets': {'client_id': '', 'client_secret': ''}}, json=True)
RATE_LIMIT = 2.2 RATE_LIMIT = 2.2
color = d.Color(0x1A1A1A) color = d.Color(0x1A1A1A)