Move calc_counddown() to own file

This commit is contained in:
2022-08-14 13:43:29 +02:00
parent d25f98abf5
commit 35e47115b8
3 changed files with 67 additions and 61 deletions

View File

@ -0,0 +1,54 @@
import datetime
import pytz
from apscheduler.job import Job
from apscheduler.triggers.date import DateTrigger
from discord_reminder_bot.settings import config_timezone
def calculate(job: Job) -> str:
"""Get trigger time from a reminder and calculate how many days,
hours and minutes till trigger.
Days/Minutes will not be included if 0.
Args:
job: The job. Can be cron, interval or normal.
Returns:
Returns days, hours and minutes till reminder. Returns "Failed to calculate time" if no job is found.
"""
# TODO: This "breaks" when only seconds are left.
# If we use (in {calc_countdown(job)}) it will show (in )
if type(job.trigger) is DateTrigger:
trigger_time = job.trigger.run_date
else:
trigger_time = job.next_run_time
# Get_job() returns None when it can't find a job with that id.
if trigger_time is None:
# TODO: Change this to None and send this text where needed.
return "Failed to calculate time"
# Get time and date the job will run and calculate how many days,
# hours and seconds.
countdown = trigger_time - datetime.datetime.now(tz=pytz.timezone(config_timezone))
days, hours, minutes = (
countdown.days,
countdown.seconds // 3600,
countdown.seconds // 60 % 60,
)
# TODO: Explain this.
return ", ".join(
f"{x} {y}{'s' * (x != 1)}"
for x, y in (
(days, "day"),
(hours, "hour"),
(minutes, "minute"),
)
if x
)

View File

