Merge branch 'master' into werewolf-develop

pull/147/head
bobloy 4 years ago
commit 31c2e77be6

@ -0,0 +1,26 @@
---
name: Bug report
about: Create an issue to report a bug
title: ''
labels: bug
assignees: bobloy
---
**Describe the bug**
<!--A clear and concise description of what the bug is.-->
**To Reproduce**
<!--Steps to reproduce the behavior:-->
1. Load cog '...'
2. Run command '....'
3. See error
**Expected behavior**
<!--A clear and concise description of what you expected to happen.-->
**Screenshots or Error Messages**
<!--If applicable, add screenshots to help explain your problem.-->
**Additional context**
<!--Add any other context about the problem here.-->

@ -0,0 +1,14 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[Feature Request]"
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
<!--A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]-->
**Describe the solution you'd like**
<!--A clear and concise description of what you want to happen. Include which cog or cogs this would interact with-->

@ -0,0 +1,26 @@
---
name: New AudioTrivia List
about: Submit a new AudioTrivia list to be added
title: "[AudioTrivia Submission]"
labels: 'cog: audiotrivia'
assignees: bobloy
---
**What is this trivia list?**
<!--What's in the list? What kind of category is?-->
**Number of Questions**
<!--Rough estimate at the number of question in this list-->
**Original Content?**
<!--Did you come up with this list yourself or did you get it from some else's work?-->
<!--If no, be sure to include the source-->
- [ ] Yes
- [ ] No
**Did I test the list?**
<!--Did you already try out the list and find no bugs?-->
- [ ] Yes
- [ ] No

