Merge branch 'master' of https://github.com/Phxntxm/Bonfire
This commit is contained in:
commit
4b870fcc0d
10 changed files with 245 additions and 64 deletions
2
bot.py
2
bot.py
|
@ -66,7 +66,7 @@ async def process_command(ctx):
|
|||
command_usage['member_usage'] = total_member_usage
|
||||
|
||||
# Add one to the server's usage for this command
|
||||
if message.server is not None:
|
||||
if ctx.message.server is not None:
|
||||
total_server_usage = command_usage.get('server_usage', {})
|
||||
server_usage = total_server_usage.get(server.id, 0) + 1
|
||||
total_server_usage[server.id] = server_usage
|
||||
|
|
|
@ -172,8 +172,8 @@ class Core:
|
|||
|
||||
cmd = None
|
||||
page = 1
|
||||
|
||||
perms = self.bot.permissions_in(ctx.message.channel)
|
||||
if ctx.message.server:
|
||||
perms = ctx.message.server.me.permissions_in(ctx.message.channel)
|
||||
if not (perms.embed_links and perms.add_reactions):
|
||||
fmt = "I need the permissions `embed_links` and `add_reactions` to send my help message! " \
|
||||
" Otherwise you can use this link to view available commands {}".format(
|
||||
|
|
|
@ -110,7 +110,12 @@ class Music:
|
|||
@commands.command(pass_context=True, no_pm=True, enabled=False)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
async def queue(self, ctx):
|
||||
"""Provides a printout of the songs that are in the queue
|
||||
"""Provides a printout of the songs that are in the queue.
|
||||
\N{LEFTWARDS BLACK ARROW}: Goes to the previous page
|
||||
\N{BLACK RIGHTWARDS ARROW}: Goes to the next page
|
||||
\N{DOWNWARDS BLACK ARROW}: Moves the current song showing back in the queue
|
||||
\N{UPWARDS BLACK ARROW}: Moves the current song showing up in the queue
|
||||
\N{CROSS MARK}: Removes the current song showing from the queue
|
||||
|
||||
EXAMPLE: !queue
|
||||
RESULT: A list of shitty songs you probably don't wanna listen to"""
|
||||
|
|
|
@ -138,7 +138,11 @@ class Interaction:
|
|||
if file is None:
|
||||
await self.bot.say(url)
|
||||
else:
|
||||
await self.bot.upload(file, filename='avatar.jpg')
|
||||
if '.gif' in url:
|
||||
filename = 'avatar.gif'
|
||||
else:
|
||||
filename = 'avatar.webp'
|
||||
await self.bot.upload(file, filename=filename)
|
||||
else:
|
||||
await self.bot.say(url)
|
||||
|
||||
|
|
179
cogs/music.py
179
cogs/music.py
|
@ -9,6 +9,8 @@ import time
|
|||
import asyncio
|
||||
import re
|
||||
import os
|
||||
import glob
|
||||
import socket
|
||||
|
||||
if not discord.opus.is_loaded():
|
||||
discord.opus.load_opus('/usr/lib64/libopus.so.0')
|
||||
|
@ -33,6 +35,7 @@ class VoiceState:
|
|||
}
|
||||
self.volume = 50
|
||||
self.downloader = download
|
||||
self.file_names = []
|
||||
|
||||
def is_playing(self):
|
||||
# If our VoiceClient or current VoiceEntry do not exist, then we are not playing a song
|
||||
|
@ -58,8 +61,6 @@ class VoiceState:
|
|||
self.player.stop()
|
||||
|
||||
def toggle_next(self):
|
||||
# Delete the old file (screw caching, when on 5000+ Guilds this takes up too much space)
|
||||
os.remove(self.current.filename)
|
||||
# Set the Event so that the next song in the queue can be played
|
||||
self.bot.loop.call_soon_threadsafe(self.play_next_song.set)
|
||||
|
||||
|
@ -74,6 +75,7 @@ class VoiceState:
|
|||
|
||||
# Make sure we find a song
|
||||
while self.current is None:
|
||||
self.clear_audio_files()
|
||||
await asyncio.sleep(1)
|
||||
self.current = await self.songs.get_next_entry()
|
||||
|
||||
|
@ -82,6 +84,10 @@ class VoiceState:
|
|||
print("Downloading...")
|
||||
await asyncio.sleep(1)
|
||||
|
||||
# Now add this file to our list of filenames, so that it can be deleted later
|
||||
if self.current.filename not in self.file_names:
|
||||
self.file_names.append(self.current.filename)
|
||||
|
||||
# Create the player object
|
||||
self.current.player = self.voice.create_ffmpeg_player(
|
||||
self.current.filename,
|
||||
|
@ -100,6 +106,11 @@ class VoiceState:
|
|||
# Wait till the Event has been set, before doing our task again
|
||||
await self.play_next_song.wait()
|
||||
|
||||
def clear_audio_files(self):
|
||||
"""Deletes all the audio files this guild has created"""
|
||||
for f in self.file_names:
|
||||
os.remove(f)
|
||||
self.file_names = []
|
||||
|
||||
class Music:
|
||||
"""Voice related commands.
|
||||
|
@ -112,6 +123,12 @@ class Music:
|
|||
down = Downloader(download_folder='audio_tmp')
|
||||
self.downloader = down
|
||||
self.bot.downloader = down
|
||||
self.clear_audio_tmp()
|
||||
|
||||
def clear_audio_tmp(self):
|
||||
files = glob.glob('audio_tmp/*')
|
||||
for f in files:
|
||||
os.remove(f)
|
||||
|
||||
def get_voice_state(self, server):
|
||||
state = self.voice_states.get(server.id)
|
||||
|
@ -132,7 +149,9 @@ class Music:
|
|||
server = channel.server
|
||||
state = self.get_voice_state(server)
|
||||
voice = self.bot.voice_client_in(server)
|
||||
|
||||
# Attempt 3 times
|
||||
for i in range(3):
|
||||
try:
|
||||
if voice is None:
|
||||
state.voice = await self.bot.join_voice_channel(channel)
|
||||
return True
|
||||
|
@ -143,6 +162,9 @@ class Music:
|
|||
await voice.disconnect()
|
||||
state.voice = await self.bot.join_voice_channel(channel)
|
||||
return True
|
||||
except (discord.ClientException, socket.gaierror):
|
||||
continue
|
||||
|
||||
|
||||
async def remove_voice_client(self, server):
|
||||
"""Removes any voice clients from a server
|
||||
|
@ -171,11 +193,126 @@ class Music:
|
|||
if state.voice is None:
|
||||
return
|
||||
voice_channel = state.voice.channel
|
||||
if voice_channel != before.voice.voice_channel and voice_channel != after.voice.voice_channel:
|
||||
return
|
||||
num_members = len(voice_channel.voice_members)
|
||||
state.required_skips = math.ceil((num_members + 1) / 3)
|
||||
|
||||
async def queue_embed_task(self, state, channel, author):
|
||||
index = 0
|
||||
message = None
|
||||
fmt = None
|
||||
# Our check to ensure the only one who reacts is the bot
|
||||
def check(reaction, user):
|
||||
return user == author
|
||||
possible_reactions = ['\u27A1', '\u2B05', '\u2b06', '\u2b07', '\u274c']
|
||||
while True:
|
||||
# Get the current queue (It might change while we're doing this)
|
||||
# So do this in the while loop
|
||||
queue = state.songs.entries
|
||||
count = len(queue)
|
||||
# This means the last song was removed
|
||||
if count == 0:
|
||||
await self.bot.send_message(channel, "Nothing currently in the queue")
|
||||
break
|
||||
# Get the current entry
|
||||
entry = queue[index]
|
||||
# Get the entry's embed
|
||||
embed = entry.to_embed()
|
||||
# Set the embed's title to indicate the amount of things in the queue
|
||||
count = len(queue)
|
||||
embed.title = "Current Queue [{}/{}]".format(index+1, count)
|
||||
# Now we need to send the embed, so check if the message is already set
|
||||
# If not, then we need to send a new one (i.e. this is the first time called)
|
||||
if message:
|
||||
message = await self.bot.edit_message(message, fmt, embed=embed)
|
||||
# There's only one reaction we want to make sure we remove in the circumstances
|
||||
# If the member doesn't have kick_members permissions, and isn't the requester
|
||||
# Then they can't remove the song, otherwise they can
|
||||
if not author.server_permissions.kick_members and author != entry.requester:
|
||||
try:
|
||||
await self.bot.remove_reaction(message, '\u274c', channel.server.me)
|
||||
except:
|
||||
pass
|
||||
elif not author.server_permissions.kick_members and author == entry.requester:
|
||||
try:
|
||||
await self.bot.add_reaction(message, '\u274c')
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
message = await self.bot.send_message(channel, embed=embed)
|
||||
await self.bot.add_reaction(message, '\N{LEFTWARDS BLACK ARROW}')
|
||||
await self.bot.add_reaction(message, '\N{BLACK RIGHTWARDS ARROW}')
|
||||
# The moderation tools that can be used
|
||||
if author.server_permissions.kick_members:
|
||||
await self.bot.add_reaction(message, '\N{DOWNWARDS BLACK ARROW}')
|
||||
await self.bot.add_reaction(message, '\N{UPWARDS BLACK ARROW}')
|
||||
await self.bot.add_reaction(message, '\N{CROSS MARK}')
|
||||
elif author == entry.requester:
|
||||
await self.bot.add_reaction(message, '\N{CROSS MARK}')
|
||||
# Reset the fmt message
|
||||
fmt = None
|
||||
# Now we wait for the next reaction
|
||||
res = await self.bot.wait_for_reaction(possible_reactions, message=message, check=check, timeout=180)
|
||||
if res is None:
|
||||
break
|
||||
else:
|
||||
reaction, user = res
|
||||
# Now we can prepare for the next embed to be sent
|
||||
# If right is clicked
|
||||
if '\u27A1' in reaction.emoji:
|
||||
index += 1
|
||||
if index >= count:
|
||||
index = 0
|
||||
# If left is clicked
|
||||
elif '\u2B05' in reaction.emoji:
|
||||
index -= 1
|
||||
if index < 0:
|
||||
index = count - 1
|
||||
# If up is clicked
|
||||
elif '\u2b06' in reaction.emoji:
|
||||
# A second check just to make sure, as well as ensuring index is higher than 0
|
||||
if author.server_permissions.kick_members and index > 0:
|
||||
if entry != queue[index]:
|
||||
fmt = "`Error: Position of this entry has changed, cannot complete your action`"
|
||||
else:
|
||||
# Remove the current entry
|
||||
del queue[index]
|
||||
# Add it one position higher
|
||||
queue.insert(index - 1, entry)
|
||||
# Lets move the index to look at the new place of the entry
|
||||
index -= 1
|
||||
# If down is clicked
|
||||
elif '\u2b07' in reaction.emoji:
|
||||
# A second check just to make sure, as well as ensuring index is lower than last
|
||||
if author.server_permissions.kick_members and index < (count - 1):
|
||||
if entry != queue[index]:
|
||||
fmt = "`Error: Position of this entry has changed, cannot complete your action`"
|
||||
else:
|
||||
# Remove the current entry
|
||||
del queue[index]
|
||||
# Add it one position lower
|
||||
queue.insert(index + 1, entry)
|
||||
# Lets move the index to look at the new place of the entry
|
||||
index += 1
|
||||
# If x is clicked
|
||||
elif '\u274c' in reaction.emoji:
|
||||
# A second check just to make sure
|
||||
if author.server_permissions.kick_members or author == entry.requester:
|
||||
if entry != queue[index]:
|
||||
fmt = "`Error: Position of this entry has changed, cannot complete your action`"
|
||||
else:
|
||||
# Simply remove the entry in place
|
||||
del queue[index]
|
||||
# This is the only check we need to make, to ensure index is now not more than last
|
||||
new_count = count - 1
|
||||
if index >= new_count:
|
||||
index = new_count - 1
|
||||
try:
|
||||
await self.bot.remove_reaction(message, reaction.emoji, user)
|
||||
except discord.Forbidden:
|
||||
pass
|
||||
await self.bot.delete_message(message)
|
||||
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
async def progress(self, ctx):
|
||||
|
@ -281,6 +418,10 @@ class Music:
|
|||
await self.bot.say("You are not currently in the channel; please join before trying to request a song.")
|
||||
return
|
||||
|
||||
# Set the number of required skips to start
|
||||
num_members = len(my_channel.voice_members)
|
||||
state.required_skips = math.ceil((num_members + 1) / 3)
|
||||
|
||||
# Create the player, and check if this was successful
|
||||
# Here all we want is to get the information of the player
|
||||
song = re.sub('[<>\[\]]', '', song)
|
||||
|
@ -289,8 +430,8 @@ class Music:
|
|||
_entry, position = await state.songs.add_entry(song, ctx.message.author)
|
||||
except WrongEntryTypeError:
|
||||
# This means that a song was attempted to be searched, instead of a link provided
|
||||
info = await self.downloader.extract_info(self.bot.loop, song, download=False, process=True)
|
||||
try:
|
||||
info = await self.downloader.extract_info(self.bot.loop, song, download=False, process=True)
|
||||
song = info.get('entries', [])[0]['webpage_url']
|
||||
except IndexError:
|
||||
await self.bot.send_message(ctx.message.channel, "No results found for {}!".format(song))
|
||||
|
@ -310,6 +451,7 @@ class Music:
|
|||
fmt = "Sorry but I couldn't download that! Either you provided a playlist, a streamed link, or " \
|
||||
"a page that is not supported to download."
|
||||
await self.bot.send_message(ctx.message.channel, fmt)
|
||||
return
|
||||
except ExtractionError as e:
|
||||
# This gets the youtube_dl error, instead of our error raised
|
||||
error = str(e).split("\n\n")[1]
|
||||
|
@ -376,8 +518,9 @@ class Music:
|
|||
# Then erase the voice_state entirely, and disconnect from the channel
|
||||
try:
|
||||
state.audio_player.cancel()
|
||||
state.clear_audio_files()
|
||||
await self.remove_voice_client(ctx.message.server)
|
||||
del self.voice_states[server.id]
|
||||
await state.voice.disconnect()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -433,10 +576,9 @@ class Music:
|
|||
# Asyncio provides no non-private way to access the queue, so we have to use _queue
|
||||
queue = state.songs.entries
|
||||
if len(queue) == 0:
|
||||
fmt = "Nothing currently in the queue"
|
||||
await self.bot.say("Nothing currently in the queue")
|
||||
else:
|
||||
fmt = "\n\n".join(str(x) for x in queue)
|
||||
await self.bot.say("Current songs in the queue:```\n{}```".format(fmt))
|
||||
self.bot.loop.create_task(self.queue_embed_task(state, ctx.message.channel, ctx.message.author))
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
|
@ -498,8 +640,23 @@ class Music:
|
|||
if not state.is_playing():
|
||||
await self.bot.say('Not playing anything.')
|
||||
else:
|
||||
# Create the embed object we'll use
|
||||
embed = discord.Embed()
|
||||
# Fill in the simple things
|
||||
embed.add_field(name='Title', value=state.current.title, inline=False)
|
||||
embed.add_field(name='Requester', value=state.current.requester.display_name, inline=False)
|
||||
# Get the amount of current skips, and display how many have been skipped/how many required
|
||||
skip_count = len(state.skip_votes)
|
||||
await self.bot.say('Now playing {} [skips: {}/{}]'.format(state.current, skip_count, state.required_skips))
|
||||
embed.add_field(name='Skip Count', value='{}/{}'.format(skip_count, state.required_skips), inline=False)
|
||||
# Get the current progress and display this
|
||||
progress = state.current.progress
|
||||
length = state.current.length
|
||||
progress = divmod(round(progress, 0), 60)
|
||||
length = divmod(round(length, 0), 60)
|
||||
fmt = "{0[0]}m {0[1]}s/{1[0]}m {1[1]}s".format(progress, length)
|
||||
embed.add_field(name='Progress', value=fmt,inline=False)
|
||||
# And send the embed
|
||||
await self.bot.say(embed=embed)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
|
|
|
@ -7,8 +7,8 @@ import traceback
|
|||
import logging
|
||||
|
||||
from discord.ext import commands
|
||||
from .utils import config
|
||||
from .utils import checks
|
||||
|
||||
from . import utils
|
||||
|
||||
log = logging.getLogger()
|
||||
base_url = 'https://ptvappapi.picarto.tv'
|
||||
|
@ -24,7 +24,7 @@ async def online_users():
|
|||
# In place of requesting for /channel and checking if that is online currently, for each channel
|
||||
# This method is in place to just return all online_users
|
||||
url = '{}/online/all?key={}'.format(base_url, key)
|
||||
with aiohttp.ClientSession(headers={"User-Agent": config.user_agent}) as s:
|
||||
with aiohttp.ClientSession(headers={"User-Agent": utils.user_agent}) as s:
|
||||
async with s.get(url) as response:
|
||||
return await response.json()
|
||||
except:
|
||||
|
@ -43,7 +43,7 @@ def check_online(online_channels, channel):
|
|||
class Picarto:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.headers = {"User-Agent": config.user_agent}
|
||||
self.headers = {"User-Agent": utils.user_agent}
|
||||
self.session = aiohttp.ClientSession()
|
||||
|
||||
async def check_channels(self):
|
||||
|
@ -52,7 +52,7 @@ class Picarto:
|
|||
try:
|
||||
while not self.bot.is_closed:
|
||||
r_filter = {'notifications_on': 1}
|
||||
picarto = await config.get_content('picarto', r_filter)
|
||||
picarto = await utils.get_content('picarto', r_filter)
|
||||
# Get all online users before looping, so that only one request is needed
|
||||
online_users_list = await online_users()
|
||||
old_online_users = {data['member_id']: data for data in picarto if data['live']}
|
||||
|
@ -69,7 +69,7 @@ class Picarto:
|
|||
server = self.bot.get_server(server_id)
|
||||
if server is None:
|
||||
continue
|
||||
server_alerts = await config.get_content('server_alerts', {'server_id': server_id})
|
||||
server_alerts = await utils.get_content('server_alerts', {'server_id': server_id})
|
||||
try:
|
||||
channel_id = server_alerts[0]['channel_id']
|
||||
except (IndexError, TypeError):
|
||||
|
@ -82,7 +82,7 @@ class Picarto:
|
|||
|
||||
fmt = "{} has just gone live! View their stream at {}".format(member.display_name, url)
|
||||
await self.bot.send_message(channel, fmt)
|
||||
await config.update_content('picarto', {'live': 1}, {'member_id': m_id})
|
||||
await utils.update_content('picarto', {'live': 1}, {'member_id': m_id})
|
||||
for m_id, result in old_online_users.items():
|
||||
# Get their url and their user based on that url
|
||||
url = result['picarto_url']
|
||||
|
@ -94,7 +94,7 @@ class Picarto:
|
|||
server = self.bot.get_server(server_id)
|
||||
if server is None:
|
||||
continue
|
||||
server_alerts = await config.get_content('server_alerts', {'server_id': server_id})
|
||||
server_alerts = await utils.get_content('server_alerts', {'server_id': server_id})
|
||||
try:
|
||||
channel_id = server_alerts[0]['channel_id']
|
||||
except IndexError:
|
||||
|
@ -105,7 +105,7 @@ class Picarto:
|
|||
fmt = "{} has just gone offline! Catch them next time they stream at {}".format(
|
||||
member.display_name, url)
|
||||
await self.bot.send_message(channel, fmt)
|
||||
await config.update_content('picarto', {'live': 0}, {'member_id': m_id})
|
||||
await utils.update_content('picarto', {'live': 0}, {'member_id': m_id})
|
||||
await asyncio.sleep(30)
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
|
@ -113,7 +113,7 @@ class Picarto:
|
|||
log.error(fmt)
|
||||
|
||||
@commands.group(pass_context=True, invoke_without_command=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def picarto(self, ctx, member: discord.Member = None):
|
||||
"""This command can be used to view Picarto stats about a certain member
|
||||
|
||||
|
@ -122,7 +122,7 @@ class Picarto:
|
|||
# If member is not given, base information on the author
|
||||
member = member or ctx.message.author
|
||||
r_filter = {'member_id': member.id}
|
||||
picarto_entry = await config.get_content('picarto', r_filter)
|
||||
picarto_entry = await utils.get_content('picarto', r_filter)
|
||||
if picarto_entry is None:
|
||||
await self.bot.say("That user does not have a picarto url setup!")
|
||||
return
|
||||
|
@ -151,7 +151,7 @@ class Picarto:
|
|||
await self.bot.say("Picarto stats for {}: ```\n{}```".format(member.display_name, fmt))
|
||||
|
||||
@picarto.command(name='add', pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def add_picarto_url(self, ctx, url: str):
|
||||
"""Saves your user's picarto URL
|
||||
|
||||
|
@ -187,20 +187,20 @@ class Picarto:
|
|||
'notifications_on': 1,
|
||||
'live': 0,
|
||||
'member_id': ctx.message.author.id}
|
||||
if await config.add_content('picarto', entry, r_filter):
|
||||
if await utils.add_content('picarto', entry, r_filter):
|
||||
await self.bot.say(
|
||||
"I have just saved your Picarto URL {}, this server will now be notified when you go live".format(
|
||||
ctx.message.author.mention))
|
||||
else:
|
||||
await config.update_content('picarto', {'picarto_url': url}, r_filter)
|
||||
await utils.update_content('picarto', {'picarto_url': url}, r_filter)
|
||||
await self.bot.say("I have just updated your Picarto URL")
|
||||
|
||||
@picarto.command(name='remove', aliases=['delete'], pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def remove_picarto_url(self, ctx):
|
||||
"""Removes your picarto URL"""
|
||||
r_filter = {'member_id': ctx.message.author.id}
|
||||
if await config.remove_content('picarto', r_filter):
|
||||
if await utils.remove_content('picarto', r_filter):
|
||||
await self.bot.say("I am no longer saving your picarto URL {}".format(ctx.message.author.mention))
|
||||
else:
|
||||
await self.bot.say(
|
||||
|
@ -208,7 +208,7 @@ class Picarto:
|
|||
ctx.message.author.mention, ctx.prefix))
|
||||
|
||||
@picarto.group(pass_context=True, no_pm=True, invoke_without_command=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def notify(self, ctx):
|
||||
"""This can be used to turn picarto notifications on or off
|
||||
Call this command by itself, to add this server to the list of servers to be notified
|
||||
|
@ -216,7 +216,7 @@ class Picarto:
|
|||
EXAMPLE: !picarto notify
|
||||
RESULT: This server will now be notified of you going live"""
|
||||
r_filter = {'member_id': ctx.message.author.id}
|
||||
result = await config.get_content('picarto', r_filter)
|
||||
result = await utils.get_content('picarto', r_filter)
|
||||
# Check if this user is saved at all
|
||||
if result is None:
|
||||
await self.bot.say(
|
||||
|
@ -226,30 +226,30 @@ class Picarto:
|
|||
elif ctx.message.server.id in result[0]['servers']:
|
||||
await self.bot.say("I am already set to notify in this server...")
|
||||
else:
|
||||
await config.update_content('picarto', {'servers': r.row['servers'].append(ctx.message.server.id)},
|
||||
await utils.update_content('picarto', {'servers': r.row['servers'].append(ctx.message.server.id)},
|
||||
r_filter)
|
||||
|
||||
@notify.command(name='on', aliases=['start,yes'], pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def notify_on(self, ctx):
|
||||
"""Turns picarto notifications on
|
||||
|
||||
EXAMPLE: !picarto notify on
|
||||
RESULT: Notifications are sent when you go live"""
|
||||
r_filter = {'member_id': ctx.message.author.id}
|
||||
await config.update_content('picarto', {'notifications_on': 1}, r_filter)
|
||||
await utils.update_content('picarto', {'notifications_on': 1}, r_filter)
|
||||
await self.bot.say("I will notify if you go live {}, you'll get a bajillion followers I promise c:".format(
|
||||
ctx.message.author.mention))
|
||||
|
||||
@notify.command(name='off', aliases=['stop,no'], pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
@utils.custom_perms(send_messages=True)
|
||||
async def notify_off(self, ctx):
|
||||
"""Turns picarto notifications off
|
||||
|
||||
EXAMPLE: !picarto notify off
|
||||
RESULT: No more notifications sent when you go live"""
|
||||
r_filter = {'member_id': ctx.message.author.id}
|
||||
await config.update_content('picarto', {'notifications_on': 0}, r_filter)
|
||||
await utils.update_content('picarto', {'notifications_on': 0}, r_filter)
|
||||
await self.bot.say(
|
||||
"I will not notify if you go live anymore {}, "
|
||||
"are you going to stream some lewd stuff you don't want people to see?~".format(
|
||||
|
|
|
@ -75,7 +75,10 @@ class Raffle:
|
|||
# We don't have to wait for it however, so create a task for it
|
||||
r_filter = {'id': raffle_id}
|
||||
self.bot.loop.create_task(config.remove_content('raffles', r_filter))
|
||||
try:
|
||||
await self.bot.send_message(server, fmt)
|
||||
except discord.Forbidden:
|
||||
pass
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
@checks.custom_perms(send_messages=True)
|
||||
|
|
|
@ -46,8 +46,8 @@ class Twitch:
|
|||
# Loop through as long as the bot is connected
|
||||
try:
|
||||
while not self.bot.is_closed:
|
||||
twitch = await config.get_content('twitch', {'notifications_on': 1})
|
||||
# Online/offline is based on whether they are set to such, in the config file
|
||||
twitch = await utils.get_content('twitch', {'notifications_on': 1})
|
||||
# Online/offline is based on whether they are set to such, in the utils file
|
||||
# This means they were detected as online/offline before and we check for a change
|
||||
online_users = {data['member_id']: data for data in twitch if data['live']}
|
||||
offline_users = {data['member_id']: data for data in twitch if not data['live']}
|
||||
|
@ -62,7 +62,7 @@ class Twitch:
|
|||
server = self.bot.get_server(server_id)
|
||||
if server is None:
|
||||
continue
|
||||
server_alerts = await config.get_content('server_alerts', {'server_id': server_id})
|
||||
server_alerts = await utils.get_content('server_alerts', {'server_id': server_id})
|
||||
try:
|
||||
channel_id = server_alerts[0]['channel_id']
|
||||
except (IndexError, TypeError):
|
||||
|
@ -75,7 +75,7 @@ class Twitch:
|
|||
|
||||
fmt = "{} has just gone live! View their stream at {}".format(member.display_name, url)
|
||||
await self.bot.send_message(channel, fmt)
|
||||
await config.update_content('twitch', {'live': 1}, {'member_id': m_id})
|
||||
await utils.update_content('twitch', {'live': 1}, {'member_id': m_id})
|
||||
for m_id, result in online_users.items():
|
||||
# Get their url and their user based on that url
|
||||
url = result['twitch_url']
|
||||
|
@ -87,7 +87,7 @@ class Twitch:
|
|||
server = self.bot.get_server(server_id)
|
||||
if server is None:
|
||||
continue
|
||||
server_alerts = await config.get_content('server_alerts', {'server_id': server_id})
|
||||
server_alerts = await utils.get_content('server_alerts', {'server_id': server_id})
|
||||
channel_id = server_id
|
||||
if len(server_alerts) > 0:
|
||||
channel_id = server_alerts[0].get('channel_id')
|
||||
|
@ -97,7 +97,7 @@ class Twitch:
|
|||
fmt = "{} has just gone offline! Catch them next time they stream at {}".format(
|
||||
member.display_name, url)
|
||||
await self.bot.send_message(channel, fmt)
|
||||
await config.update_content('twitch', {'live': 0}, {'member_id': m_id})
|
||||
await utils.update_content('twitch', {'live': 0}, {'member_id': m_id})
|
||||
await asyncio.sleep(30)
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
|
|
|
@ -61,7 +61,7 @@ async def download_image(url):
|
|||
return None
|
||||
|
||||
# Then wrap it in a BytesIO object, to be used like an actual file
|
||||
image = io.BytesIO(await r.read())
|
||||
image = io.BytesIO(bts)
|
||||
return image
|
||||
|
||||
async def request(url, *, headers=None, payload=None, method='GET', attr='json'):
|
||||
|
|
|
@ -3,6 +3,7 @@ import json
|
|||
import os
|
||||
import traceback
|
||||
import time
|
||||
import discord
|
||||
|
||||
from hashlib import md5
|
||||
from .exceptions import ExtractionError
|
||||
|
@ -270,5 +271,16 @@ class URLPlaylistEntry(BasePlaylistEntry):
|
|||
else:
|
||||
# Move the temporary file to it's final location.
|
||||
os.rename(unhashed_fname, self.filename)
|
||||
|
||||
|
||||
def to_embed(self):
|
||||
"""Returns an embed that can be used to display information about this particular song"""
|
||||
# Create the embed object we'll use
|
||||
embed = discord.Embed()
|
||||
# Fill in the simple things
|
||||
embed.add_field(name='Title', value=self.title, inline=False)
|
||||
embed.add_field(name='Requester', value=self.requester.display_name, inline=False)
|
||||
# Get the current length of the song and display this
|
||||
length = divmod(round(self.length, 0), 60)
|
||||
fmt = "{0[0]}m {0[1]}s".format(length)
|
||||
embed.add_field(name='Duration', value=fmt,inline=False)
|
||||
# And return the embed we created
|
||||
return embed
|
||||
|
|
Loading…
Reference in a new issue