1
0
Fork 0
mirror of synced 2024-05-18 19:42:28 +12:00

Move tasks into their own methods, to try to gc better

This commit is contained in:
phxntxm 2018-09-22 11:17:11 -05:00
parent 259da83950
commit c7742a8023
5 changed files with 172 additions and 140 deletions

View file

@ -1,35 +1,45 @@
import discord import discord
import pendulum import pendulum
import asyncio import asyncio
import traceback
from pendulum.parsing.exceptions import ParserError from pendulum.parsing.exceptions import ParserError
from discord.ext import commands from discord.ext import commands
from . import utils from . import utils
tzmap = {
'us-central': pendulum.timezone('US/Central'),
'eu-central': pendulum.timezone('Europe/Paris'),
'hongkong': pendulum.timezone('Hongkong'),
}
def sort_birthdays(bds):
# First sort the birthdays based on the comparison of the actual date
bds = sorted(bds, key=lambda x: x['birthday'])
# We want to split this into birthdays after and before todays date
# We can then use this to sort based on "whose is closest"
later_bds = []
previous_bds = []
# Loop through each birthday
for bd in bds:
# If it is after or equal to today, insert into our later list
if bd['birthday'].date() >= pendulum.today().date():
later_bds.append(bd)
# Otherwise, insert into our previous list
else:
previous_bds.append(bd)
# At this point we have 2 lists, in order, one from all of dates before today, and one after
# So all we need to do is put them in order all of "laters" then all of "befores"
return later_bds + previous_bds
class Birthday: class Birthday:
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
self.bot.loop.create_task(self.birthday_task()) self.task = self.bot.loop.create_task(self.birthday_task())
def sort_birthdays(self, bds):
# First sort the birthdays based on the comparison of the actual date
bds = sorted(bds, key=lambda x: x['birthday'])
# We want to split this into birthdays after and before todays date
# We can then use this to sort based on "whose is closest"
later_bds = []
previous_bds = []
# Loop through each birthday
for bd in bds:
# If it is after or equal to today, insert into our later list
if bd['birthday'].date() >= pendulum.today().date():
later_bds.append(bd)
# Otherwise, insert into our previous list
else:
previous_bds.append(bd)
# At this point we have 2 lists, in order, one from all of dates before today, and one after
# So all we need to do is put them in order all of "laters" then all of "befores"
return later_bds + previous_bds
def get_birthdays_for_server(self, server, today=False): def get_birthdays_for_server(self, server, today=False):
bds = self.bot.db.load('birthdays') bds = self.bot.db.load('birthdays')
@ -46,6 +56,7 @@ class Birthday:
continue continue
day = pendulum.parse(bd['birthday']) day = pendulum.parse(bd['birthday'])
# tz = tzmap.get(server.region)
# Check if it's today, and we want to only get todays birthdays # Check if it's today, and we want to only get todays birthdays
if (today and day.date() == pendulum.today().date()) or not today: if (today and day.date() == pendulum.today().date()) or not today:
# If so, get the member and add them to the entry # If so, get the member and add them to the entry
@ -55,13 +66,19 @@ class Birthday:
'member': member 'member': member
}) })
return self.sort_birthdays(_entries) return sort_birthdays(_entries)
async def birthday_task(self): async def birthday_task(self):
while True: while True:
await self.notify_birthdays() try:
# Every 12 hours, this is not something that needs to happen often await self.notify_birthdays()
await asyncio.sleep(60 * 60 * 12) except Exception as error:
with open("error_log", 'a') as f:
traceback.print_tb(error.__traceback__, file=f)
print('{0.__class__.__name__}: {0}'.format(error), file=f)
finally:
# Every 12 hours, this is not something that needs to happen often
await asyncio.sleep(60 * 60 * 12)
async def notify_birthdays(self): async def notify_birthdays(self):
tfilter = {'birthdays_allowed': True} tfilter = {'birthdays_allowed': True}

View file