@ -0,0 +1,62 @@
'cog: announcedaily':
- announcedaily/*
'cog: audiotrivia':
- audiotrivia/*
'cog: ccrole':
- ccrole/*
'cog: chatter':
- chatter/*
'cog: conquest':
- conquest/*
'cog: dad':
- dad/*
'cog: exclusiverole':
- exclusiverole/*
'cog: fifo':
- fifo/*
'cog: firstmessage':
- firstmessage/*
'cog: flag':
- flag/*
'cog: forcemention':
- forcemention/*
'cog: hangman':
- hangman
'cog: infochannel':
- infochannel/*
'cog: isitdown':
- isitdown/*
'cog: launchlib':
- launchlib/*
'cog: leaver':
- leaver/*
'cog: lovecalculator':
- lovecalculator/*
'cog: lseen':
- lseen/*
'cog: nudity':
- nudity/*
'cog: planttycoon':
- planttycoon/*
'cog: qrinvite':
- qrinvite/*
'cog: reactrestrict':
- reactrestrict/*
'cog: recyclingplant':
- recyclingplant/*
'cog: rpsls':
- rpsls/*
'cog: sayurl':
- sayurl/*
'cog: scp':
- scp/*
'cog: stealemoji':
- stealemoji/*
'cog: timerole':
- timerole/*
'cog: tts':
- tts/*
'cog: unicode':
- unicode/*
'cog: werewolf':
- werewolf

@ -0,0 +1,20 @@
# GitHub Action that uses Black to reformat the Python code in an incoming pull request.
# If all Python code in the pull request is compliant with Black then this Action does nothing.
# Othewrwise, Black is run and its changes are committed back to the incoming pull request.
# https://github.com/cclauss/autoblack
name: black
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install Black
run: pip install --upgrade --no-cache-dir black
- name: Run black --check .
run: black --check --diff -l 99 .

@ -0,0 +1,19 @@
# This workflow will triage pull requests and apply a label based on the
# paths that are modified in the pull request.
#
# To use this workflow, you will need to set up a .github/labeler.yml
# file with configuration. For more information, see:
# https://github.com/actions/labeler
name: Labeler
on: [pull_request]
jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v2
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

@ -1,8 +1,13 @@
"""Module to manage audio trivia sessions.""" """Module to manage audio trivia sessions."""
import asyncio import asyncio
import logging
import lavalink import lavalink
from lavalink.enums import LoadType
from redbot.cogs.trivia import TriviaSession from redbot.cogs.trivia import TriviaSession
from redbot.core.utils.chat_formatting import bold
log = logging.getLogger("red.fox_v3.audiotrivia.audiosession")
class AudioSession(TriviaSession): class AudioSession(TriviaSession):
@ -23,9 +28,9 @@ class AudioSession(TriviaSession):
async def run(self): async def run(self):
"""Run the audio trivia session. """Run the audio trivia session.
In order for the trivia session to be stopped correctly, this should In order for the trivia session to be stopped correctly, this should
only be called internally by `TriviaSession.start`. only be called internally by `TriviaSession.start`.
""" """
await self._send_startup_msg() await self._send_startup_msg()
max_score = self.settings["max_score"] max_score = self.settings["max_score"]
delay = self.settings["delay"] delay = self.settings["delay"]
@ -36,8 +41,9 @@ class AudioSession(TriviaSession):
self.count += 1 self.count += 1
await self.player.stop() await self.player.stop()
msg = "**Question number {}!**\n\nName this audio!".format(self.count) msg = bold(f"Question number {self.count}!") + "\n\nName this audio!"
await self.ctx.send(msg) await self.ctx.maybe_send_embed(msg)
log.debug(f"Audio question: {question}")
# print("Audio question: {}".format(question)) # print("Audio question: {}".format(question))
# await self.ctx.invoke(self.audio.play(ctx=self.ctx, query=question)) # await self.ctx.invoke(self.audio.play(ctx=self.ctx, query=question))
@ -45,18 +51,28 @@ class AudioSession(TriviaSession):
# await self.ctx.invoke(self.player.play, query=question) # await self.ctx.invoke(self.player.play, query=question)
query = question.strip("<>") query = question.strip("<>")
tracks = await self.player.get_tracks(query) load_result = await self.player.load_tracks(query)
seconds = tracks[0].length / 1000 log.debug(f"{load_result.load_type=}")
if load_result.has_error or load_result.load_type != LoadType.TRACK_LOADED:
await self.ctx.maybe_send_embed(f"Track has error, skipping. See logs for details")
log.info(f"Track has error: {load_result.exception_message}")
continue # Skip tracks with error
tracks = load_result.tracks
track = tracks[0]
seconds = track.length / 1000
if self.settings["repeat"] and seconds < delay: if self.settings["repeat"] and seconds < delay:
# Append it until it's longer than the delay
tot_length = seconds + 0 tot_length = seconds + 0
while tot_length < delay: while tot_length < delay:
self.player.add(self.ctx.author, tracks[0]) self.player.add(self.ctx.author, track)
tot_length += seconds tot_length += seconds
else: else:
self.player.add(self.ctx.author, tracks[0]) self.player.add(self.ctx.author, track)
if not self.player.current: if not self.player.current:
log.debug("Pressing play")
await self.player.play() await self.player.play()
continue_ = await self.wait_for_answer(answers, delay, timeout) continue_ = await self.wait_for_answer(answers, delay, timeout)

@ -1,4 +1,5 @@
import datetime import datetime
import logging
import pathlib import pathlib
from typing import List from typing import List
@ -15,7 +16,7 @@ from redbot.core.utils.chat_formatting import box
from .audiosession import AudioSession from .audiosession import AudioSession
# from redbot.cogs.audio.utils import userlimit log = logging.getLogger("red.fox_v3.audiotrivia")
class AudioTrivia(Trivia): class AudioTrivia(Trivia):
@ -83,24 +84,24 @@ class AudioTrivia(Trivia):
self.audio: Audio = self.bot.get_cog("Audio") self.audio: Audio = self.bot.get_cog("Audio")
if self.audio is None: if self.audio is None:
await ctx.send("Audio is not loaded. Load it and try again") await ctx.maybe_send_embed("Audio is not loaded. Load it and try again")
return return
categories = [c.lower() for c in categories] categories = [c.lower() for c in categories]
session = self._get_trivia_session(ctx.channel) session = self._get_trivia_session(ctx.channel)
if session is not None: if session is not None:
await ctx.send("There is already an ongoing trivia session in this channel.") await ctx.maybe_send_embed("There is already an ongoing trivia session in this channel.")
return return
status = await self.audio.config.status() status = await self.audio.config.status()
notify = await self.audio.config.guild(ctx.guild).notify() notify = await self.audio.config.guild(ctx.guild).notify()
if status: if status:
await ctx.send( await ctx.maybe_send_embed(
f"It is recommended to disable audio status with `{ctx.prefix}audioset status`" f"It is recommended to disable audio status with `{ctx.prefix}audioset status`"
) )
if notify: if notify:
await ctx.send( await ctx.maybe_send_embed(
f"It is recommended to disable audio notify with `{ctx.prefix}audioset notify`" f"It is recommended to disable audio notify with `{ctx.prefix}audioset notify`"
) )
@ -109,12 +110,12 @@ class AudioTrivia(Trivia):
if not ctx.author.voice.channel.permissions_for( if not ctx.author.voice.channel.permissions_for(
ctx.me ctx.me
).connect or self.audio.is_vc_full(ctx.author.voice.channel): ).connect or self.audio.is_vc_full(ctx.author.voice.channel):
return await ctx.send("I don't have permission to connect to your channel.") return await ctx.maybe_send_embed("I don't have permission to connect to your channel.")
await lavalink.connect(ctx.author.voice.channel) await lavalink.connect(ctx.author.voice.channel)
lavaplayer = lavalink.get_player(ctx.guild.id) lavaplayer = lavalink.get_player(ctx.guild.id)
lavaplayer.store("connect", datetime.datetime.utcnow()) lavaplayer.store("connect", datetime.datetime.utcnow())
except AttributeError: except AttributeError:
return await ctx.send("Connect to a voice channel first.") return await ctx.maybe_send_embed("Connect to a voice channel first.")
lavaplayer = lavalink.get_player(ctx.guild.id) lavaplayer = lavalink.get_player(ctx.guild.id)
lavaplayer.store("channel", ctx.channel.id) # What's this for? I dunno lavaplayer.store("channel", ctx.channel.id) # What's this for? I dunno
@ -122,7 +123,7 @@ class AudioTrivia(Trivia):
await self.audio.set_player_settings(ctx) await self.audio.set_player_settings(ctx)
if not ctx.author.voice or ctx.author.voice.channel != lavaplayer.channel: if not ctx.author.voice or ctx.author.voice.channel != lavaplayer.channel:
return await ctx.send( return await ctx.maybe_send_embed(
"You must be in the voice channel to use the audiotrivia command." "You must be in the voice channel to use the audiotrivia command."
) )
@ -134,13 +135,13 @@ class AudioTrivia(Trivia):
try: try:
dict_ = self.get_audio_list(category) dict_ = self.get_audio_list(category)
except FileNotFoundError: except FileNotFoundError:
await ctx.send( await ctx.maybe_send_embed(
"Invalid category `{0}`. See `{1}audiotrivia list`" "Invalid category `{0}`. See `{1}audiotrivia list`"
" for a list of trivia categories." " for a list of trivia categories."
"".format(category, ctx.prefix) "".format(category, ctx.prefix)
) )
except InvalidListError: except InvalidListError:
await ctx.send( await ctx.maybe_send_embed(
"There was an error parsing the trivia list for" "There was an error parsing the trivia list for"
" the `{}` category. It may be formatted" " the `{}` category. It may be formatted"
" incorrectly.".format(category) " incorrectly.".format(category)
@ -151,7 +152,7 @@ class AudioTrivia(Trivia):
continue continue
return return
if not trivia_dict: if not trivia_dict:
await ctx.send( await ctx.maybe_send_embed(
"The trivia list was parsed successfully, however it appears to be empty!" "The trivia list was parsed successfully, however it appears to be empty!"
) )
return return
@ -166,7 +167,10 @@ class AudioTrivia(Trivia):
# Delay in audiosettings overwrites delay in settings # Delay in audiosettings overwrites delay in settings
combined_settings = {**settings, **audiosettings} combined_settings = {**settings, **audiosettings}
session = AudioSession.start( session = AudioSession.start(
ctx=ctx, question_list=trivia_dict, settings=combined_settings, player=lavaplayer, ctx=ctx,
question_list=trivia_dict,
settings=combined_settings,
player=lavaplayer,
) )
self.trivia_sessions.append(session) self.trivia_sessions.append(session)
LOG.debug("New audio trivia session; #%s in %d", ctx.channel, ctx.guild.id) LOG.debug("New audio trivia session; #%s in %d", ctx.channel, ctx.guild.id)

@ -1,13 +1,14 @@
AUTHOR: Plab AUTHOR: Plab
https://www.youtube.com/watch?v=--bWm9hhoZo: NEEDS: New links for all songs.
https://www.youtube.com/watch?v=f9O2Rjn1azc:
- Transistor - Transistor
https://www.youtube.com/watch?v=-4nCbgayZNE: https://www.youtube.com/watch?v=PgUhYFkVdSY:
- Dark Cloud 2 - Dark Cloud 2
- Dark Cloud II - Dark Cloud II
https://www.youtube.com/watch?v=-64NlME4lJU: https://www.youtube.com/watch?v=1T1RZttyMwU:
- Mega Man 7 - Mega Man 7
- Mega Man VII - Mega Man VII
https://www.youtube.com/watch?v=-AesqnudNuw: https://www.youtube.com/watch?v=AdDbbzuq1vY:
- Mega Man 9 - Mega Man 9
- Mega Man IX - Mega Man IX
https://www.youtube.com/watch?v=-BmGDtP2t7M: https://www.youtube.com/watch?v=-BmGDtP2t7M:

File diff suppressed because it is too large Load Diff

@ -85,6 +85,8 @@ class Dad(Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_message_without_command(self, message: discord.Message): async def on_message_without_command(self, message: discord.Message):
if message.author.bot:
return
guild: discord.Guild = getattr(message, "guild", None) guild: discord.Guild = getattr(message, "guild", None)
if guild is None: if guild is None:
return return

@ -1,9 +1,10 @@
from datetime import datetime from datetime import datetime, tzinfo
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from apscheduler.triggers.cron import CronTrigger from apscheduler.triggers.cron import CronTrigger
from dateutil import parser from dateutil import parser
from discord.ext.commands import BadArgument, Converter from discord.ext.commands import BadArgument, Converter
from pytz import timezone
from fifo.timezones import assemble_timezones from fifo.timezones import assemble_timezones
@ -12,6 +13,18 @@ if TYPE_CHECKING:
CronConverter = str CronConverter = str
else: else:
class TimezoneConverter(Converter):
async def convert(self, ctx, argument) -> tzinfo:
tzinfos = assemble_timezones()
if argument.upper() in tzinfos:
return tzinfos[argument.upper()]
timez = timezone(argument)
if timez is not None:
return timez
raise BadArgument()
class DatetimeConverter(Converter): class DatetimeConverter(Converter):
async def convert(self, ctx, argument) -> datetime: async def convert(self, ctx, argument) -> datetime:
dt = parser.parse(argument, fuzzy=True, tzinfos=assemble_timezones()) dt = parser.parse(argument, fuzzy=True, tzinfos=assemble_timezones())

@ -1,5 +1,5 @@
import logging import logging
from datetime import datetime, timedelta from datetime import datetime, timedelta, tzinfo
from typing import Optional, Union from typing import Optional, Union
import discord import discord
@ -10,8 +10,9 @@ from apscheduler.schedulers.base import STATE_PAUSED, STATE_RUNNING
from redbot.core import Config, checks, commands from redbot.core import Config, checks, commands
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.commands import TimedeltaConverter from redbot.core.commands import TimedeltaConverter
from redbot.core.utils.chat_formatting import pagify
from .datetime_cron_converters import CronConverter, DatetimeConverter from .datetime_cron_converters import CronConverter, DatetimeConverter, TimezoneConverter
from .task import Task from .task import Task
schedule_log = logging.getLogger("red.fox_v3.fifo.scheduler") schedule_log = logging.getLogger("red.fox_v3.fifo.scheduler")
@ -57,6 +58,8 @@ class FIFO(commands.Cog):
self.scheduler = None self.scheduler = None
self.jobstore = None self.jobstore = None
self.tz_cog = None
async def red_delete_data_for_user(self, **kwargs): async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete""" """Nothing to delete"""
return return
@ -131,6 +134,24 @@ class FIFO(commands.Cog):
async def _remove_job(self, task: Task): async def _remove_job(self, task: Task):
return self.scheduler.remove_job(job_id=_assemble_job_id(task.name, task.guild_id)) return self.scheduler.remove_job(job_id=_assemble_job_id(task.name, task.guild_id))
async def _get_tz(self, user: Union[discord.User, discord.Member]) -> Union[None, tzinfo]:
if self.tz_cog is None:
self.tz_cog = self.bot.get_cog("Timezone")
if self.tz_cog is None:
self.tz_cog = False # only try once to get the timezone cog
if not self.tz_cog:
return None
try:
usertime = await self.tz_cog.config.user(user).usertime()
except AttributeError:
return None
if usertime:
return await TimezoneConverter().convert(None, usertime)
else:
return None
@checks.is_owner() @checks.is_owner()
@commands.guild_only() @commands.guild_only()
@commands.command() @commands.command()
@ -139,7 +160,7 @@ class FIFO(commands.Cog):
self.scheduler.remove_all_jobs() self.scheduler.remove_all_jobs()
await self.config.guild(ctx.guild).tasks.clear() await self.config.guild(ctx.guild).tasks.clear()
await self.config.jobs.clear() await self.config.jobs.clear()
await self.config.jobs_index.clear() # await self.config.jobs_index.clear()
await ctx.tick() await ctx.tick()
@checks.is_owner() # Will be reduced when I figure out permissions later @checks.is_owner() # Will be reduced when I figure out permissions later
@ -306,7 +327,11 @@ class FIFO(commands.Cog):
out += f"{task_name}: {task_data}\n" out += f"{task_name}: {task_data}\n"
if out: if out:
await ctx.maybe_send_embed(out) if len(out) > 2000:
for page in pagify(out):
await ctx.maybe_send_embed(page)
else:
await ctx.maybe_send_embed(out)
else: else:
await ctx.maybe_send_embed("No tasks to list") await ctx.maybe_send_embed("No tasks to list")
@ -406,7 +431,7 @@ class FIFO(commands.Cog):
job: Job = await self._process_task(task) job: Job = await self._process_task(task)
delta_from_now: timedelta = job.next_run_time - datetime.now(job.next_run_time.tzinfo) delta_from_now: timedelta = job.next_run_time - datetime.now(job.next_run_time.tzinfo)
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
f"Task `{task_name}` added interval of {interval_str} to its scheduled runtimes\n" f"Task `{task_name}` added interval of {interval_str} to its scheduled runtimes\n\n"
f"Next run time: {job.next_run_time} ({delta_from_now.total_seconds()} seconds)" f"Next run time: {job.next_run_time} ({delta_from_now.total_seconds()} seconds)"
) )
@ -427,7 +452,9 @@ class FIFO(commands.Cog):
) )
return return
result = await task.add_trigger("date", datetime_str) maybe_tz = await self._get_tz(ctx.author)
result = await task.add_trigger("date", datetime_str, maybe_tz)
if not result: if not result:
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
"Failed to add a date trigger to this task, see console for logs" "Failed to add a date trigger to this task, see console for logs"
@ -444,7 +471,12 @@ class FIFO(commands.Cog):
@fifo_trigger.command(name="cron") @fifo_trigger.command(name="cron")
async def fifo_trigger_cron( async def fifo_trigger_cron(
self, ctx: commands.Context, task_name: str, *, cron_str: CronConverter self,
ctx: commands.Context,
task_name: str,
optional_tz: Optional[TimezoneConverter] = None,
*,
cron_str: CronConverter,
): ):
""" """
Add a cron "time of day" trigger to the specified task Add a cron "time of day" trigger to the specified task
@ -460,7 +492,10 @@ class FIFO(commands.Cog):
) )
return return
result = await task.add_trigger("cron", cron_str) if optional_tz is None:
optional_tz = await self._get_tz(ctx.author) # might still be None
result = await task.add_trigger("cron", cron_str, optional_tz)
if not result: if not result:
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
"Failed to add a cron trigger to this task, see console for logs" "Failed to add a cron trigger to this task, see console for logs"

@ -3,14 +3,14 @@
"Bobloy" "Bobloy"
], ],
"min_bot_version": "3.4.0", "min_bot_version": "3.4.0",
"description": "[ALPHA] Schedule commands to be run at certain times or intervals", "description": "[BETA] Schedule commands to be run at certain times or intervals",
"hidden": false, "hidden": false,
"install_msg": "Thank you for installing FIFO.\nGet started with `[p]load fifo`, then `[p]help FIFO`", "install_msg": "Thank you for installing FIFO.\nGet started with `[p]load fifo`, then `[p]help FIFO`",
"short": "[ALPHA] Schedule commands to be run at certain times or intervals", "short": "[BETA] Schedule commands to be run at certain times or intervals",
"end_user_data_statement": "This cog does not store any End User Data", "end_user_data_statement": "This cog does not store any End User Data",
"requirements": [ "requirements": [
"apscheduler", "apscheduler",
"python-dateutil" "pytz"
], ],
"tags": [ "tags": [
"bobloy", "bobloy",
@ -24,6 +24,7 @@
"date", "date",
"datetime", "datetime",
"time", "time",
"calendar" "calendar",
"timezone"
] ]
} }

@ -9,6 +9,7 @@ from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.date import DateTrigger from apscheduler.triggers.date import DateTrigger
from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.interval import IntervalTrigger
from discord.utils import time_snowflake from discord.utils import time_snowflake
from pytz import timezone
from redbot.core import Config, commands from redbot.core import Config, commands
from redbot.core.bot import Red from redbot.core.bot import Red
@ -25,10 +26,10 @@ def get_trigger(data):
return IntervalTrigger(days=parsed_time.days, seconds=parsed_time.seconds) return IntervalTrigger(days=parsed_time.days, seconds=parsed_time.seconds)
if data["type"] == "date": if data["type"] == "date":
return DateTrigger(data["time_data"]) return DateTrigger(data["time_data"], timezone=data["tzinfo"])
if data["type"] == "cron": if data["type"] == "cron":
return CronTrigger.from_crontab(data["time_data"]) return CronTrigger.from_crontab(data["time_data"], timezone=data["tzinfo"])
return False return False
@ -70,6 +71,7 @@ class Task:
default_trigger = { default_trigger = {
"type": "", "type": "",
"time_data": None, # Used for Interval and Date Triggers "time_data": None, # Used for Interval and Date Triggers
"tzinfo": None,
} }
def __init__( def __init__(
@ -99,7 +101,13 @@ class Task:
if t["type"] == "date": # Convert into datetime if t["type"] == "date": # Convert into datetime
dt: datetime = t["time_data"] dt: datetime = t["time_data"]
triggers.append({"type": t["type"], "time_data": dt.isoformat()}) triggers.append(
{
"type": t["type"],
"time_data": dt.isoformat(),
"tzinfo": getattr(t["tzinfo"], "zone", None),
}
)
# triggers.append( # triggers.append(
# { # {
# "type": t["type"], # "type": t["type"],
@ -117,9 +125,18 @@ class Task:
continue continue
if t["type"] == "cron": if t["type"] == "cron":
triggers.append(t) # already a string, nothing to do if t["tzinfo"] is None:
triggers.append(t) # already a string, nothing to do
else:
triggers.append(
{
"type": t["type"],
"time_data": t["time_data"],
"tzinfo": getattr(t["tzinfo"], "zone", None),
}
)
continue continue
raise NotImplemented raise NotImplemented
return triggers return triggers
@ -128,18 +145,27 @@ class Task:
if not self.data or not self.data.get("triggers", None): if not self.data or not self.data.get("triggers", None):
return return
for n, t in enumerate(self.data["triggers"]): for t in self.data["triggers"]:
# Backwards compatibility
if "tzinfo" not in t:
t["tzinfo"] = None
# First decode timezone if there is one
if t["tzinfo"] is not None:
t["tzinfo"] = timezone(t["tzinfo"])
if t["type"] == "interval": # Convert into timedelta if t["type"] == "interval": # Convert into timedelta
self.data["triggers"][n]["time_data"] = timedelta(**t["time_data"]) t["time_data"] = timedelta(**t["time_data"])
continue continue
if t["type"] == "date": # Convert into datetime if t["type"] == "date": # Convert into datetime
# self.data["triggers"][n]["time_data"] = datetime(**t["time_data"]) # self.data["triggers"][n]["time_data"] = datetime(**t["time_data"])
self.data["triggers"][n]["time_data"] = datetime.fromisoformat(t["time_data"]) t["time_data"] = datetime.fromisoformat(t["time_data"])
continue continue
if t["type"] == "cron": if t["type"] == "cron":
continue # already a string continue # already a string
raise NotImplemented raise NotImplemented
# async def load_from_data(self, data: Dict): # async def load_from_data(self, data: Dict):
@ -300,8 +326,16 @@ class Task:
self.data["command_str"] = command_str self.data["command_str"] = command_str
return True return True
async def add_trigger(self, param, parsed_time: Union[timedelta, datetime, str]): async def add_trigger(
trigger_data = {"type": param, "time_data": parsed_time} self, param, parsed_time: Union[timedelta, datetime, str], timezone=None
):
# TODO: Save timezone separately for cron and date triggers
trigger_data = self.default_trigger.copy()
trigger_data["type"] = param
trigger_data["time_data"] = parsed_time
if timezone is not None:
trigger_data["tzinfo"] = timezone
if not get_trigger(trigger_data): if not get_trigger(trigger_data):
return False return False

@ -4,7 +4,8 @@ Timezone information for the dateutil parser
All credit to https://github.com/prefrontal/dateutil-parser-timezones All credit to https://github.com/prefrontal/dateutil-parser-timezones
""" """
from dateutil.tz import gettz # from dateutil.tz import gettz
from pytz import timezone
def assemble_timezones(): def assemble_timezones():
@ -14,182 +15,182 @@ def assemble_timezones():
""" """
timezones = {} timezones = {}
timezones['ACDT'] = gettz('Australia/Darwin') # Australian Central Daylight Savings Time (UTC+10:30) timezones['ACDT'] = timezone('Australia/Darwin') # Australian Central Daylight Savings Time (UTC+10:30)
timezones['ACST'] = gettz('Australia/Darwin') # Australian Central Standard Time (UTC+09:30) timezones['ACST'] = timezone('Australia/Darwin') # Australian Central Standard Time (UTC+09:30)
timezones['ACT'] = gettz('Brazil/Acre') # Acre Time (UTC05) timezones['ACT'] = timezone('Brazil/Acre') # Acre Time (UTC05)
timezones['ADT'] = gettz('America/Halifax') # Atlantic Daylight Time (UTC03) timezones['ADT'] = timezone('America/Halifax') # Atlantic Daylight Time (UTC03)
timezones['AEDT'] = gettz('Australia/Sydney') # Australian Eastern Daylight Savings Time (UTC+11) timezones['AEDT'] = timezone('Australia/Sydney') # Australian Eastern Daylight Savings Time (UTC+11)
timezones['AEST'] = gettz('Australia/Sydney') # Australian Eastern Standard Time (UTC+10) timezones['AEST'] = timezone('Australia/Sydney') # Australian Eastern Standard Time (UTC+10)
timezones['AFT'] = gettz('Asia/Kabul') # Afghanistan Time (UTC+04:30) timezones['AFT'] = timezone('Asia/Kabul') # Afghanistan Time (UTC+04:30)
timezones['AKDT'] = gettz('America/Juneau') # Alaska Daylight Time (UTC08) timezones['AKDT'] = timezone('America/Juneau') # Alaska Daylight Time (UTC08)
timezones['AKST'] = gettz('America/Juneau') # Alaska Standard Time (UTC09) timezones['AKST'] = timezone('America/Juneau') # Alaska Standard Time (UTC09)
timezones['AMST'] = gettz('America/Manaus') # Amazon Summer Time (Brazil)[1] (UTC03) timezones['AMST'] = timezone('America/Manaus') # Amazon Summer Time (Brazil)[1] (UTC03)
timezones['AMT'] = gettz('America/Manaus') # Amazon Time (Brazil)[2] (UTC04) timezones['AMT'] = timezone('America/Manaus') # Amazon Time (Brazil)[2] (UTC04)
timezones['ART'] = gettz('America/Cordoba') # Argentina Time (UTC03) timezones['ART'] = timezone('America/Cordoba') # Argentina Time (UTC03)
timezones['AST'] = gettz('Asia/Riyadh') # Arabia Standard Time (UTC+03) timezones['AST'] = timezone('Asia/Riyadh') # Arabia Standard Time (UTC+03)
timezones['AWST'] = gettz('Australia/Perth') # Australian Western Standard Time (UTC+08) timezones['AWST'] = timezone('Australia/Perth') # Australian Western Standard Time (UTC+08)
timezones['AZOST'] = gettz('Atlantic/Azores') # Azores Summer Time (UTC±00) timezones['AZOST'] = timezone('Atlantic/Azores') # Azores Summer Time (UTC±00)
timezones['AZOT'] = gettz('Atlantic/Azores') # Azores Standard Time (UTC01) timezones['AZOT'] = timezone('Atlantic/Azores') # Azores Standard Time (UTC01)
timezones['AZT'] = gettz('Asia/Baku') # Azerbaijan Time (UTC+04) timezones['AZT'] = timezone('Asia/Baku') # Azerbaijan Time (UTC+04)
timezones['BDT'] = gettz('Asia/Brunei') # Brunei Time (UTC+08) timezones['BDT'] = timezone('Asia/Brunei') # Brunei Time (UTC+08)
timezones['BIOT'] = gettz('Etc/GMT+6') # British Indian Ocean Time (UTC+06) timezones['BIOT'] = timezone('Etc/GMT+6') # British Indian Ocean Time (UTC+06)
timezones['BIT'] = gettz('Pacific/Funafuti') # Baker Island Time (UTC12) timezones['BIT'] = timezone('Pacific/Funafuti') # Baker Island Time (UTC12)
timezones['BOT'] = gettz('America/La_Paz') # Bolivia Time (UTC04) timezones['BOT'] = timezone('America/La_Paz') # Bolivia Time (UTC04)
timezones['BRST'] = gettz('America/Sao_Paulo') # Brasilia Summer Time (UTC02) timezones['BRST'] = timezone('America/Sao_Paulo') # Brasilia Summer Time (UTC02)
timezones['BRT'] = gettz('America/Sao_Paulo') # Brasilia Time (UTC03) timezones['BRT'] = timezone('America/Sao_Paulo') # Brasilia Time (UTC03)
timezones['BST'] = gettz('Asia/Dhaka') # Bangladesh Standard Time (UTC+06) timezones['BST'] = timezone('Asia/Dhaka') # Bangladesh Standard Time (UTC+06)
timezones['BTT'] = gettz('Asia/Thimphu') # Bhutan Time (UTC+06) timezones['BTT'] = timezone('Asia/Thimphu') # Bhutan Time (UTC+06)
timezones['CAT'] = gettz('Africa/Harare') # Central Africa Time (UTC+02) timezones['CAT'] = timezone('Africa/Harare') # Central Africa Time (UTC+02)
timezones['CCT'] = gettz('Indian/Cocos') # Cocos Islands Time (UTC+06:30) timezones['CCT'] = timezone('Indian/Cocos') # Cocos Islands Time (UTC+06:30)
timezones['CDT'] = gettz('America/Chicago') # Central Daylight Time (North America) (UTC05) timezones['CDT'] = timezone('America/Chicago') # Central Daylight Time (North America) (UTC05)
timezones['CEST'] = gettz('Europe/Berlin') # Central European Summer Time (Cf. HAEC) (UTC+02) timezones['CEST'] = timezone('Europe/Berlin') # Central European Summer Time (Cf. HAEC) (UTC+02)
timezones['CET'] = gettz('Europe/Berlin') # Central European Time (UTC+01) timezones['CET'] = timezone('Europe/Berlin') # Central European Time (UTC+01)
timezones['CHADT'] = gettz('Pacific/Chatham') # Chatham Daylight Time (UTC+13:45) timezones['CHADT'] = timezone('Pacific/Chatham') # Chatham Daylight Time (UTC+13:45)
timezones['CHAST'] = gettz('Pacific/Chatham') # Chatham Standard Time (UTC+12:45) timezones['CHAST'] = timezone('Pacific/Chatham') # Chatham Standard Time (UTC+12:45)
timezones['CHOST'] = gettz('Asia/Choibalsan') # Choibalsan Summer Time (UTC+09) timezones['CHOST'] = timezone('Asia/Choibalsan') # Choibalsan Summer Time (UTC+09)
timezones['CHOT'] = gettz('Asia/Choibalsan') # Choibalsan Standard Time (UTC+08) timezones['CHOT'] = timezone('Asia/Choibalsan') # Choibalsan Standard Time (UTC+08)
timezones['CHST'] = gettz('Pacific/Guam') # Chamorro Standard Time (UTC+10) timezones['CHST'] = timezone('Pacific/Guam') # Chamorro Standard Time (UTC+10)
timezones['CHUT'] = gettz('Pacific/Chuuk') # Chuuk Time (UTC+10) timezones['CHUT'] = timezone('Pacific/Chuuk') # Chuuk Time (UTC+10)
timezones['CIST'] = gettz('Etc/GMT-8') # Clipperton Island Standard Time (UTC08) timezones['CIST'] = timezone('Etc/GMT-8') # Clipperton Island Standard Time (UTC08)
timezones['CIT'] = gettz('Asia/Makassar') # Central Indonesia Time (UTC+08) timezones['CIT'] = timezone('Asia/Makassar') # Central Indonesia Time (UTC+08)
timezones['CKT'] = gettz('Pacific/Rarotonga') # Cook Island Time (UTC10) timezones['CKT'] = timezone('Pacific/Rarotonga') # Cook Island Time (UTC10)
timezones['CLST'] = gettz('America/Santiago') # Chile Summer Time (UTC03) timezones['CLST'] = timezone('America/Santiago') # Chile Summer Time (UTC03)
timezones['CLT'] = gettz('America/Santiago') # Chile Standard Time (UTC04) timezones['CLT'] = timezone('America/Santiago') # Chile Standard Time (UTC04)
timezones['COST'] = gettz('America/Bogota') # Colombia Summer Time (UTC04) timezones['COST'] = timezone('America/Bogota') # Colombia Summer Time (UTC04)
timezones['COT'] = gettz('America/Bogota') # Colombia Time (UTC05) timezones['COT'] = timezone('America/Bogota') # Colombia Time (UTC05)
timezones['CST'] = gettz('America/Chicago') # Central Standard Time (North America) (UTC06) timezones['CST'] = timezone('America/Chicago') # Central Standard Time (North America) (UTC06)
timezones['CT'] = gettz('Asia/Chongqing') # China time (UTC+08) timezones['CT'] = timezone('Asia/Chongqing') # China time (UTC+08)
timezones['CVT'] = gettz('Atlantic/Cape_Verde') # Cape Verde Time (UTC01) timezones['CVT'] = timezone('Atlantic/Cape_Verde') # Cape Verde Time (UTC01)
timezones['CXT'] = gettz('Indian/Christmas') # Christmas Island Time (UTC+07) timezones['CXT'] = timezone('Indian/Christmas') # Christmas Island Time (UTC+07)
timezones['DAVT'] = gettz('Antarctica/Davis') # Davis Time (UTC+07) timezones['DAVT'] = timezone('Antarctica/Davis') # Davis Time (UTC+07)
timezones['DDUT'] = gettz('Antarctica/DumontDUrville') # Dumont d'Urville Time (UTC+10) timezones['DDUT'] = timezone('Antarctica/DumontDUrville') # Dumont d'Urville Time (UTC+10)
timezones['DFT'] = gettz('Europe/Berlin') # AIX equivalent of Central European Time (UTC+01) timezones['DFT'] = timezone('Europe/Berlin') # AIX equivalent of Central European Time (UTC+01)
timezones['EASST'] = gettz('Chile/EasterIsland') # Easter Island Summer Time (UTC05) timezones['EASST'] = timezone('Chile/EasterIsland') # Easter Island Summer Time (UTC05)
timezones['EAST'] = gettz('Chile/EasterIsland') # Easter Island Standard Time (UTC06) timezones['EAST'] = timezone('Chile/EasterIsland') # Easter Island Standard Time (UTC06)
timezones['EAT'] = gettz('Africa/Mogadishu') # East Africa Time (UTC+03) timezones['EAT'] = timezone('Africa/Mogadishu') # East Africa Time (UTC+03)
timezones['ECT'] = gettz('America/Guayaquil') # Ecuador Time (UTC05) timezones['ECT'] = timezone('America/Guayaquil') # Ecuador Time (UTC05)
timezones['EDT'] = gettz('America/New_York') # Eastern Daylight Time (North America) (UTC04) timezones['EDT'] = timezone('America/New_York') # Eastern Daylight Time (North America) (UTC04)
timezones['EEST'] = gettz('Europe/Bucharest') # Eastern European Summer Time (UTC+03) timezones['EEST'] = timezone('Europe/Bucharest') # Eastern European Summer Time (UTC+03)
timezones['EET'] = gettz('Europe/Bucharest') # Eastern European Time (UTC+02) timezones['EET'] = timezone('Europe/Bucharest') # Eastern European Time (UTC+02)
timezones['EGST'] = gettz('America/Scoresbysund') # Eastern Greenland Summer Time (UTC±00) timezones['EGST'] = timezone('America/Scoresbysund') # Eastern Greenland Summer Time (UTC±00)
timezones['EGT'] = gettz('America/Scoresbysund') # Eastern Greenland Time (UTC01) timezones['EGT'] = timezone('America/Scoresbysund') # Eastern Greenland Time (UTC01)
timezones['EIT'] = gettz('Asia/Jayapura') # Eastern Indonesian Time (UTC+09) timezones['EIT'] = timezone('Asia/Jayapura') # Eastern Indonesian Time (UTC+09)
timezones['EST'] = gettz('America/New_York') # Eastern Standard Time (North America) (UTC05) timezones['EST'] = timezone('America/New_York') # Eastern Standard Time (North America) (UTC05)
timezones['FET'] = gettz('Europe/Minsk') # Further-eastern European Time (UTC+03) timezones['FET'] = timezone('Europe/Minsk') # Further-eastern European Time (UTC+03)
timezones['FJT'] = gettz('Pacific/Fiji') # Fiji Time (UTC+12) timezones['FJT'] = timezone('Pacific/Fiji') # Fiji Time (UTC+12)
timezones['FKST'] = gettz('Atlantic/Stanley') # Falkland Islands Summer Time (UTC03) timezones['FKST'] = timezone('Atlantic/Stanley') # Falkland Islands Summer Time (UTC03)
timezones['FKT'] = gettz('Atlantic/Stanley') # Falkland Islands Time (UTC04) timezones['FKT'] = timezone('Atlantic/Stanley') # Falkland Islands Time (UTC04)
timezones['FNT'] = gettz('Brazil/DeNoronha') # Fernando de Noronha Time (UTC02) timezones['FNT'] = timezone('Brazil/DeNoronha') # Fernando de Noronha Time (UTC02)
timezones['GALT'] = gettz('Pacific/Galapagos') # Galapagos Time (UTC06) timezones['GALT'] = timezone('Pacific/Galapagos') # Galapagos Time (UTC06)
timezones['GAMT'] = gettz('Pacific/Gambier') # Gambier Islands (UTC09) timezones['GAMT'] = timezone('Pacific/Gambier') # Gambier Islands (UTC09)
timezones['GET'] = gettz('Asia/Tbilisi') # Georgia Standard Time (UTC+04) timezones['GET'] = timezone('Asia/Tbilisi') # Georgia Standard Time (UTC+04)
timezones['GFT'] = gettz('America/Cayenne') # French Guiana Time (UTC03) timezones['GFT'] = timezone('America/Cayenne') # French Guiana Time (UTC03)
timezones['GILT'] = gettz('Pacific/Tarawa') # Gilbert Island Time (UTC+12) timezones['GILT'] = timezone('Pacific/Tarawa') # Gilbert Island Time (UTC+12)
timezones['GIT'] = gettz('Pacific/Gambier') # Gambier Island Time (UTC09) timezones['GIT'] = timezone('Pacific/Gambier') # Gambier Island Time (UTC09)
timezones['GMT'] = gettz('GMT') # Greenwich Mean Time (UTC±00) timezones['GMT'] = timezone('GMT') # Greenwich Mean Time (UTC±00)
timezones['GST'] = gettz('Asia/Muscat') # Gulf Standard Time (UTC+04) timezones['GST'] = timezone('Asia/Muscat') # Gulf Standard Time (UTC+04)
timezones['GYT'] = gettz('America/Guyana') # Guyana Time (UTC04) timezones['GYT'] = timezone('America/Guyana') # Guyana Time (UTC04)
timezones['HADT'] = gettz('Pacific/Honolulu') # Hawaii-Aleutian Daylight Time (UTC09) timezones['HADT'] = timezone('Pacific/Honolulu') # Hawaii-Aleutian Daylight Time (UTC09)
timezones['HAEC'] = gettz('Europe/Paris') # Heure Avancée d'Europe Centrale (CEST) (UTC+02) timezones['HAEC'] = timezone('Europe/Paris') # Heure Avancée d'Europe Centrale (CEST) (UTC+02)
timezones['HAST'] = gettz('Pacific/Honolulu') # Hawaii-Aleutian Standard Time (UTC10) timezones['HAST'] = timezone('Pacific/Honolulu') # Hawaii-Aleutian Standard Time (UTC10)
timezones['HKT'] = gettz('Asia/Hong_Kong') # Hong Kong Time (UTC+08) timezones['HKT'] = timezone('Asia/Hong_Kong') # Hong Kong Time (UTC+08)
timezones['HMT'] = gettz('Indian/Kerguelen') # Heard and McDonald Islands Time (UTC+05) timezones['HMT'] = timezone('Indian/Kerguelen') # Heard and McDonald Islands Time (UTC+05)
timezones['HOVST'] = gettz('Asia/Hovd') # Khovd Summer Time (UTC+08) timezones['HOVST'] = timezone('Asia/Hovd') # Khovd Summer Time (UTC+08)
timezones['HOVT'] = gettz('Asia/Hovd') # Khovd Standard Time (UTC+07) timezones['HOVT'] = timezone('Asia/Hovd') # Khovd Standard Time (UTC+07)
timezones['ICT'] = gettz('Asia/Ho_Chi_Minh') # Indochina Time (UTC+07) timezones['ICT'] = timezone('Asia/Ho_Chi_Minh') # Indochina Time (UTC+07)
timezones['IDT'] = gettz('Asia/Jerusalem') # Israel Daylight Time (UTC+03) timezones['IDT'] = timezone('Asia/Jerusalem') # Israel Daylight Time (UTC+03)
timezones['IOT'] = gettz('Etc/GMT+3') # Indian Ocean Time (UTC+03) timezones['IOT'] = timezone('Etc/GMT+3') # Indian Ocean Time (UTC+03)
timezones['IRDT'] = gettz('Asia/Tehran') # Iran Daylight Time (UTC+04:30) timezones['IRDT'] = timezone('Asia/Tehran') # Iran Daylight Time (UTC+04:30)
timezones['IRKT'] = gettz('Asia/Irkutsk') # Irkutsk Time (UTC+08) timezones['IRKT'] = timezone('Asia/Irkutsk') # Irkutsk Time (UTC+08)
timezones['IRST'] = gettz('Asia/Tehran') # Iran Standard Time (UTC+03:30) timezones['IRST'] = timezone('Asia/Tehran') # Iran Standard Time (UTC+03:30)
timezones['IST'] = gettz('Asia/Kolkata') # Indian Standard Time (UTC+05:30) timezones['IST'] = timezone('Asia/Kolkata') # Indian Standard Time (UTC+05:30)
timezones['JST'] = gettz('Asia/Tokyo') # Japan Standard Time (UTC+09) timezones['JST'] = timezone('Asia/Tokyo') # Japan Standard Time (UTC+09)
timezones['KGT'] = gettz('Asia/Bishkek') # Kyrgyzstan time (UTC+06) timezones['KGT'] = timezone('Asia/Bishkek') # Kyrgyzstan time (UTC+06)
timezones['KOST'] = gettz('Pacific/Kosrae') # Kosrae Time (UTC+11) timezones['KOST'] = timezone('Pacific/Kosrae') # Kosrae Time (UTC+11)
timezones['KRAT'] = gettz('Asia/Krasnoyarsk') # Krasnoyarsk Time (UTC+07) timezones['KRAT'] = timezone('Asia/Krasnoyarsk') # Krasnoyarsk Time (UTC+07)
timezones['KST'] = gettz('Asia/Seoul') # Korea Standard Time (UTC+09) timezones['KST'] = timezone('Asia/Seoul') # Korea Standard Time (UTC+09)
timezones['LHST'] = gettz('Australia/Lord_Howe') # Lord Howe Standard Time (UTC+10:30) timezones['LHST'] = timezone('Australia/Lord_Howe') # Lord Howe Standard Time (UTC+10:30)
timezones['LINT'] = gettz('Pacific/Kiritimati') # Line Islands Time (UTC+14) timezones['LINT'] = timezone('Pacific/Kiritimati') # Line Islands Time (UTC+14)
timezones['MAGT'] = gettz('Asia/Magadan') # Magadan Time (UTC+12) timezones['MAGT'] = timezone('Asia/Magadan') # Magadan Time (UTC+12)
timezones['MART'] = gettz('Pacific/Marquesas') # Marquesas Islands Time (UTC09:30) timezones['MART'] = timezone('Pacific/Marquesas') # Marquesas Islands Time (UTC09:30)
timezones['MAWT'] = gettz('Antarctica/Mawson') # Mawson Station Time (UTC+05) timezones['MAWT'] = timezone('Antarctica/Mawson') # Mawson Station Time (UTC+05)
timezones['MDT'] = gettz('America/Denver') # Mountain Daylight Time (North America) (UTC06) timezones['MDT'] = timezone('America/Denver') # Mountain Daylight Time (North America) (UTC06)
timezones['MEST'] = gettz('Europe/Paris') # Middle European Summer Time Same zone as CEST (UTC+02) timezones['MEST'] = timezone('Europe/Paris') # Middle European Summer Time Same zone as CEST (UTC+02)
timezones['MET'] = gettz('Europe/Berlin') # Middle European Time Same zone as CET (UTC+01) timezones['MET'] = timezone('Europe/Berlin') # Middle European Time Same zone as CET (UTC+01)
timezones['MHT'] = gettz('Pacific/Kwajalein') # Marshall Islands (UTC+12) timezones['MHT'] = timezone('Pacific/Kwajalein') # Marshall Islands (UTC+12)
timezones['MIST'] = gettz('Antarctica/Macquarie') # Macquarie Island Station Time (UTC+11) timezones['MIST'] = timezone('Antarctica/Macquarie') # Macquarie Island Station Time (UTC+11)
timezones['MIT'] = gettz('Pacific/Marquesas') # Marquesas Islands Time (UTC09:30) timezones['MIT'] = timezone('Pacific/Marquesas') # Marquesas Islands Time (UTC09:30)
timezones['MMT'] = gettz('Asia/Rangoon') # Myanmar Standard Time (UTC+06:30) timezones['MMT'] = timezone('Asia/Rangoon') # Myanmar Standard Time (UTC+06:30)
timezones['MSK'] = gettz('Europe/Moscow') # Moscow Time (UTC+03) timezones['MSK'] = timezone('Europe/Moscow') # Moscow Time (UTC+03)
timezones['MST'] = gettz('America/Denver') # Mountain Standard Time (North America) (UTC07) timezones['MST'] = timezone('America/Denver') # Mountain Standard Time (North America) (UTC07)
timezones['MUT'] = gettz('Indian/Mauritius') # Mauritius Time (UTC+04) timezones['MUT'] = timezone('Indian/Mauritius') # Mauritius Time (UTC+04)
timezones['MVT'] = gettz('Indian/Maldives') # Maldives Time (UTC+05) timezones['MVT'] = timezone('Indian/Maldives') # Maldives Time (UTC+05)
timezones['MYT'] = gettz('Asia/Kuching') # Malaysia Time (UTC+08) timezones['MYT'] = timezone('Asia/Kuching') # Malaysia Time (UTC+08)
timezones['NCT'] = gettz('Pacific/Noumea') # New Caledonia Time (UTC+11) timezones['NCT'] = timezone('Pacific/Noumea') # New Caledonia Time (UTC+11)
timezones['NDT'] = gettz('Canada/Newfoundland') # Newfoundland Daylight Time (UTC02:30) timezones['NDT'] = timezone('Canada/Newfoundland') # Newfoundland Daylight Time (UTC02:30)
timezones['NFT'] = gettz('Pacific/Norfolk') # Norfolk Time (UTC+11) timezones['NFT'] = timezone('Pacific/Norfolk') # Norfolk Time (UTC+11)
timezones['NPT'] = gettz('Asia/Kathmandu') # Nepal Time (UTC+05:45) timezones['NPT'] = timezone('Asia/Kathmandu') # Nepal Time (UTC+05:45)
timezones['NST'] = gettz('Canada/Newfoundland') # Newfoundland Standard Time (UTC03:30) timezones['NST'] = timezone('Canada/Newfoundland') # Newfoundland Standard Time (UTC03:30)
timezones['NT'] = gettz('Canada/Newfoundland') # Newfoundland Time (UTC03:30) timezones['NT'] = timezone('Canada/Newfoundland') # Newfoundland Time (UTC03:30)
timezones['NUT'] = gettz('Pacific/Niue') # Niue Time (UTC11) timezones['NUT'] = timezone('Pacific/Niue') # Niue Time (UTC11)
timezones['NZDT'] = gettz('Pacific/Auckland') # New Zealand Daylight Time (UTC+13) timezones['NZDT'] = timezone('Pacific/Auckland') # New Zealand Daylight Time (UTC+13)
timezones['NZST'] = gettz('Pacific/Auckland') # New Zealand Standard Time (UTC+12) timezones['NZST'] = timezone('Pacific/Auckland') # New Zealand Standard Time (UTC+12)
timezones['OMST'] = gettz('Asia/Omsk') # Omsk Time (UTC+06) timezones['OMST'] = timezone('Asia/Omsk') # Omsk Time (UTC+06)
timezones['ORAT'] = gettz('Asia/Oral') # Oral Time (UTC+05) timezones['ORAT'] = timezone('Asia/Oral') # Oral Time (UTC+05)
timezones['PDT'] = gettz('America/Los_Angeles') # Pacific Daylight Time (North America) (UTC07) timezones['PDT'] = timezone('America/Los_Angeles') # Pacific Daylight Time (North America) (UTC07)
timezones['PET'] = gettz('America/Lima') # Peru Time (UTC05) timezones['PET'] = timezone('America/Lima') # Peru Time (UTC05)
timezones['PETT'] = gettz('Asia/Kamchatka') # Kamchatka Time (UTC+12) timezones['PETT'] = timezone('Asia/Kamchatka') # Kamchatka Time (UTC+12)
timezones['PGT'] = gettz('Pacific/Port_Moresby') # Papua New Guinea Time (UTC+10) timezones['PGT'] = timezone('Pacific/Port_Moresby') # Papua New Guinea Time (UTC+10)
timezones['PHOT'] = gettz('Pacific/Enderbury') # Phoenix Island Time (UTC+13) timezones['PHOT'] = timezone('Pacific/Enderbury') # Phoenix Island Time (UTC+13)
timezones['PKT'] = gettz('Asia/Karachi') # Pakistan Standard Time (UTC+05) timezones['PKT'] = timezone('Asia/Karachi') # Pakistan Standard Time (UTC+05)
timezones['PMDT'] = gettz('America/Miquelon') # Saint Pierre and Miquelon Daylight time (UTC02) timezones['PMDT'] = timezone('America/Miquelon') # Saint Pierre and Miquelon Daylight time (UTC02)
timezones['PMST'] = gettz('America/Miquelon') # Saint Pierre and Miquelon Standard Time (UTC03) timezones['PMST'] = timezone('America/Miquelon') # Saint Pierre and Miquelon Standard Time (UTC03)
timezones['PONT'] = gettz('Pacific/Pohnpei') # Pohnpei Standard Time (UTC+11) timezones['PONT'] = timezone('Pacific/Pohnpei') # Pohnpei Standard Time (UTC+11)
timezones['PST'] = gettz('America/Los_Angeles') # Pacific Standard Time (North America) (UTC08) timezones['PST'] = timezone('America/Los_Angeles') # Pacific Standard Time (North America) (UTC08)
timezones['PYST'] = gettz('America/Asuncion') # Paraguay Summer Time (South America)[7] (UTC03) timezones['PYST'] = timezone('America/Asuncion') # Paraguay Summer Time (South America)[7] (UTC03)
timezones['PYT'] = gettz('America/Asuncion') # Paraguay Time (South America)[8] (UTC04) timezones['PYT'] = timezone('America/Asuncion') # Paraguay Time (South America)[8] (UTC04)
timezones['RET'] = gettz('Indian/Reunion') # Réunion Time (UTC+04) timezones['RET'] = timezone('Indian/Reunion') # Réunion Time (UTC+04)
timezones['ROTT'] = gettz('Antarctica/Rothera') # Rothera Research Station Time (UTC03) timezones['ROTT'] = timezone('Antarctica/Rothera') # Rothera Research Station Time (UTC03)
timezones['SAKT'] = gettz('Asia/Vladivostok') # Sakhalin Island time (UTC+11) timezones['SAKT'] = timezone('Asia/Vladivostok') # Sakhalin Island time (UTC+11)
timezones['SAMT'] = gettz('Europe/Samara') # Samara Time (UTC+04) timezones['SAMT'] = timezone('Europe/Samara') # Samara Time (UTC+04)
timezones['SAST'] = gettz('Africa/Johannesburg') # South African Standard Time (UTC+02) timezones['SAST'] = timezone('Africa/Johannesburg') # South African Standard Time (UTC+02)
timezones['SBT'] = gettz('Pacific/Guadalcanal') # Solomon Islands Time (UTC+11) timezones['SBT'] = timezone('Pacific/Guadalcanal') # Solomon Islands Time (UTC+11)
timezones['SCT'] = gettz('Indian/Mahe') # Seychelles Time (UTC+04) timezones['SCT'] = timezone('Indian/Mahe') # Seychelles Time (UTC+04)
timezones['SGT'] = gettz('Asia/Singapore') # Singapore Time (UTC+08) timezones['SGT'] = timezone('Asia/Singapore') # Singapore Time (UTC+08)
timezones['SLST'] = gettz('Asia/Colombo') # Sri Lanka Standard Time (UTC+05:30) timezones['SLST'] = timezone('Asia/Colombo') # Sri Lanka Standard Time (UTC+05:30)
timezones['SRET'] = gettz('Asia/Srednekolymsk') # Srednekolymsk Time (UTC+11) timezones['SRET'] = timezone('Asia/Srednekolymsk') # Srednekolymsk Time (UTC+11)
timezones['SRT'] = gettz('America/Paramaribo') # Suriname Time (UTC03) timezones['SRT'] = timezone('America/Paramaribo') # Suriname Time (UTC03)
timezones['SST'] = gettz('Asia/Singapore') # Singapore Standard Time (UTC+08) timezones['SST'] = timezone('Asia/Singapore') # Singapore Standard Time (UTC+08)
timezones['SYOT'] = gettz('Antarctica/Syowa') # Showa Station Time (UTC+03) timezones['SYOT'] = timezone('Antarctica/Syowa') # Showa Station Time (UTC+03)
timezones['TAHT'] = gettz('Pacific/Tahiti') # Tahiti Time (UTC10) timezones['TAHT'] = timezone('Pacific/Tahiti') # Tahiti Time (UTC10)
timezones['TFT'] = gettz('Indian/Kerguelen') # Indian/Kerguelen (UTC+05) timezones['TFT'] = timezone('Indian/Kerguelen') # Indian/Kerguelen (UTC+05)
timezones['THA'] = gettz('Asia/Bangkok') # Thailand Standard Time (UTC+07) timezones['THA'] = timezone('Asia/Bangkok') # Thailand Standard Time (UTC+07)
timezones['TJT'] = gettz('Asia/Dushanbe') # Tajikistan Time (UTC+05) timezones['TJT'] = timezone('Asia/Dushanbe') # Tajikistan Time (UTC+05)
timezones['TKT'] = gettz('Pacific/Fakaofo') # Tokelau Time (UTC+13) timezones['TKT'] = timezone('Pacific/Fakaofo') # Tokelau Time (UTC+13)
timezones['TLT'] = gettz('Asia/Dili') # Timor Leste Time (UTC+09) timezones['TLT'] = timezone('Asia/Dili') # Timor Leste Time (UTC+09)
timezones['TMT'] = gettz('Asia/Ashgabat') # Turkmenistan Time (UTC+05) timezones['TMT'] = timezone('Asia/Ashgabat') # Turkmenistan Time (UTC+05)
timezones['TOT'] = gettz('Pacific/Tongatapu') # Tonga Time (UTC+13) timezones['TOT'] = timezone('Pacific/Tongatapu') # Tonga Time (UTC+13)
timezones['TVT'] = gettz('Pacific/Funafuti') # Tuvalu Time (UTC+12) timezones['TVT'] = timezone('Pacific/Funafuti') # Tuvalu Time (UTC+12)
timezones['ULAST'] = gettz('Asia/Ulan_Bator') # Ulaanbaatar Summer Time (UTC+09) timezones['ULAST'] = timezone('Asia/Ulan_Bator') # Ulaanbaatar Summer Time (UTC+09)
timezones['ULAT'] = gettz('Asia/Ulan_Bator') # Ulaanbaatar Standard Time (UTC+08) timezones['ULAT'] = timezone('Asia/Ulan_Bator') # Ulaanbaatar Standard Time (UTC+08)
timezones['USZ1'] = gettz('Europe/Kaliningrad') # Kaliningrad Time (UTC+02) timezones['USZ1'] = timezone('Europe/Kaliningrad') # Kaliningrad Time (UTC+02)
timezones['UTC'] = gettz('UTC') # Coordinated Universal Time (UTC±00) timezones['UTC'] = timezone('UTC') # Coordinated Universal Time (UTC±00)
timezones['UYST'] = gettz('America/Montevideo') # Uruguay Summer Time (UTC02) timezones['UYST'] = timezone('America/Montevideo') # Uruguay Summer Time (UTC02)
timezones['UYT'] = gettz('America/Montevideo') # Uruguay Standard Time (UTC03) timezones['UYT'] = timezone('America/Montevideo') # Uruguay Standard Time (UTC03)
timezones['UZT'] = gettz('Asia/Tashkent') # Uzbekistan Time (UTC+05) timezones['UZT'] = timezone('Asia/Tashkent') # Uzbekistan Time (UTC+05)
timezones['VET'] = gettz('America/Caracas') # Venezuelan Standard Time (UTC04) timezones['VET'] = timezone('America/Caracas') # Venezuelan Standard Time (UTC04)
timezones['VLAT'] = gettz('Asia/Vladivostok') # Vladivostok Time (UTC+10) timezones['VLAT'] = timezone('Asia/Vladivostok') # Vladivostok Time (UTC+10)
timezones['VOLT'] = gettz('Europe/Volgograd') # Volgograd Time (UTC+04) timezones['VOLT'] = timezone('Europe/Volgograd') # Volgograd Time (UTC+04)
timezones['VOST'] = gettz('Antarctica/Vostok') # Vostok Station Time (UTC+06) timezones['VOST'] = timezone('Antarctica/Vostok') # Vostok Station Time (UTC+06)
timezones['VUT'] = gettz('Pacific/Efate') # Vanuatu Time (UTC+11) timezones['VUT'] = timezone('Pacific/Efate') # Vanuatu Time (UTC+11)
timezones['WAKT'] = gettz('Pacific/Wake') # Wake Island Time (UTC+12) timezones['WAKT'] = timezone('Pacific/Wake') # Wake Island Time (UTC+12)
timezones['WAST'] = gettz('Africa/Lagos') # West Africa Summer Time (UTC+02) timezones['WAST'] = timezone('Africa/Lagos') # West Africa Summer Time (UTC+02)
timezones['WAT'] = gettz('Africa/Lagos') # West Africa Time (UTC+01) timezones['WAT'] = timezone('Africa/Lagos') # West Africa Time (UTC+01)
timezones['WEST'] = gettz('Europe/London') # Western European Summer Time (UTC+01) timezones['WEST'] = timezone('Europe/London') # Western European Summer Time (UTC+01)
timezones['WET'] = gettz('Europe/London') # Western European Time (UTC±00) timezones['WET'] = timezone('Europe/London') # Western European Time (UTC±00)
timezones['WIT'] = gettz('Asia/Jakarta') # Western Indonesian Time (UTC+07) timezones['WIT'] = timezone('Asia/Jakarta') # Western Indonesian Time (UTC+07)
timezones['WST'] = gettz('Australia/Perth') # Western Standard Time (UTC+08) timezones['WST'] = timezone('Australia/Perth') # Western Standard Time (UTC+08)
timezones['YAKT'] = gettz('Asia/Yakutsk') # Yakutsk Time (UTC+09) timezones['YAKT'] = timezone('Asia/Yakutsk') # Yakutsk Time (UTC+09)
timezones['YEKT'] = gettz('Asia/Yekaterinburg') # Yekaterinburg Time (UTC+05) timezones['YEKT'] = timezone('Asia/Yekaterinburg') # Yekaterinburg Time (UTC+05)
return timezones return timezones

@ -6,4 +6,3 @@ def setup(bot):
n = Hangman(bot) n = Hangman(bot)
data_manager.bundled_data_path(n) data_manager.bundled_data_path(n)
bot.add_cog(n) bot.add_cog(n)
bot.add_listener(n.on_react, "on_reaction_add")

@ -50,27 +50,27 @@ class Hangman(Cog):
theface = await self.config.guild(guild).theface() theface = await self.config.guild(guild).theface()
self.hanglist[guild] = ( self.hanglist[guild] = (
"""> """>
\_________ \\_________
|/ |/
| |
| |
| |
| |
| |
|\___ |\\___
""", """,
"""> """>
\_________ \\_________
|/ | |/ |
| |
| |
| |
| |
| |
|\___ |\\___
H""", H""",
"""> """>
\_________ \\_________
|/ | |/ |
| """ | """
+ theface + theface
@ -79,10 +79,10 @@ class Hangman(Cog):
| |
| |
| |
|\___ |\\___
HA""", HA""",
"""> """>
\________ \\________
|/ | |/ |
| """ | """
+ theface + theface
@ -91,10 +91,10 @@ class Hangman(Cog):
| | | |
| |
| |
|\___ |\\___
HAN""", HAN""",
"""> """>
\_________ \\_________
|/ | |/ |
| """ | """
+ theface + theface
@ -103,43 +103,43 @@ class Hangman(Cog):
| | | |
| |
| |
|\___ |\\___
HANG""", HANG""",
"""> """>
\_________ \\_________
|/ | |/ |
| """ | """
+ theface + theface
+ """ + """
| /|\ | /|\\
| | | |
| |
| |
|\___ |\\___
HANGM""", HANGM""",
"""> """>
\________ \\________
|/ | |/ |
| """ | """
+ theface + theface
+ """ + """
| /|\ | /|\\
| | | |
| / | /
| |
|\___ |\\___
HANGMA""", HANGMA""",
"""> """>
\________ \\________
|/ | |/ |
| """ | """
+ theface + theface
+ """ + """
| /|\ | /|\\
| | | |
| / \ | / \\
| |
|\___ |\\___
HANGMAN""", HANGMAN""",
) )
@ -255,7 +255,7 @@ class Hangman(Cog):
elif i in self.the_data[guild]["guesses"] or i not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": elif i in self.the_data[guild]["guesses"] or i not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
out_str += "__" + i + "__ " out_str += "__" + i + "__ "
else: else:
out_str += "**\_** " out_str += "**\\_** "
self.winbool[guild] = False self.winbool[guild] = False
return out_str return out_str
@ -286,10 +286,10 @@ class Hangman(Cog):
await self._reprintgame(message) await self._reprintgame(message)
@commands.Cog.listener() @commands.Cog.listener("on_reaction_add")
async def on_react(self, reaction, user: Union[discord.User, discord.Member]): async def on_react(self, reaction, user: Union[discord.User, discord.Member]):
""" Thanks to flapjack reactpoll for guidelines """Thanks to flapjack reactpoll for guidelines
https://github.com/flapjax/FlapJack-Cogs/blob/master/reactpoll/reactpoll.py""" https://github.com/flapjax/FlapJack-Cogs/blob/master/reactpoll/reactpoll.py"""
guild: discord.Guild = getattr(user, "guild", None) guild: discord.Guild = getattr(user, "guild", None)
if guild is None: if guild is None:
return return

@ -75,9 +75,7 @@ class LastSeen(Cog):
else: else:
last_seen = await self.config.member(member).seen() last_seen = await self.config.member(member).seen()
if last_seen is None: if last_seen is None:
await ctx.maybe_send_embed( await ctx.maybe_send_embed("I've never seen this user")
embed=discord.Embed(description="I've never seen this user")
)
return return
last_seen = self.get_date_time(last_seen) last_seen = self.get_date_time(last_seen)

@ -360,7 +360,9 @@ class PlantTycoon(commands.Cog):
``{0}prune``: Prune your plant.\n""" ``{0}prune``: Prune your plant.\n"""
em = discord.Embed( em = discord.Embed(
title=title, description=description.format(prefix), color=discord.Color.green(), title=title,
description=description.format(prefix),
color=discord.Color.green(),
) )
em.set_thumbnail(url="https://image.prntscr.com/image/AW7GuFIBSeyEgkR2W3SeiQ.png") em.set_thumbnail(url="https://image.prntscr.com/image/AW7GuFIBSeyEgkR2W3SeiQ.png")
em.set_footer( em.set_footer(
@ -525,7 +527,8 @@ class PlantTycoon(commands.Cog):
if t: if t:
em = discord.Embed( em = discord.Embed(
title="Plant statistics of {}".format(plant["name"]), color=discord.Color.green(), title="Plant statistics of {}".format(plant["name"]),
color=discord.Color.green(),
) )
em.set_thumbnail(url=plant["image"]) em.set_thumbnail(url=plant["image"])
em.add_field(name="**Name**", value=plant["name"]) em.add_field(name="**Name**", value=plant["name"])
@ -583,7 +586,8 @@ class PlantTycoon(commands.Cog):
author = ctx.author author = ctx.author
if product is None: if product is None:
em = discord.Embed( em = discord.Embed(
title="All gardening supplies that you can buy:", color=discord.Color.green(), title="All gardening supplies that you can buy:",
color=discord.Color.green(),
) )
for pd in self.products: for pd in self.products:
em.add_field( em.add_field(
@ -616,8 +620,11 @@ class PlantTycoon(commands.Cog):
await gardener.save_gardener() await gardener.save_gardener()
message = "You bought {}.".format(product.lower()) message = "You bought {}.".format(product.lower())
else: else:
message = "You don't have enough Thneeds. You have {}, but need {}.".format( message = (
gardener.points, self.products[product.lower()]["cost"] * amount, "You don't have enough Thneeds. You have {}, but need {}.".format(
gardener.points,
self.products[product.lower()]["cost"] * amount,
)
) )
else: else:
message = "I don't have this product." message = "I don't have this product."

@ -157,7 +157,7 @@ class Timerole(Cog):
await ctx.maybe_send_embed(out) await ctx.maybe_send_embed(out)
async def timerole_update(self): async def timerole_update(self):
for guild in self.bot.guilds: async for guild in AsyncIter(self.bot.guilds):
addlist = [] addlist = []
removelist = [] removelist = []
@ -200,7 +200,7 @@ class Timerole(Cog):
async def announce_roles(self, title, role_list, channel, guild, to_add: True): async def announce_roles(self, title, role_list, channel, guild, to_add: True):
results = "" results = ""
for member, role_id in role_list: async for member, role_id in AsyncIter(role_list):
role = discord.utils.get(guild.roles, id=role_id) role = discord.utils.get(guild.roles, id=role_id)
try: try:
if to_add: if to_add:
@ -219,7 +219,7 @@ class Timerole(Cog):
log.info(results) log.info(results)
async def check_required_and_date(self, role_list, check_roles, has_roles, member, role_dict): async def check_required_and_date(self, role_list, check_roles, has_roles, member, role_dict):
for role_id in check_roles: async for role_id in AsyncIter(check_roles):
# Check for required role # Check for required role
if "required" in role_dict[str(role_id)]: if "required" in role_dict[str(role_id)]:
if not set(role_dict[str(role_id)]["required"]) & set(has_roles): if not set(role_dict[str(role_id)]["required"]) & set(has_roles):
@ -242,6 +242,3 @@ class Timerole(Cog):
while self is self.bot.get_cog("Timerole"): while self is self.bot.get_cog("Timerole"):
await self.timerole_update() await self.timerole_update()
await sleep_till_next_hour() await sleep_till_next_hour()

Loading…
Cancel
Save