From 9b634133b5ec4256299972d7d32e8c29151731cd Mon Sep 17 00:00:00 2001 From: UzNaZ Date: Wed, 20 Nov 2024 13:42:54 +0100 Subject: [PATCH 1/5] implemented main logic --- core/celery.py | 15 +++++++++++++++ core/settings.py | 15 ++++++++++++++- tracker/models.py | 1 + tracker/tasks.py | 41 +++++++++++++++++++++++++++++++++++++++++ tracker/telegram/bot.py | 22 ++++++++++++++++++---- 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 core/celery.py create mode 100644 tracker/tasks.py diff --git a/core/celery.py b/core/celery.py new file mode 100644 index 0000000..8e681e7 --- /dev/null +++ b/core/celery.py @@ -0,0 +1,15 @@ +import os + +from celery import Celery + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") + +app = Celery("core") + +app.config_from_object("django.conf:settings", namespace="CELERY") +app.autodiscover_tasks() + + +@app.task(bind=True) +def debug_task(self): + print(f"Request: {self.request!r}") diff --git a/core/settings.py b/core/settings.py index 4978fa0..8d52bf7 100644 --- a/core/settings.py +++ b/core/settings.py @@ -15,6 +15,8 @@ from dotenv import load_dotenv +from celery.schedules import timedelta + load_dotenv() # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -28,7 +30,7 @@ SECRET_KEY = os.environ.get("SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +DEBUG = True ALLOWED_HOSTS = ["*"] @@ -43,6 +45,7 @@ "django.contrib.messages", "django.contrib.staticfiles", "tracker", + ] MIDDLEWARE = [ @@ -139,3 +142,13 @@ GITHUB_AUTH_TOKEN = os.environ.get("GITHUB_AUTH_TOKEN") TELEGRAM_AUTH_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN") + +REDIS_IP = os.environ.get("CELERY_BROKER_IP", "redis") +CELERY_BROKER_URL = f"redis://{REDIS_IP}:6379/0" +CELERY_RESULT_BACKEND = f"redis://{REDIS_IP}:6379/0" +CELERY_BEAT_SCHEDULE = { + "send_orders_task": { + "task": "tracker.tasks.check_for_new_issues", + "schedule": timedelta(seconds=10), + } +} diff --git a/tracker/models.py b/tracker/models.py index 72c7340..74b4cb0 100644 --- a/tracker/models.py +++ b/tracker/models.py @@ -180,6 +180,7 @@ class TelegramUser(AbstractModel): user = models.OneToOneField(CustomUser, on_delete=models.CASCADE) telegram_id = models.CharField(unique=True) + notify_about_new_issues = models.BooleanField(default=False) def __str__(self) -> str: """ diff --git a/tracker/tasks.py b/tracker/tasks.py new file mode 100644 index 0000000..6e604f4 --- /dev/null +++ b/tracker/tasks.py @@ -0,0 +1,41 @@ +from django.db.models import Q +from celery import Celery + +from tracker.models import TelegramUser, Repository + +app = Celery('tasks', broker='redis://localhost:6379/0') + + +@app.on_after_configure.connect +def check_for_new_issues(sender, **kwargs): + # Calls test('hello') every 10 seconds. + sender.add_periodic_task(10.0, test.s('hello'), name='add every 10') + + +@app.task +def test(arg): + print(arg) + + +def get_relevant_recipients(repositories: list) -> dict[str, list]: + + subscribed_users = TelegramUser.objects.filter( + notify_about_new_issues=True, + user__repository__name__in=repositories # Assuming 'name' identifies the repositories. + ).distinct() + + user_repo_map = {} + + for telegram_user in subscribed_users: + repositories = Repository.objects.filter(user=telegram_user.user, name__in=repositories) + + print(f"Telegram User: {telegram_user.telegram_id}") + for repo in repositories: + # Initialize the list for this telegram_id if it doesn't exist + if telegram_user.telegram_id not in user_repo_map: + user_repo_map[telegram_user.telegram_id] = [] + # Append the repository name to the user's list + user_repo_map[telegram_user.telegram_id].append(repo.name) + print(f" Subscribed Repository: {repo.name}") + + return user_repo_map diff --git a/tracker/telegram/bot.py b/tracker/telegram/bot.py index 8961784..7717214 100644 --- a/tracker/telegram/bot.py +++ b/tracker/telegram/bot.py @@ -5,16 +5,18 @@ from aiogram import Bot, Dispatcher, F from aiogram.client.default import DefaultBotProperties -from aiogram.filters import CommandObject, CommandStart +from aiogram.filters import CommandObject, CommandStart, Command from aiogram.types.message import Message from aiogram.utils.deep_linking import create_start_link from aiogram.utils.keyboard import ReplyKeyboardBuilder, ReplyKeyboardMarkup +from django.core.exceptions import ObjectDoesNotExist from dotenv import load_dotenv from tracker import ISSUES_URL, PULLS_URL, get_issues_without_pull_requests +from tracker.models import TelegramUser from tracker.utils import ( create_telegram_user, - get_all_repostitories, + get_all_repositories, get_user, get_all_available_issues, ) @@ -67,6 +69,18 @@ async def start_message(message: Message) -> None: ) +@dp.message(Command("notify_about_new_issues")) +async def subscribe_to_issue_notifications(msg: Message): + try: + telegram_user = TelegramUser.objects.get(telegram_id=msg.from_user.id) + telegram_user.is_subscribed = not telegram_user.is_subscribed + telegram_user.save(update_fields=["is_subscribed"]) + return f"Subscription status updated for Telegram ID {msg.from_user.id}." + + except ObjectDoesNotExist: + return f"Telegram user with ID {msg.from_user.id} not found." + + @dp.message(F.text == "đź““get missed deadlinesđź““") async def send_deprecated_issue_assignees(msg: Message) -> None: """ @@ -74,7 +88,7 @@ async def send_deprecated_issue_assignees(msg: Message) -> None: :param msg: Message instance for communication with a user :return: None """ - all_repositories = await get_all_repostitories(msg.from_user.id) + all_repositories = await get_all_repositories(msg.from_user.id) for repository in all_repositories: issues = get_issues_without_pull_requests( @@ -120,7 +134,7 @@ async def send_available_issues(msg: Message) -> None: :param msg: Message instance for communication with a user :return: None """ - all_repositories = await get_all_repostitories(msg.from_user.id) + all_repositories = await get_all_repositories(msg.from_user.id) for repository in all_repositories: issues = get_all_available_issues( From e9e838775e0845e891b4c5d5a634c39ab57ac377 Mon Sep 17 00:00:00 2001 From: UzNaZ Date: Sat, 23 Nov 2024 17:01:30 +0100 Subject: [PATCH 2/5] fixes applied --- core/celery.py | 2 ++ core/settings.py | 4 ++- tracker/models.py | 2 +- tracker/tasks.py | 68 +++++++++++++++++++++++++++++++---------- tracker/telegram/bot.py | 23 +++++++++++--- 5 files changed, 76 insertions(+), 23 deletions(-) diff --git a/core/celery.py b/core/celery.py index 8e681e7..cf8ba09 100644 --- a/core/celery.py +++ b/core/celery.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, unicode_literals + import os from celery import Celery diff --git a/core/settings.py b/core/settings.py index 0c71d2f..cfd6e88 100644 --- a/core/settings.py +++ b/core/settings.py @@ -30,7 +30,7 @@ SECRET_KEY = os.environ.get("SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = os.environ.get("DEBUG") ALLOWED_HOSTS = [ os.environ.get("DOMAIN", "*"), @@ -147,6 +147,8 @@ TELEGRAM_AUTH_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN") REDIS_IP = os.environ.get("CELERY_BROKER_IP", "redis") +CELERY_ACCEPT_CONTENT = ["json"] +CELERY_TASK_SERIALIZER = "json" CELERY_BROKER_URL = f"redis://{REDIS_IP}:6379/0" CELERY_RESULT_BACKEND = f"redis://{REDIS_IP}:6379/0" CELERY_BEAT_SCHEDULE = { diff --git a/tracker/models.py b/tracker/models.py index 74b4cb0..e114ee4 100644 --- a/tracker/models.py +++ b/tracker/models.py @@ -180,7 +180,7 @@ class TelegramUser(AbstractModel): user = models.OneToOneField(CustomUser, on_delete=models.CASCADE) telegram_id = models.CharField(unique=True) - notify_about_new_issues = models.BooleanField(default=False) + is_allowed_notification = models.BooleanField(default=False) def __str__(self) -> str: """ diff --git a/tracker/tasks.py b/tracker/tasks.py index 6e604f4..dec5d9b 100644 --- a/tracker/tasks.py +++ b/tracker/tasks.py @@ -1,41 +1,77 @@ +import logging +import os + +import json +from asgiref.sync import async_to_sync from django.db.models import Q -from celery import Celery +from celery import Celery, shared_task +import redis +from dotenv import load_dotenv from tracker.models import TelegramUser, Repository +from tracker.telegram.bot import send_new_issue_notification + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + -app = Celery('tasks', broker='redis://localhost:6379/0') +load_dotenv() +# Connect to Redis -@app.on_after_configure.connect -def check_for_new_issues(sender, **kwargs): - # Calls test('hello') every 10 seconds. - sender.add_periodic_task(10.0, test.s('hello'), name='add every 10') +@shared_task() +def get_relevant_recipients(): + """ + Retrieves a mapping of Telegram users subscribed for + new-issue-notifications to the repositories they are subscribed to. + :return: A dictionary where keys are Telegram user IDs, and values are lists of subscribed repository names. + """ -@app.task -def test(arg): - print(arg) + Repository.objects.filter + repository_data = { + "spotnet": ["issue1", "issue2"] + } + user_data = {"name": "Alice", "age": 30} + cache = redis.Redis(host=os.environ.get("REDIS_HOST"), port=6379, decode_responses=True) + # Set a cache entry without expiration + user_data = {"name": "Alice", "age": 30} + cache.set("user:123", json.dumps(user_data)) + + # Check TTL (should return -1 for no expiration) + ttl = cache.ttl("user:123") + logger.info(f"TTL for user:123: {ttl}") # Output: -1 -def get_relevant_recipients(repositories: list) -> dict[str, list]: + # Retrieve the data + cached_data = cache.get("user:123") + if cached_data: + user = json.loads(cached_data) + print(f"User found in cache: {user}") + else: + print("User not found in cache.") + repositories = ["spotnet"] + repository_data = { + "spotnet": ["issue1", "issue2"] + } subscribed_users = TelegramUser.objects.filter( notify_about_new_issues=True, user__repository__name__in=repositories # Assuming 'name' identifies the repositories. - ).distinct() + ) user_repo_map = {} for telegram_user in subscribed_users: - repositories = Repository.objects.filter(user=telegram_user.user, name__in=repositories) + repos = Repository.objects.filter(user=telegram_user.user, name__in=repositories) - print(f"Telegram User: {telegram_user.telegram_id}") - for repo in repositories: + logger.info(f"Telegram User: {telegram_user.telegram_id}") + for repo in repos: # Initialize the list for this telegram_id if it doesn't exist if telegram_user.telegram_id not in user_repo_map: user_repo_map[telegram_user.telegram_id] = [] # Append the repository name to the user's list user_repo_map[telegram_user.telegram_id].append(repo.name) - print(f" Subscribed Repository: {repo.name}") + logger.info(f" Subscribed Repository: {repo.name}") - return user_repo_map + async_to_sync(send_new_issue_notification)(user_repo_map) diff --git a/tracker/telegram/bot.py b/tracker/telegram/bot.py index cad7564..cabf1cb 100644 --- a/tracker/telegram/bot.py +++ b/tracker/telegram/bot.py @@ -3,14 +3,15 @@ import os import sys + from aiogram import Bot, Dispatcher, F from aiogram.client.default import DefaultBotProperties from aiogram.filters import CommandObject, CommandStart, Command from aiogram.types.message import Message from aiogram.utils.deep_linking import create_start_link from aiogram.utils.keyboard import ReplyKeyboardBuilder, ReplyKeyboardMarkup -from django.core.exceptions import ObjectDoesNotExist from dotenv import load_dotenv +from celery import Celery from tracker import ISSUES_URL, PULLS_URL, get_issues_without_pull_requests from tracker.models import TelegramUser @@ -72,13 +73,18 @@ async def start_message(message: Message) -> None: @dp.message(Command("notify_about_new_issues")) async def subscribe_to_issue_notifications(msg: Message): try: - telegram_user = TelegramUser.objects.get(telegram_id=msg.from_user.id) + telegram_user = TelegramUser.objects.filter(telegram_id=msg.from_user.id).first() + if not telegram_user: + await msg.answer(f"Telegram user with ID {msg.from_user.id} not found.") + return + telegram_user.is_subscribed = not telegram_user.is_subscribed telegram_user.save(update_fields=["is_subscribed"]) - return f"Subscription status updated for Telegram ID {msg.from_user.id}." + status = "subscribed" if telegram_user.is_subscribed else "unsubscribed" + await msg.answer(f'Your status was successfully changed to "{status}"') - except ObjectDoesNotExist: - return f"Telegram user with ID {msg.from_user.id} not found." + except Exception as e: + logger.error(f"During the execution, unexpected error occurred: {e}") @dp.message(F.text == "đź““get missed deadlinesđź““") @@ -186,6 +192,13 @@ async def send_available_issues(msg: Message) -> None: await msg.reply(message, parse_mode="HTML") +async def send_new_issue_notification(id_to_repos_map: dict[str, list]): + message = "New issue appeared in the following repositories: {}" + for tg_id, repos in id_to_repos_map.values(): + message.format(", ".join(repos)) + await bot.send_message(tg_id, message) + + def main_button_markup() -> ReplyKeyboardMarkup: """ A function that generates a button From e8ebc420030cbf3eb6cbb3232a6492c779ed8707 Mon Sep 17 00:00:00 2001 From: UzNaZ Date: Mon, 25 Nov 2024 23:10:52 +0100 Subject: [PATCH 3/5] Implemented whole functionality --- .env.example | 5 ++ core/__init__.py | 7 ++ pyproject.toml | 2 + ...02_telegramuser_is_allowed_notification.py | 18 +++++ tracker/tasks.py | 54 +++++---------- tracker/telegram/bot.py | 23 +++++-- tracker/utils.py | 68 +++++++++++++++++-- 7 files changed, 130 insertions(+), 47 deletions(-) create mode 100644 tracker/migrations/0002_telegramuser_is_allowed_notification.py diff --git a/.env.example b/.env.example index ba0e41c..4b32e64 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,10 @@ # Django SECRET_KEY=# +DEBUG=# + +# redis +CELERY_BROKER_IP=# +REDIS_HOST=# # PostgreSQL DB_NAME=postgres diff --git a/core/__init__.py b/core/__init__.py index e69de29..a6e0695 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -0,0 +1,7 @@ +from __future__ import absolute_import, unicode_literals + +# This will make sure the app is always imported when +# Django starts. +from .celery import app as celery_app + +__all__ = ("celery_app",) diff --git a/pyproject.toml b/pyproject.toml index 80070e7..84254fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,8 @@ isort = "^5.13.2" requests = "^2.32.3" python-dateutil = "^2.9.0.post0" gunicorn = "^23.0.0" +celery = "^5.4.0" +redis = "^5.2.0" [build-system] diff --git a/tracker/migrations/0002_telegramuser_is_allowed_notification.py b/tracker/migrations/0002_telegramuser_is_allowed_notification.py new file mode 100644 index 0000000..70919ed --- /dev/null +++ b/tracker/migrations/0002_telegramuser_is_allowed_notification.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.3 on 2024-11-21 19:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("tracker", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="telegramuser", + name="is_allowed_notification", + field=models.BooleanField(default=False), + ), + ] diff --git a/tracker/tasks.py b/tracker/tasks.py index dec5d9b..bb866ff 100644 --- a/tracker/tasks.py +++ b/tracker/tasks.py @@ -8,8 +8,10 @@ import redis from dotenv import load_dotenv +from tracker.values import ISSUES_URL from tracker.models import TelegramUser, Repository from tracker.telegram.bot import send_new_issue_notification +from tracker.utils import get_all_opened_issues, get_existing_issues_for_subscribed_users, compare_two_repo_dicts logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -20,58 +22,38 @@ @shared_task() -def get_relevant_recipients(): +def get_relevant_recipients() -> None: """ Retrieves a mapping of Telegram users subscribed for new-issue-notifications to the repositories they are subscribed to. :return: A dictionary where keys are Telegram user IDs, and values are lists of subscribed repository names. """ + subscribed_users = TelegramUser.objects.filter( + notify_about_new_issues=True + ).first().user + repositories = Repository.objects.filter(user__in=subscribed_users).values("author", "name") + existing_issues = get_existing_issues_for_subscribed_users(repositories) - Repository.objects.filter - repository_data = { - "spotnet": ["issue1", "issue2"] - } - user_data = {"name": "Alice", "age": 30} cache = redis.Redis(host=os.environ.get("REDIS_HOST"), port=6379, decode_responses=True) + if not cache.exists("task_first_run_flag"): + cache.set("existing:issues", json.dumps(existing_issues)) + return - # Set a cache entry without expiration - user_data = {"name": "Alice", "age": 30} - cache.set("user:123", json.dumps(user_data)) - - # Check TTL (should return -1 for no expiration) - ttl = cache.ttl("user:123") - logger.info(f"TTL for user:123: {ttl}") # Output: -1 - - # Retrieve the data - cached_data = cache.get("user:123") - if cached_data: - user = json.loads(cached_data) - print(f"User found in cache: {user}") - else: - print("User not found in cache.") - - repositories = ["spotnet"] - repository_data = { - "spotnet": ["issue1", "issue2"] - } - subscribed_users = TelegramUser.objects.filter( - notify_about_new_issues=True, - user__repository__name__in=repositories # Assuming 'name' identifies the repositories. - ) + cached_existing_issues = cache.get("existing:issues") + cached_existing_issues = json.loads(str(cached_existing_issues)) + new_issues = compare_two_repo_dicts(existing_issues, cached_existing_issues) + repos_with_new_issues = [key for key in new_issues] user_repo_map = {} - for telegram_user in subscribed_users: - repos = Repository.objects.filter(user=telegram_user.user, name__in=repositories) + repos = Repository.objects.filter(user=telegram_user.user, name__in=repos_with_new_issues) logger.info(f"Telegram User: {telegram_user.telegram_id}") for repo in repos: - # Initialize the list for this telegram_id if it doesn't exist if telegram_user.telegram_id not in user_repo_map: user_repo_map[telegram_user.telegram_id] = [] - # Append the repository name to the user's list + user_repo_map[telegram_user.telegram_id].append(repo.name) - logger.info(f" Subscribed Repository: {repo.name}") - async_to_sync(send_new_issue_notification)(user_repo_map) + async_to_sync(send_new_issue_notification)(user_repo_map, new_issues) diff --git a/tracker/telegram/bot.py b/tracker/telegram/bot.py index cabf1cb..5e10be1 100644 --- a/tracker/telegram/bot.py +++ b/tracker/telegram/bot.py @@ -72,6 +72,13 @@ async def start_message(message: Message) -> None: @dp.message(Command("notify_about_new_issues")) async def subscribe_to_issue_notifications(msg: Message): + """ + + Updates telegram user subscription status, and responds with the new subscription status. + + :param msg: Message instance used to retrieve telegram id. + :return: None + """ try: telegram_user = TelegramUser.objects.filter(telegram_id=msg.from_user.id).first() if not telegram_user: @@ -84,7 +91,7 @@ async def subscribe_to_issue_notifications(msg: Message): await msg.answer(f'Your status was successfully changed to "{status}"') except Exception as e: - logger.error(f"During the execution, unexpected error occurred: {e}") + logger.info(f"During the execution, unexpected error occurred: {e}") @dp.message(F.text == "đź““get missed deadlinesđź““") @@ -189,14 +196,18 @@ async def send_available_issues(msg: Message) -> None: if not issues: message += "No available issues.\n" - await msg.reply(message, parse_mode="HTML") + await msg.reply(message) -async def send_new_issue_notification(id_to_repos_map: dict[str, list]): - message = "New issue appeared in the following repositories: {}" +async def send_new_issue_notification(id_to_repos_map: dict[str, list], + repo_to_issues_map: dict[str, list]): for tg_id, repos in id_to_repos_map.values(): - message.format(", ".join(repos)) - await bot.send_message(tg_id, message) + for repo in repos: + message = f"There are new issues in {repo}!\n" + repo_issues = repo_to_issues_map[repo] + for issue in repo_issues: + message += f"
{issue}
" + await bot.send_message(tg_id, message) def main_button_markup() -> ReplyKeyboardMarkup: diff --git a/tracker/utils.py b/tracker/utils.py index b51bc09..fc7e6cc 100644 --- a/tracker/utils.py +++ b/tracker/utils.py @@ -1,18 +1,20 @@ import logging from datetime import datetime +from typing import Tuple, Any, Dict, List import requests from asgiref.sync import sync_to_async from dateutil.relativedelta import relativedelta -from .values import HEADERS +from .models import Repository, TelegramUser +from .values import HEADERS, ISSUES_URL logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @sync_to_async -def get_all_repostitories(tele_id: str) -> list[dict]: +def get_all_repositories(tele_id: str) -> list[dict]: """ A function that returns a list of repositories asyncronously. :param tele_id: str @@ -91,8 +93,8 @@ def check_issue_assignment_events(issue: dict) -> dict: def get_all_open_and_assigned_issues(url: str) -> list[dict]: """ - Retrieves all open and assigned issues from a given URL. - :param url: The API endpoint for issues. + Retrieves all open and assigned issues from the given URL. + :param url: An API endpoint for issues. :return: A list of dictionaries representing open and assigned issues. """ try: @@ -209,9 +211,65 @@ def get_all_available_issues(url: str) -> list[dict]: issues, ) ) - logger.info(available_issues) return available_issues except requests.exceptions.RequestException as e: logger.info(e) return [] + + +def get_all_opened_issues(url: str) -> list[dict]: + """ + Retrieves all opened issues from the given URL. + :param url: An API endpoint for issues. + :return: A list of dictionaries representing opened issues. + """ + try: + response = requests.get(url, headers=HEADERS) + response.raise_for_status() + + if response.ok: + issues = response.json() + + opened_issues = list( + filter( + lambda issue: issue.get("state") == "open" + and not issue.get("draft") + and not issue.get("pull_request"), + issues, + ) + ) + + return opened_issues + except requests.exceptions.RequestException as e: + logger.info(e) + return [] + + +def get_existing_issues_for_subscribed_users(repositories: list[dict]) -> dict[str, list[str]]: + """ + Retrieves open issues for a given list of repositories. + + :param repositories: List of repositories with "author" and "name". + :return: Dictionary with repository names as keys and lists of open issue titles as values. + """ + + repository_data = {} + for repository in repositories: + issues = get_all_opened_issues(ISSUES_URL.format( + owner=repository.get("author", str()), + repo=repository.get("name", str()))) + repository_data[repository.get("name", str())] = [issue.get("title") for issue in issues] + return repository_data + + +def compare_two_repo_dicts(dict1: dict[str, list[str]], + dict2: dict[str, list[str]]) -> dict[str, list[str]]: + diff = {} + for key in dict1: + len_1 = len(dict1[key]) + len_2 = len(dict2[key]) + if len_1 > len_2: + new_issues = len_1 - len_2 + diff.update({key: dict1[key][:new_issues]}) + return diff From b7f356e147a9db0e59c2799347dda2845afb6310 Mon Sep 17 00:00:00 2001 From: iamnovichek Date: Mon, 9 Dec 2024 15:09:31 +0100 Subject: [PATCH 4/5] typo fix --- tracker/telegram/bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracker/telegram/bot.py b/tracker/telegram/bot.py index 63eb102..a2939d3 100644 --- a/tracker/telegram/bot.py +++ b/tracker/telegram/bot.py @@ -18,7 +18,7 @@ attach_link_to_issue, create_telegram_user, get_all_available_issues, - get_all_repostitories, + get_all_repositories, get_contributor_issues, get_repository_support, get_support_link, @@ -252,7 +252,7 @@ async def send_support_contacts(msg: Message) -> None: :param msg: Message instance for communication with a user :return: None """ - all_repositories = await get_all_repostitories(msg.from_user.id) + all_repositories = await get_all_repositories(msg.from_user.id) for repository in all_repositories: repo_message = TEMPLATES.repo_header.substitute( From 031be82d46472234510d5b7a0b0bb5730535bc34 Mon Sep 17 00:00:00 2001 From: iamnovichek Date: Mon, 9 Dec 2024 15:12:56 +0100 Subject: [PATCH 5/5] unnecessary imports removed --- tracker/tasks.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tracker/tasks.py b/tracker/tasks.py index 299b452..d3353bc 100644 --- a/tracker/tasks.py +++ b/tracker/tasks.py @@ -4,19 +4,16 @@ import redis from asgiref.sync import async_to_sync -from celery import Celery, shared_task -from django.db.models import Q +from celery import shared_task from dotenv import load_dotenv from tracker.models import Repository, TelegramUser from tracker.telegram.bot import send_new_issue_notification, send_revision_messages from tracker.utils import ( compare_two_repo_dicts, - get_all_opened_issues, get_existing_issues_for_subscribed_users, get_user_revisions, ) -from tracker.values import ISSUES_URL logger = logging.getLogger(__name__) logger.setLevel(logging.INFO)