@ -2,20 +2,18 @@ import asyncio
import discord import discord
import re import re
import traceback import traceback
import logging
from discord.ext import commands from discord.ext import commands
from . import utils from . import utils
log = logging.getLogger()
BASE_URL = 'https://api.picarto.tv/v1' BASE_URL = 'https://api.picarto.tv/v1'
class Picarto: class Picarto:
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
self.bot.loop.create_task(self.check_channels()) self.task = self.bot.loop.create_task(self.picarto_task())
# noinspection PyAttributeOutsideInit # noinspection PyAttributeOutsideInit
async def get_online_users(self): async def get_online_users(self):
@ -69,64 +67,66 @@ class Picarto:
channel = re.search("(?<=picarto.tv/)(.*)", channel).group(1) channel = re.search("(?<=picarto.tv/)(.*)", channel).group(1)
return channel.lower() in [stream['name'].lower() for stream in self.online_channels] return channel.lower() in [stream['name'].lower() for stream in self.online_channels]
async def check_channels(self): async def picarto_task(self):
await self.bot.wait_until_ready()
# This is a loop that runs every 30 seconds, checking if anyone has gone online
try: try:
await self.bot.wait_until_ready()
while not self.bot.is_closed(): while not self.bot.is_closed():
await self.get_online_users() await self.check_channels()
picarto = await self.bot.db.actual_load('picarto', table_filter={'notifications_on': 1}) except Exception as error:
for data in picarto: with open("error_log", 'a') as f:
m_id = int(data['member_id']) traceback.print_tb(error.__traceback__, file=f)
url = data['picarto_url'] print('{0.__class__.__name__}: {0}'.format(error), file=f)
# Check if they are online finally:
online = self.channel_online(url) await asyncio.sleep(30)
# If they're currently online, but saved as not then we'll let servers know they are now online
if online and data['live'] == 0:
msg = "{member.display_name} has just gone live!"
self.bot.db.save('picarto', {'live': 1, 'member_id': str(m_id)})
# Otherwise our notification will say they've gone offline
elif not online and data['live'] == 1:
msg = "{member.display_name} has just gone offline!"
self.bot.db.save('picarto', {'live': 0, 'member_id': str(m_id)})
else:
continue
embed = await self.channel_embed(url) async def check_channels(self):
# Loop through each server that they are set to notify await self.get_online_users()
for s_id in data['servers']: picarto = await self.bot.db.actual_load('picarto', table_filter={'notifications_on': 1})
server = self.bot.get_guild(int(s_id)) for data in picarto:
# If we can't find it, ignore this one m_id = int(data['member_id'])
if server is None: url = data['picarto_url']
continue # Check if they are online
member = server.get_member(m_id) online = self.channel_online(url)
# If we can't find them in this server, also ignore # If they're currently online, but saved as not then we'll let servers know they are now online
if member is None: if online and data['live'] == 0:
continue msg = "{member.display_name} has just gone live!"
self.bot.db.save('picarto', {'live': 1, 'member_id': str(m_id)})
# Otherwise our notification will say they've gone offline
elif not online and data['live'] == 1:
msg = "{member.display_name} has just gone offline!"
self.bot.db.save('picarto', {'live': 0, 'member_id': str(m_id)})
else:
continue
# Get the notifications settings, get the picarto setting embed = await self.channel_embed(url)
notifications = self.bot.db.load('server_settings', key=s_id, pluck='notifications') or {} # Loop through each server that they are set to notify
# Set our default to either the one set, or the default channel of the server for s_id in data['servers']:
default_channel_id = notifications.get('default') server = self.bot.get_guild(int(s_id))
# If it is has been overriden by picarto notifications setting, use this # If we can't find it, ignore this one
channel_id = notifications.get('picarto') or default_channel_id if server is None:
# Now get the channel continue
if channel_id: member = server.get_member(m_id)
channel = server.get_channel(int(channel_id)) # If we can't find them in this server, also ignore
else: if member is None:
continue continue
# Then just send our message # Get the notifications settings, get the picarto setting
try: notifications = self.bot.db.load('server_settings', key=s_id, pluck='notifications') or {}
await channel.send(msg.format(member=member), embed=embed) # Set our default to either the one set, or the default channel of the server
except (discord.Forbidden, discord.HTTPException, AttributeError): default_channel_id = notifications.get('default')
pass # If it is has been overriden by picarto notifications setting, use this
channel_id = notifications.get('picarto') or default_channel_id
# Now get the channel
if channel_id:
channel = server.get_channel(int(channel_id))
else:
continue
await asyncio.sleep(30) # Then just send our message
except Exception as e: try:
tb = traceback.format_exc() await channel.send(msg.format(member=member), embed=embed)
fmt = "{1}\n{0.__class__.__name__}: {0}".format(tb, e) except (discord.Forbidden, discord.HTTPException, AttributeError):
log.error(fmt) pass
@commands.group(invoke_without_command=True) @commands.group(invoke_without_command=True)
@utils.custom_perms(send_messages=True) @utils.custom_perms(send_messages=True)

