From 0f14d4d91b6a87b913d23112787118ffe952b3f2 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Fri, 16 May 2025 20:35:57 -0400 Subject: [PATCH] feat(tasks)!: remove unused tasks --- README.md | 6 -- requirements.txt | 1 - src/discord_bot/bot.py | 12 --- src/discord_bot/helpers.py | 71 -------------- src/discord_bot/tasks.py | 154 ------------------------------- tests/conftest.py | 1 - tests/unit/discord/test_tasks.py | 35 ------- 7 files changed, 280 deletions(-) diff --git a/README.md b/README.md index 783dc53..9a85dbe 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,6 @@ platforms such as GitHub discussions/issues might be added in the future. | variable | required | default | description | |----------------------------------|----------|------------------------------------------------------|--------------------------------------------------------------------------------------------| -| DAILY_TASKS | False | `true` | Daily tasks on or off. | -| DAILY_RELEASES | False | `true` | Send a message for each game released on this day in history. | -| DAILY_CHANNEL_ID | False | `None` | Required if daily_tasks is enabled. | -| DAILY_TASKS_UTC_HOUR | False | `12` | The hour to run daily tasks. | | DATA_REPO | False | `https://github.com/LizardByte/support-bot-data` | Repository to store persistent data. This repository should be private! | | DATA_REPO_BRANCH | False | `master` | Branch to store persistent data. | | DISCORD_BOT_TOKEN | True | `None` | Token from Bot page on discord developer portal. | @@ -61,8 +57,6 @@ platforms such as GitHub discussions/issues might be added in the future. | GITHUB_TOKEN | True | `None` | GitHub personal access token. Must have `read:org` | | GITHUB_WEBHOOK_SECRET_KEY | True | `None` | A secret value to ensure webhooks are from trusted sources. | | GRAVATAR_EMAIL | False | `None` | Gravatar email address for bot avatar. | -| IGDB_CLIENT_ID | False | `None` | Required if daily_releases is enabled. | -| IGDB_CLIENT_SECRET | False | `None` | Required if daily_releases is enabled. | | PRAW_CLIENT_ID | True | `None` | `client_id` from reddit app setup page. | | PRAW_CLIENT_SECRET | True | `None` | `client_secret` from reddit app setup page. | | PRAW_SUBREDDIT | True | `None` | Subreddit to monitor (reddit user should be moderator of the subreddit) | diff --git a/requirements.txt b/requirements.txt index 5be453b..aa2477d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ cryptography==44.0.3 Flask==3.1.1 GitPython==3.1.44 -igdb-api-v4==0.3.3 libgravatar==1.0.4 mistletoe==1.4.0 praw==7.8.1 diff --git a/src/discord_bot/bot.py b/src/discord_bot/bot.py index 1948b95..fc9e3f5 100644 --- a/src/discord_bot/bot.py +++ b/src/discord_bot/bot.py @@ -40,7 +40,6 @@ def __init__(self, *args, **kwargs): self.ephemeral_db = {} self.oauth_states = {} self.clean_ephemeral_cache = tasks.clean_ephemeral_cache - self.daily_task = tasks.daily_task self.role_update_task = tasks.role_update_task self.load_extension( @@ -74,16 +73,6 @@ async def on_ready(self): self.clean_ephemeral_cache.start(bot=self) self.role_update_task.start(bot=self) - try: - os.environ['DAILY_TASKS'] - except KeyError: - self.daily_task.start(bot=self) - else: - if os.environ['DAILY_TASKS'].lower() == 'true': - self.daily_task.start(bot=self) - else: - print("'DAILY_TASKS' environment variable is disabled") - await self.sync_commands() async def async_send_message( @@ -284,7 +273,6 @@ def start_threaded(self): def stop(self, future: asyncio.Future = None): print("Attempting to stop tasks") self.DEGRADED = True - self.daily_task.stop() self.role_update_task.stop() self.clean_ephemeral_cache.stop() print("Attempting to close bot connection") diff --git a/src/discord_bot/helpers.py b/src/discord_bot/helpers.py index 7f363b9..528befa 100644 --- a/src/discord_bot/helpers.py +++ b/src/discord_bot/helpers.py @@ -4,55 +4,6 @@ # lib imports import requests -# convert month number to igdb human-readable month -month_dictionary = { - 1: 'Jan', - 2: 'Feb', - 3: 'Mar', - 4: 'Apr', - 5: 'May', - 6: 'Jun', - 7: 'Jul', - 8: 'Aug', - 9: 'Sep', - 10: 'Oct', - 11: 'Nov', - 12: 'Dec' -} - - -def igdb_authorization(client_id: str, client_secret: str) -> Any: - """ - Authorization for IGDB. - - Return an authorization dictionary for the IGDB api. - - Parameters - ---------- - client_id : str - IGDB/Twitch API client id. - client_secret : str - IGDB/Twitch client secret. - - Returns - ------- - Any - Authorization dictionary. - """ - grant_type = 'client_credentials' - - auth_headers = { - 'Accept': 'application/json', - 'client_id': client_id, - 'client_secret': client_secret, - 'grant_type': grant_type - } - - token_url = 'https://id.twitch.tv/oauth2/token' - - authorization = post_json(url=token_url, headers=auth_headers) - return authorization - def get_json(url: str) -> Any: """ @@ -74,25 +25,3 @@ def get_json(url: str) -> Any: data = res.json() return data - - -def post_json(url: str, headers: dict) -> Any: - """ - Make a POST request and get the response in json. - - Makes a POST request with given headers to the given url. - - Parameters - ---------- - url : str - The url for the POST request. - headers : dict - Headers for the POST request. - - Returns - ------- - Any - The json response. - """ - result = requests.post(url=url, data=headers).json() - return result diff --git a/src/discord_bot/tasks.py b/src/discord_bot/tasks.py index 53c832b..869e937 100644 --- a/src/discord_bot/tasks.py +++ b/src/discord_bot/tasks.py @@ -2,19 +2,14 @@ import asyncio import copy from datetime import datetime, UTC -import json -import os # lib imports import discord from discord.ext import tasks -from igdb.wrapper import IGDBWrapper # local imports -from src.common.common import avatar, bot_name, bot_url, colors from src.common import sponsors from src.discord_bot.bot import Bot -from src.discord_bot.helpers import igdb_authorization, month_dictionary @tasks.loop(seconds=30) @@ -32,155 +27,6 @@ async def clean_ephemeral_cache(bot: Bot) -> bool: return True -@tasks.loop(minutes=60.0) -async def daily_task(bot: Bot) -> bool: - """ - Run daily task loop. - - This function runs on a schedule, every 60 minutes. Create an embed and thread for each game released - on this day in history (according to IGDB), if enabled. - - Returns - ------- - bool - True if the task ran successfully, False otherwise. - """ - date = datetime.now(UTC) - if date.hour != int(os.getenv(key='DAILY_TASKS_UTC_HOUR', default=12)): - return False - - daily_releases = True if os.getenv(key='DAILY_RELEASES', default='true').lower() == 'true' else False - if not daily_releases: - print("'DAILY_RELEASES' environment variable is disabled") - return False - - try: - channel_id = int(os.environ['DAILY_CHANNEL_ID']) - except KeyError: - print("'DAILY_CHANNEL_ID' not defined in environment variables.") - return False - - igdb_auth = igdb_authorization(client_id=os.environ['IGDB_CLIENT_ID'], - client_secret=os.environ['IGDB_CLIENT_SECRET']) - wrapper = IGDBWrapper(client_id=os.environ['IGDB_CLIENT_ID'], auth_token=igdb_auth['access_token']) - - end_point = 'release_dates' - fields = [ - 'human', - 'game.name', - 'game.summary', - 'game.url', - 'game.genres.name', - 'game.rating', - 'game.cover.url', - 'game.artworks.url', - 'game.platforms.name', - 'game.platforms.url' - ] - - where = f'human="{month_dictionary[date.month]} {date.day:02d}"*' - limit = 500 - query = f'fields {", ".join(fields)}; where {where}; limit {limit};' - - byte_array = bytes(wrapper.api_request(endpoint=end_point, query=query)) - json_result = json.loads(byte_array) - - game_ids = [] - - for game in json_result: - try: - game_id = game['game']['id'] - except KeyError: - continue - - if game_id in game_ids: - continue # do not repeat the same game... even though it could be a different platform - game_ids.append(game_id) - - try: - embed = discord.Embed( - title=game['game']['name'], - url=game['game']['url'], - description=game['game']['summary'][0:2000 - 1], - color=colors['purple'] - ) - except KeyError: - continue - - try: - rating = round(game['game']['rating'] / 20, 1) - embed.add_field( - name='Average Rating', - value=f'⭐{rating}', - inline=True - ) - except KeyError: - continue - if rating < 4.0: # reduce the number of messages per day - continue - - try: - embed.add_field( - name='Release Date', - value=game['human'], - inline=True - ) - except KeyError: - pass - - try: - embed.set_thumbnail(url=f"https:{game['game']['cover']['url'].replace('_thumb', '_original')}") - except KeyError: - pass - - try: - embed.set_image(url=f"https:{game['game']['artworks'][0]['url'].replace('_thumb', '_original')}") - except KeyError: - pass - - try: - platforms = ', '.join(platform['name'] for platform in game['game']['platforms']) - name = 'Platforms' if len(game['game']['platforms']) > 1 else 'Platform' - - embed.add_field( - name=name, - value=platforms, - inline=False - ) - except KeyError: - pass - - try: - genres = ', '.join(genre['name'] for genre in game['game']['genres']) - name = 'Genres' if len(game['game']['genres']) > 1 else 'Genre' - - embed.add_field( - name=name, - value=genres, - inline=False - ) - except KeyError: - pass - - embed.set_author( - name=bot_name, - url=bot_url, - icon_url=avatar - ) - - embed.set_footer( - text='Data provided by IGDB', - icon_url='https://www.igdb.com/favicon-196x196.png' - ) - - message = bot.send_message(channel_id=channel_id, embed=embed) - thread = bot.create_thread(message=message, name=embed.title) - - print(f'thread created: {thread.name}') - - return True - - @tasks.loop(minutes=1.0) async def role_update_task(bot: Bot, test_mode: bool = False) -> bool: """ diff --git a/tests/conftest.py b/tests/conftest.py index b93e5ea..0f4c548 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,7 +26,6 @@ def discord_bot(): time.sleep(1) bot.role_update_task.stop() - bot.daily_task.stop() bot.clean_ephemeral_cache.stop() yield bot diff --git a/tests/unit/discord/test_tasks.py b/tests/unit/discord/test_tasks.py index e3130d4..6891549 100644 --- a/tests/unit/discord/test_tasks.py +++ b/tests/unit/discord/test_tasks.py @@ -21,16 +21,6 @@ def set_env_variable(env_var_name, request): del os.environ[env_var_name] -@pytest.fixture(scope='function') -def set_daily_channel_id(request): - yield from set_env_variable('DAILY_CHANNEL_ID', request) - - -@pytest.fixture(scope='function') -def set_daily_releases(request): - yield from set_env_variable('DAILY_RELEASES', request) - - @pytest.mark.asyncio @pytest.mark.parametrize("db_start, expected_keys", [ ( @@ -85,31 +75,6 @@ async def test_clean_ephemeral_cache(discord_bot, mocker, db_start, expected_key assert v['expires_at'] >= datetime.now(UTC) - timedelta(minutes=5), f"Key {k} should not have expired" -@pytest.mark.asyncio -@pytest.mark.parametrize("skip, set_daily_releases, set_daily_channel_id, expected", [ - (True, 'false', None, False), - (False, 'false', None, False), - (False, 'true', None, False), - (False, 'true', os.environ['DISCORD_GITHUB_STATUS_CHANNEL_ID'], True), -], indirect=["set_daily_releases", "set_daily_channel_id"]) -async def test_daily_task(discord_bot, mocker, skip, set_daily_releases, set_daily_channel_id, expected): - """ - WHEN the daily task is called - THEN check that the task runs without error - """ - # Patch datetime.datetime at the location where it's imported in `tasks` - mock_datetime = mocker.patch('src.discord_bot.tasks.datetime', autospec=True) - mock_datetime.now.return_value = datetime(2023, 1, 1, 1 if skip else 12, 0, 0, tzinfo=timezone.utc) - - # Run the daily task - result = await tasks.daily_task(bot=discord_bot) - - assert result is expected - - # Verify that datetime.now() was called - mock_datetime.now.assert_called_once() - - @pytest.mark.asyncio @pytest.mark.parametrize("skip", [True, False]) async def test_role_update_task(discord_bot, discord_db_users, mocker, skip):