@ -1,9 +1,7 @@
import datetime
import logging import logging
import dateparser import dateparser
import discord import discord
import pytz
from apscheduler.triggers.date import DateTrigger from apscheduler.triggers.date import DateTrigger
from discord.errors import NotFound from discord.errors import NotFound
from discord.ext import commands from discord.ext import commands
@ -12,6 +10,7 @@ from discord_slash.error import IncorrectFormat, RequestFailure
from discord_slash.model import SlashCommandOptionType from discord_slash.model import SlashCommandOptionType
from discord_slash.utils.manage_commands import create_choice, create_option from discord_slash.utils.manage_commands import create_choice, create_option
from discord_reminder_bot.countdown import calculate
from discord_reminder_bot.settings import bot_token, config_timezone, log_level, scheduler, sqlite_location from discord_reminder_bot.settings import bot_token, config_timezone, log_level, scheduler, sqlite_location
bot = commands.Bot( bot = commands.Bot(
@ -21,54 +20,6 @@ bot = commands.Bot(
slash = SlashCommand(bot, sync_commands=True) slash = SlashCommand(bot, sync_commands=True)
def calc_countdown(job) -> str:
"""Get trigger time from a reminder and calculate how many days,
hours and minutes till trigger.
Days/Minutes will not be included if 0.
Args:
job: The job. Can be cron, interval or normal.
Returns:
Returns days, hours and minutes till reminder. Returns
"Failed to calculate time" if no job is found.
"""
# TODO: This "breaks" when only seconds are left.
# If we use (in {calc_countdown(job)}) it will show (in )
if type(job.trigger) is DateTrigger:
trigger_time = job.trigger.run_date
else:
trigger_time = job.next_run_time
# Get_job() returns None when it can't find a job with that id.
if trigger_time is None:
# TODO: Change this to None and send this text where needed.
return "Failed to calculate time"
# Get time and date the job will run and calculate how many days,
# hours and seconds.
countdown = trigger_time - datetime.datetime.now(tz=pytz.timezone(config_timezone))
days, hours, minutes = (
countdown.days,
countdown.seconds // 3600,
countdown.seconds // 60 % 60,
)
# TODO: Explain this.
return ", ".join(
f"{x} {y}{'s' * (x != 1)}"
for x, y in (
(days, "day"),
(hours, "hour"),
(minutes, "minute"),
)
if x
)
@bot.event @bot.event
async def on_slash_command_error(ctx: SlashContext, ex: Exception): async def on_slash_command_error(ctx: SlashContext, ex: Exception):
logging.error(f"Error occurred during the execution of '/{ctx.name} {ctx.subcommand_name}' by {ctx.author}: {ex}") logging.error(f"Error occurred during the execution of '/{ctx.name} {ctx.subcommand_name}' by {ctx.author}: {ex}")
@ -152,7 +103,7 @@ async def command_modify(ctx: SlashContext, time_or_message: str):
return return
message = job.kwargs.get("message") message = job.kwargs.get("message")
old_time = calc_countdown(job) old_time = calculate(job)
channel_name = bot.get_channel(int(job.kwargs.get("channel_id"))) channel_name = bot.get_channel(int(job.kwargs.get("channel_id")))
msg = f"**Modified** {job_from_dict} in #{channel_name}\n" msg = f"**Modified** {job_from_dict} in #{channel_name}\n"
@ -195,7 +146,7 @@ async def command_modify(ctx: SlashContext, time_or_message: str):
job = scheduler.reschedule_job(job_from_dict, run_date=date_new) job = scheduler.reschedule_job(job_from_dict, run_date=date_new)
date_old = job.trigger.run_date.strftime("%Y-%m-%d %H:%M") date_old = job.trigger.run_date.strftime("%Y-%m-%d %H:%M")
new_time = calc_countdown(job_from_dict) new_time = calculate(job_from_dict)
msg += f"**Old date**: {date_old} (in {old_time})\n**New date**: {date_new} (in {new_time})" msg += f"**Old date**: {date_old} (in {old_time})\n**New date**: {date_new} (in {new_time})"
await ctx.send(msg) await ctx.send(msg)
@ -245,7 +196,7 @@ async def remind_remove(ctx: SlashContext):
if trigger_time is None: if trigger_time is None:
trigger_value = "Paused - can be resumed with '/remind resume'" trigger_value = "Paused - can be resumed with '/remind resume'"
else: else:
trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calc_countdown(job)})' trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calculate(job)})'
msg = f"**Removed** {message} in #{channel_name}.\n**Time**: {trigger_value}" msg = f"**Removed** {message} in #{channel_name}.\n**Time**: {trigger_value}"
@ -305,7 +256,7 @@ async def send_list(ctx, skip_datetriggers=False, skip_cron_or_interval=False):
if trigger_time is None: if trigger_time is None:
trigger_value = "Paused" trigger_value = "Paused"
else: else:
trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calc_countdown(job)})' trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calculate(job)})'
job_number += 1 job_number += 1
jobs_dict[job_number] = job.id jobs_dict[job_number] = job.id
@ -376,7 +327,7 @@ async def remind_pause(ctx: SlashContext):
if trigger_time is None: if trigger_time is None:
return await ctx.channel.send(f"{message} in #{channel_name} is already paused.") return await ctx.channel.send(f"{message} in #{channel_name} is already paused.")
trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calc_countdown(job)})' trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calculate(job)})'
msg = f"**Paused** {message} in #{channel_name}.\n**Time**: {trigger_value}" msg = f"**Paused** {message} in #{channel_name}.\n**Time**: {trigger_value}"
@ -433,7 +384,7 @@ async def remind_resume(ctx: SlashContext):
if trigger_time is None: if trigger_time is None:
trigger_value = "Paused - can be resumed with '/remind resume'" trigger_value = "Paused - can be resumed with '/remind resume'"
else: else:
trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calc_countdown(job)})' trigger_value = f'{trigger_time.strftime("%Y-%m-%d %H:%M")} (in {calculate(job)})'
msg = f"**Resumed** {message} in #{channel_name}.\n**Time**: {trigger_value}\n" msg = f"**Resumed** {message} in #{channel_name}.\n**Time**: {trigger_value}\n"
@ -506,7 +457,7 @@ async def remind_add(
message = ( message = (
f"Hello {ctx.author.display_name}," f"Hello {ctx.author.display_name},"
f" I will notify you in <#{channel_id}> at:\n" f" I will notify you in <#{channel_id}> at:\n"
f"**{run_date}** (in {calc_countdown(reminder)})\n" f"**{run_date}** (in {calculate(reminder)})\n"
f"With the message:\n**{message_reason}**." f"With the message:\n**{message_reason}**."
) )
@ -675,7 +626,7 @@ async def remind_cron(
message = ( message = (
f"Hello {ctx.author.display_name}," f"Hello {ctx.author.display_name},"
f" I will send messages to <#{channel_id}>.\n" f" I will send messages to <#{channel_id}>.\n"
f"First run in {calc_countdown(job)} with the message:\n" f"First run in {calculate(job)} with the message:\n"
f"**{message_reason}**." f"**{message_reason}**."
) )
await ctx.send(message) await ctx.send(message)
@ -807,7 +758,7 @@ async def remind_interval(
# TODO: Add what arguments we used in the job to the message # TODO: Add what arguments we used in the job to the message
message = ( message = (
f"Hello {ctx.author.display_name}, I will send messages to <#{channel_id}>.\n" f"Hello {ctx.author.display_name}, I will send messages to <#{channel_id}>.\n"
f"First run in {calc_countdown(job)} with the message:\n" f"First run in {calculate(job)} with the message:\n"
f"**{message_reason}**." f"**{message_reason}**."
) )

View File

@ -10,7 +10,8 @@ from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.schedulers.asyncio import AsyncIOScheduler
from discord_reminder_bot import __version__ from discord_reminder_bot import __version__
from discord_reminder_bot.main import calc_countdown, send_to_discord from discord_reminder_bot.main import send_to_discord
from discord_reminder_bot.countdown import calculate
def test_version(): def test_version():
@ -56,5 +57,5 @@ class TestClass:
"""Check if calc_countdown returns days, hours and minutes.""" """Check if calc_countdown returns days, hours and minutes."""
# FIXME: This will break when there is 0 seconds/hours/days left # FIXME: This will break when there is 0 seconds/hours/days left
pattern = re.compile(r"\d* (day|days), \d* (hour|hours). \d* (minute|minutes)") pattern = re.compile(r"\d* (day|days), \d* (hour|hours). \d* (minute|minutes)")
countdown = calc_countdown(self.job) countdown = calculate(self.job)
assert pattern.match(countdown) assert pattern.match(countdown)