View file

@ -23,7 +23,8 @@ class Raffle:
with open("error_log", 'a') as f: with open("error_log", 'a') as f:
traceback.print_tb(error.__traceback__, file=f) traceback.print_tb(error.__traceback__, file=f)
print('{0.__class__.__name__}: {0}'.format(error), file=f) print('{0.__class__.__name__}: {0}'.format(error), file=f)
await asyncio.sleep(60) finally:
await asyncio.sleep(60)
async def check_raffles(self): async def check_raffles(self):
# This is used to periodically check the current raffles, and see if they have ended yet # This is used to periodically check the current raffles, and see if they have ended yet

View file

@ -1,5 +1,6 @@
import asyncio import asyncio
import aiohttp import aiohttp
import traceback
from discord.ext import commands from discord.ext import commands
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
@ -20,9 +21,21 @@ class Spotify:
urlsafe_b64encode(self._authorization.encode()).decode() urlsafe_b64encode(self._authorization.encode()).decode()
) )
} }
self.bot.loop.create_task(self.api_token_task()) self.task = self.bot.loop.create_task(self.api_token_task())
async def api_token_task(self): async def api_token_task(self):
while True:
try:
delay = await self.get_api_token()
except Exception as error:
with open("error_log", 'a') as f:
traceback.print_tb(error.__traceback__, file=f)
print('{0.__class__.__name__}: {0}'.format(error), file=f)
delay = 2400
finally:
await asyncio.sleep(delay)
async def get_api_token(self):
url = "https://accounts.spotify.com/api/token" url = "https://accounts.spotify.com/api/token"
opts = {"grant_type": "client_credentials"} opts = {"grant_type": "client_credentials"}
while True: while True:
@ -30,6 +43,7 @@ class Spotify:
response = await session.post(url, data=opts) response = await session.post(url, data=opts)
data = await response.json() data = await response.json()
self._token = data.get("access_token") self._token = data.get("access_token")
return data.get("expires_in")
await asyncio.sleep(data.get("expires_in", 2400)) await asyncio.sleep(data.get("expires_in", 2400))

View file

@ -2,11 +2,9 @@ from discord.ext import commands
from . import utils from . import utils
import aiohttp
import asyncio import asyncio
import discord import discord
import re import re
import rethinkdb as r
import traceback import traceback
import logging import logging
@ -23,6 +21,8 @@ class Twitch:
self.key = utils.twitch_key self.key = utils.twitch_key
self.params = {'client_id': self.key} self.params = {'client_id': self.key}
self.task = bot.loop.create_task(self.check_channels())
def _form_embed(self, data): def _form_embed(self, data):
if not data: if not data:
return None return None
@ -82,63 +82,65 @@ class Twitch:
data = await utils.request(url, payload=self.params) data = await utils.request(url, payload=self.params)
return self._form_embed(data) return self._form_embed(data)
async def check_channels(self): async def twitch_task(self):
await self.bot.wait_until_ready() await self.bot.wait_until_ready()
# This is a loop that runs every 30 seconds, checking if anyone has gone online while not self.bot.is_closed():
try: try:
while not self.bot.is_closed(): await self.check_channels()
twitch = await self.bot.db.actual_load('twitch', table_filter={'notifications_on': 1}) except Exception as error:
for data in twitch: with open("error_log", 'a') as f:
m_id = int(data['member_id']) traceback.print_tb(error.__traceback__, file=f)
url = data['twitch_url'] print('{0.__class__.__name__}: {0}'.format(error), file=f)
# Check if they are online by trying to get an displayed embed for this user finally:
embed = await self.online_embed(url)
# If they're currently online, but saved as not then we'll let servers know they are now online
if embed and data['live'] == 0:
msg = "{member.display_name} has just gone live!"
self.bot.db.save('twitch', {'live': 1, 'member_id': str(m_id)})
# Otherwise our notification will say they've gone offline
elif not embed and data['live'] == 1:
msg = "{member.display_name} has just gone offline!"
embed = await self.offline_embed(url)
self.bot.db.save('twitch', {'live': 0, 'member_id': str(m_id)})
else:
continue
# Loop through each server that they are set to notify
for s_id in data['servers']:
server = self.bot.get_guild(int(s_id))
# If we can't find it, ignore this one
if server is None:
continue
member = server.get_member(m_id)
# If we can't find them in this server, also ignore
if member is None:
continue
# Get the notifications settings, get the twitch setting
notifications = self.bot.db.load('server_settings', key=s_id, pluck='notifications') or {}
# Set our default to either the one set, or the default channel of the server
default_channel_id = notifications.get('default')
# If it is has been overriden by twitch notifications setting, use this
channel_id = notifications.get('twitch') or default_channel_id
# Now get the channel
if channel_id:
channel = server.get_channel(int(channel_id))
else:
continue
# Then just send our message
try:
await channel.send(msg.format(member=member), embed=embed)
except (discord.Forbidden, discord.HTTPException, AttributeError):
pass
await asyncio.sleep(30) await asyncio.sleep(30)
except Exception as e:
tb = traceback.format_exc() async def check_channels(self):
fmt = "{1}\n{0.__class__.__name__}: {0}".format(tb, e) twitch = await self.bot.db.actual_load('twitch', table_filter={'notifications_on': 1})
log.error(fmt) for data in twitch:
m_id = int(data['member_id'])
url = data['twitch_url']
# Check if they are online by trying to get an displayed embed for this user
embed = await self.online_embed(url)
# If they're currently online, but saved as not then we'll let servers know they are now online
if embed and data['live'] == 0:
msg = "{member.display_name} has just gone live!"
self.bot.db.save('twitch', {'live': 1, 'member_id': str(m_id)})
# Otherwise our notification will say they've gone offline
elif not embed and data['live'] == 1:
msg = "{member.display_name} has just gone offline!"
embed = await self.offline_embed(url)
self.bot.db.save('twitch', {'live': 0, 'member_id': str(m_id)})
else:
continue
# Loop through each server that they are set to notify
for s_id in data['servers']:
server = self.bot.get_guild(int(s_id))
# If we can't find it, ignore this one
if server is None:
continue
member = server.get_member(m_id)
# If we can't find them in this server, also ignore
if member is None:
continue
# Get the notifications settings, get the twitch setting
notifications = self.bot.db.load('server_settings', key=s_id, pluck='notifications') or {}
# Set our default to either the one set, or the default channel of the server
default_channel_id = notifications.get('default')
# If it is has been overriden by twitch notifications setting, use this
channel_id = notifications.get('twitch') or default_channel_id
# Now get the channel
if channel_id:
channel = server.get_channel(int(channel_id))
else:
continue
# Then just send our message
try:
await channel.send(msg.format(member=member), embed=embed)
except (discord.Forbidden, discord.HTTPException, AttributeError):
pass
@commands.group(invoke_without_command=True) @commands.group(invoke_without_command=True)
@commands.guild_only() @commands.guild_only()
@ -329,6 +331,4 @@ class Twitch:
def setup(bot): def setup(bot):
t = Twitch(bot)
bot.loop.create_task(t.check_channels())
bot.add_cog(Twitch(bot)) bot.add_cog(Twitch(bot))