3 Commits

13 changed files with 33 additions and 190 deletions

View File

@@ -1,21 +0,0 @@
from garbage_api_client import Client
from garbage_api_client.api.default.entry_find_locations_location_entries_get import (
asyncio as entry_find,
)
from garbage_api_client.api.default.location_find_locations_get import (
asyncio as location_find,
)
from garbage_api_client.api.default.location_get_locations_id_get import (
asyncio as location_get,
)
class APIClient(Client):
async def entry_find(self, *args, **kwargs):
await entry_find(client=self, *args, **kwargs)
async def location_find(self, *args, **kwargs):
await location_find(client=self, *args, **kwargs)
async def location_get(self, *args, **kwargs):
await location_get(client=self, *args, **kwargs)

View File

@@ -1,43 +1,24 @@
import logging
from datetime import datetime, timedelta
from typing import List, Union
from aiohttp import ClientSession
from apscheduler.triggers.cron import CronTrigger
from libbot.pyrogram.classes import PyroClient as LibPyroClient
from pymongo import ASCENDING, GEOSPHERE, TEXT
from pyrogram.types import User
from classes.api_client import APIClient
from classes.location import Location
from classes.pyrouser import PyroUser
from classes.updater import Updater
from modules.database_api import col_locations
from modules.reminder import remind
logger = logging.getLogger(__name__)
class PyroClient(LibPyroClient):
def __init__(self, **kwargs):
self.__version__ = (0, 1, 2)
super().__init__(**kwargs)
self.updater = Updater(ClientSession())
self.contexts = []
self.api_client = APIClient()
if self.scheduler is not None:
self.scheduler.add_job(
remind, CronTrigger.from_crontab("* * * * *"), args=(self,)
)
if self.config["update_checker"]:
self.scheduler.add_job(
self.check_updates,
CronTrigger.from_crontab("0 12 */3 * *"),
next_run_time=datetime.now() + timedelta(seconds=10),
)
self.contexts = []
async def start(self, **kwargs):
await col_locations.create_index(
@@ -50,10 +31,6 @@ class PyroClient(LibPyroClient):
await col_locations.create_index([("name", TEXT)], name="location_name")
return await super().start(**kwargs)
async def stop(self, **kwargs):
await self.updater.client_session.close()
await super().stop(**kwargs)
async def find_user(self, user: Union[int, User]) -> PyroUser:
"""Find User by it's ID or User object.
@@ -91,24 +68,3 @@ class PyroClient(LibPyroClient):
return [
await Location.get(record["id"]) async for record in col_locations.find({})
]
async def check_updates(self) -> None:
if await self.updater.check_updates(
self.__version__, self.config["strings"]["url_updater"]
):
try:
release = await self.updater.get_latest_release(
self.config["strings"]["url_updater"]
)
except Exception as exc:
logger.error("Could not fetch the latest version: %s", exc)
return
await self.send_message(
self.owner,
self._("update_available", "messages").format(
version_current=f"v{'.'.join(str(subversion) for subversion in self.__version__)}",
version_new=release["tag_name"],
release_url=release["html_url"],
),
)

View File

@@ -1,44 +0,0 @@
import logging
from typing import Any, Dict, Tuple
from aiohttp import ClientSession
logger = logging.getLogger(__name__)
class Updater:
def __init__(self, client_session: ClientSession) -> None:
self.client_session: ClientSession = client_session
async def check_updates(
self, version_current: Tuple[int, int, int], api_url: str
) -> bool:
response = await self.client_session.get(api_url)
if response.status != 200:
return False
try:
version_latest = (await response.json())["tag_name"][1:].split(".")
except Exception as exc:
logger.error("Error parsing latest version: %s", exc)
return False
return any(
version_current[index] < int(subversion)
for index, subversion in enumerate(version_latest)
)
async def get_latest_release(self, api_url: str) -> Dict[str, Any]:
response = await self.client_session.get(api_url)
if response.status != 200:
raise RuntimeError(f"Could not fetch latest release: {response.status}")
try:
return await response.json()
except Exception as exc:
logger.error("Error parsing latest release: %s", exc)
raise RuntimeError(
f"Error parsing latest release: {response.status}"
) from exc

View File

@@ -9,9 +9,6 @@
"max_concurrent_transmissions": 1,
"scoped_commands": true
},
"api": {
"url": "https://api.garbagebot.eu"
},
"database": {
"user": null,
"password": null,
@@ -19,6 +16,13 @@
"port": 27017,
"name": "garbage_bot"
},
"database_api": {
"user": null,
"password": null,
"host": "127.0.0.1",
"port": 27017,
"name": "garbage_reminder"
},
"search": {
"radius": 0.1
},
@@ -28,8 +32,6 @@
"disabled_plugins": [],
"strings": {
"url_repo": "https://git.end-play.xyz/GarbageReminder/TelegramBot",
"url_contact": "https://git.end-play.xyz/GarbageReminder/TelegramBot/issues",
"url_updater": "https://git.end-play.xyz/api/v1/repos/GarbageReminder/TelegramBot/releases/latest"
},
"update_checker": true
"url_contact": "https://git.end-play.xyz/GarbageReminder/TelegramBot/issues"
}
}

View File

@@ -64,22 +64,21 @@
"set_time_finished": "🔔 Die Benachrichtigungszeit wurde aktualisiert! Sie erhalten nun eine Benachrichtigung über die Abholung {offset} T. vor der Abholung um **{time}**. {toggle_notice}",
"set_time_invalid": "Bitte geben Sie eine gültige Uhrzeit im Format SS:MM an. {cancel_notice}",
"set_time": "Okay. Bitte senden Sie die gewünschte Zeit im Format SS:MM.",
"setup_finished": "✅ Fertig! Sie werden die Erinnerungen an die Müllabfuhr {offset} T. im Voraus um {time} für **{name}** erhalten.",
"setup_finished": "✅ Fertig! Ihr Standort ist jetzt **{name}**. Sie werden die Benachrichtigungen über die Müllabfuhr {offset} T. im Voraus um {time} erhalten.",
"setup_retry": " Wenn Sie versuchen möchten, den Speicherort erneut auszuwählen, verwenden Sie den Kommando /setup.",
"setup": "⚙️ Beginnen wir die Konfiguration mit der Suche nach Ihrem Standort.\n\nBitte wählen Sie aus, ob Sie unter den Standorten in Ihrer Nähe suchen möchten oder direkt zur Suche nach dem Standortnamen übergehen wollen.\n\nBeachten Sie, dass der von Ihnen gesendete Standort **NICHT** irgendwo gespeichert wird und nur für die Standortsuche in der Datenbank verwendet wird.",
"start_code_invalid": "🚫 Sie haben den Bot über den Link gestartet, der einen Ort enthält, aber es scheint kein gültiger zu sein. Bitte verwenden Sie den Kommando /setup, um den Standort manuell zu konfigurieren.",
"start_code": " Sie haben den Bot über den Link gestartet, der einen Ort **{name}** enthält.\n\nBitte bestätigen Sie, ob Sie diesen als Ihren Standort verwenden möchten.",
"start_configure": "📍 Lassen Sie uns Ihren Standort konfigurieren. Drücken Sie die Taste auf der Pop-up-Tastatur, um den Vorgang zu starten.",
"start_selection_no": "Gut, Sie sind jetzt auf sich allein gestellt. Bitte verwenden Sie den Kommando /setup, um Ihren Standort zu konfigurieren und Erinnerungen zu erhalten.",
"start_selection_yes": "✅ Fertig! Sie werden die Erinnerungen an die Müllabfuhr {offset} T. im Voraus um {time} für **{name}** erhalten.\n\nBitte besuchen Sie /help Menü, wenn Sie wissen möchten, wie Sie die Zeit der Benachrichtigungen ändern oder sie deaktivieren können.",
"start": "👋 Herzlich willkommen!\n\nDieser kleine Open-Source-Bot soll Ihnen das Leben etwas erleichtern, indem er Sie über die nächste Müllabfuhr in Ihrer Nähe informiert.\n\nDurch die Nutzung dieses Bots akzeptieren Sie die [Nutzungsbedingungen]({terms_of_service}) und [Datenschutzbestimmungen]({privacy_policy}), andernfalls blockieren und entfernen Sie diesen Bot bitte vor weiterer Interaktion.\n\nNun ist der offizielle Teil vorbei und Sie können sich mit dem Bot beschäftigen.",
"start_selection_yes": "✅ Fertig! Ihr Standort ist jetzt **{name}**. Sie erhalten Erinnerungen an die Müllabfuhr {offset} T. im Voraus um {time}.\n\nBitte besuchen Sie /help Menü, wenn Sie wissen möchten, wie Sie die Zeit der Benachrichtigungen ändern oder sie deaktivieren können.",
"start": "👋 Herzlich willkommen!\n\nDieser kleine Open-Source-Bot soll Ihnen das Leben etwas erleichtern, indem er Sie über die nächste Müllabfuhr in Ihrer Nähe informiert.\n\nDurch die Nutzung dieses Bots akzeptieren Sie die [Datenschutzbestimmungen]({privacy_policy}), andernfalls blockieren und entfernen Sie diesen Bot bitte vor weiterer Interaktion.\n\nNun ist der offizielle Teil vorbei und Sie können sich mit dem Bot beschäftigen.",
"toggle_disabled": "🔕 Die Benachrichtigungen wurden deaktiviert.",
"toggle_enabled_location": "🔔 Benachrichtigungen wurden aktiviert {offset} T. vor der Sammlung um {time} am **{name}**.",
"toggle_enabled": "🔔 Benachrichtigungen wurden aktiviert {offset} T. vor der Sammlung um {time}. Verwenden Sie /setup, um Ihren Standort auszuwählen.",
"toggle": "Führen Sie /toggle aus, um Benachrichtigungen zu aktivieren.",
"upcoming_empty": "Keine Müllabfuhr-Einträge für die nächsten 30 Tage bei **{name}** gefunden",
"upcoming": "Bevorstehende Müllabfuhr:\n\n{entries}",
"update_available": "Es gibt eine neue Version von GarbageBot!\n\nVersion: `{version_current}` -> `{version_new}`\n\n[Release-Seite]({release_url}) | [Update-Anleitung](https://garbagebot.eu/bot_telegram/upgrading)"
"upcoming": "Bevorstehende Müllabfuhr:\n\n{entries}"
},
"force_replies": {
"import": "JSON mit Abfalltermine",

View File

@@ -64,22 +64,21 @@
"set_time_finished": "🔔 Notifications time has been updated! You will now receive notification about collection {offset} d. before the collection at **{time}**. {toggle_notice}",
"set_time_invalid": "Please, provide a valid time in HH:MM format. {cancel_notice}",
"set_time": "Alright. Please, send your desired time in HH:MM format.",
"setup_finished": "✅ Finished! You will receive reminders about garbage collection {offset} d. in advance at {time} for **{name}**.",
"setup_finished": "✅ Finished! Your location is now **{name}**. You will receive the notifications about garbage collection {offset} d. in advance at {time}.",
"setup_retry": " If you want try selecting the location again, use the /setup command.",
"setup": "⚙️ Let's begin configuration with the search for your location.\n\nPlease, select whether you want to search among the locations near you or go straight to the search by location name.\n\nNote that the location you send will **NOT** be saved anywhere and is only used for location lookup in the database.",
"start_code_invalid": "🚫 You have started the bot by the link containing a location, but it does not seem to be a valid one. Please, use the command /setup to manually configure the location.",
"start_code": " You have started the bot by the link containing a location **{name}**.\n\nPlease, confirm whether you want to use it as your location.",
"start_configure": "📍 Let's configure your location. Press the button on pop-up keyboard to start the process.",
"start_selection_no": "Alright, you're on your own now. Please, use the command /setup to configure your location and start receiving reminders.",
"start_selection_yes": "✅ Finished! You will receive reminders about garbage collection {offset} d. in advance at {time} for **{name}**.\n\nPlease, visit /help if you want to know how to change notifications time or disable them.",
"start": "👋 Welcome!\n\nThis small open-source bot is made to simplify your life a bit easier by sending you notifications about upcoming garbage collection in your location.\n\nBy using this bot you accept [Terms of service]({terms_of_service}) and [Privacy policy]({privacy_policy}), otherwise please block and remove this bot before further interaction.\n\nNow the official part is over so you can dive into the bot.",
"start_selection_yes": "✅ Finished! Your location is now **{name}**. You will receive reminders about garbage collection {offset} d. in advance at {time}.\n\nPlease, visit /help if you want to know how to change notifications time or disable them.",
"start": "👋 Welcome!\n\nThis small open-source bot is made to simplify your life a bit easier by sending you notifications about upcoming garbage collection in your location.\n\nBy using this bot you accept [Privacy Policy]({privacy_policy}), otherwise please block and remove this bot before further interaction.\n\nNow the official part is over so you can dive into the bot.",
"toggle_disabled": "🔕 Notifications have been disabled.",
"toggle_enabled_location": "🔔 Notifications have been enabled {offset} d. before garbage collection at {time} at the **{name}**.",
"toggle_enabled": "🔔 Notifications have been enabled {offset} d. before garbage collection at {time}. Use /setup to select your location.",
"toggle": "Execute /toggle to enable notifications.",
"upcoming_empty": "No garbage collection entries found for the next 30 days at **{name}**",
"upcoming": "Upcoming garbage collection:\n\n{entries}",
"update_available": "There is a new version of GarbageBot available!\n\nVersion: `{version_current}` -> `{version_new}`\n\n[Release page]({release_url}) | [Update instructions](https://garbagebot.eu/bot_telegram/upgrading)"
"upcoming": "Upcoming garbage collection:\n\n{entries}"
},
"buttons": {
"delete_confirm": "I agree and want to proceed",

View File

@@ -64,22 +64,21 @@
"set_time_finished": "🔔 Час сповіщень було оновлено! Тепер Ви будете отримувати сповіщення про вивіз сміття за {offset} д. до вивозу о **{time}**. {toggle_notice}",
"set_time_invalid": "Будь ласка, вкажіть дійсний час у форматі ГГ:ХХ. {cancel_notice}",
"set_time": "Гаразд. Будь ласка, надішліть бажаний час у форматі ГГ:ХХ.",
"setup_finished": "✅ Готово! Ви будете отримувати нагадування про вивезення сміття для **{name}** за {offset} д. заздалегідь о {time}.",
"setup_finished": "✅ Готово! Ваше місцезнаходження тепер **{name}**. Ви будете отримувати сповіщення про вивезення сміття за {offset} д. заздалегідь о {time}.",
"setup_retry": " Якщо Ви захочете вибрати місце розташування, скористайтеся командою /setup.",
"setup": "⚙️ Почнемо налаштування з пошуку Вашого місцезнаходження.\n\nБудь ласка, виберіть, чи хочете Ви шукати серед найближчих до Вас локацій, чи одразу перейти до пошуку за назвою.\n\nЗверніть увагу, що надіслане Вами місцезнаходження **НЕ** зберігається ніде і використовується лише для пошуку місць поряд в базі даних.",
"start_code_invalid": "🚫 Ви запустили бота за посиланням, що містить локацію, але, схоже, вона не є дійсною. Будь ласка, скористайтеся командою /setup, щоб налаштувати локацію вручну.",
"start_code": " Ви запустили бота за посиланням, що містить локацію **{name}**.\n\nБудь ласка, підтвердіть, чи хочете Ви використовувати її як свою локацію для сповіщень.",
"start_configure": "📍 Налаштуймо Вашу локацію. Натисніть кнопку на показаній клавіатурі, щоб почати процес.",
"start_selection_no": "Гаразд, тепер Ви самі по собі. Будь ласка, скористайтеся командою /setup, щоб налаштувати своє місцезнаходження і почати отримувати нагадування.",
"start_selection_yes": "✅ Готово! Ви будете отримувати нагадування про вивезення сміття для **{name}** за {offset} д. заздалегідь о {time}.\n\nБудь ласка, скористайтесь /help, якщо Ви хочете дізнатися, як змінити час сповіщень або вимкнути їх.",
"start": "👋 Вітання!\n\nЦей невеличкий бот з відкритим вихідним кодом створений для того, щоб трохи спростити Вам життя, надсилаючи сповіщення про вивіз сміття у вашому регіоні.\n\nКористуючись цим ботом, Ви приймаєте [Умови надання послуг]({terms_of_service}) та [Політику конфіденційності]({privacy_policy}), в іншому випадку, будь ласка, заблокуйте та видаліть цього бота перед подальшою взаємодією.\n\nТепер офіційна частина закінчена, тож Ви можете зануритися в бота.",
"start_selection_yes": "✅ Готово! Ваша локація тепер **{name}**. Ви будете отримувати нагадування про вивезення сміття за {offset} д. заздалегідь о {time}.\n\nБудь ласка, скористайтесь /help, якщо Ви хочете дізнатися, як змінити час сповіщень або вимкнути їх.",
"start": "👋 Вітання!\n\nЦей невеличкий бот з відкритим вихідним кодом створений для того, щоб трохи спростити Вам життя, надсилаючи сповіщення про вивіз сміття у вашому регіоні.\n\nКористуючись цим ботом, Ви приймаєте [Політику конфіденційності]({privacy_policy}), в іншому випадку, будь ласка, заблокуйте та видаліть цього бота перед подальшою взаємодією.\n\nТепер офіційна частина закінчена, тож Ви можете зануритися в бота.",
"toggle_disabled": "🔕 Сповіщення було вимкнено.",
"toggle_enabled_location": "🔔 Сповіщення увімкнено за {offset} д. до вивезення сміття о {time} для локації **{name}**.",
"toggle_enabled": "🔔 Сповіщення було увімкнено за {offset} д. до вивезення сміття о {time}. Оберіть своє розташування за допомогою /setup.",
"toggle": "Використовуйте /toggle, щоб увімкнути сповіщення.",
"upcoming_empty": "Не знайдено записів про вивезення сміття на найближчі 30 днів для **{name}**",
"upcoming": "Найближчі вивози сміття:\n\n{entries}",
"update_available": "Доступна нова версія GarbageBot!\n\nВерсія: `{version_current}` -> `{version_new}`\n\n[Сторінка релізу]({release_url}) | [Інструкція з оновлення](https://garbagebot.eu/bot_telegram/upgrading)"
"upcoming": "Найближчі вивози сміття:\n\n{entries}"
},
"buttons": {
"delete_confirm": "Я погоджуюсь і хочу продовжити",

View File

@@ -64,22 +64,21 @@
"set_time_finished": "🔔 Час сповіщень було оновлено! Тепер Ви будете отримувати сповіщення про вивіз сміття за {offset} д. до вивозу о **{time}**. {toggle_notice}",
"set_time_invalid": "Будь ласка, вкажіть дійсний час у форматі ГГ:ХХ. {cancel_notice}",
"set_time": "Гаразд. Будь ласка, надішліть бажаний час у форматі ГГ:ХХ.",
"setup_finished": "✅ Готово! Ви будете отримувати нагадування про вивезення сміття для **{name}** за {offset} д. заздалегідь о {time}.",
"setup_finished": "✅ Готово! Ваше місцезнаходження тепер **{name}**. Ви будете отримувати сповіщення про вивезення сміття за {offset} д. заздалегідь о {time}.",
"setup_retry": " Якщо Ви захочете вибрати місце розташування, скористайтеся командою /setup.",
"setup": "⚙️ Почнемо налаштування з пошуку Вашого місцезнаходження.\n\nБудь ласка, виберіть, чи хочете Ви шукати серед найближчих до Вас локацій, чи одразу перейти до пошуку за назвою.\n\nЗверніть увагу, що надіслане Вами місцезнаходження **НЕ** зберігається ніде і використовується лише для пошуку місць поряд в базі даних.",
"start_code_invalid": "🚫 Ви запустили бота за посиланням, що містить локацію, але, схоже, вона не є дійсною. Будь ласка, скористайтеся командою /setup, щоб налаштувати локацію вручну.",
"start_code": " Ви запустили бота за посиланням, що містить локацію **{name}**.\n\nБудь ласка, підтвердіть, чи хочете Ви використовувати її як свою локацію для сповіщень.",
"start_configure": "📍 Налаштуймо Вашу локацію. Натисніть кнопку на показаній клавіатурі, щоб почати процес.",
"start_selection_no": "Гаразд, тепер Ви самі по собі. Будь ласка, скористайтеся командою /setup, щоб налаштувати своє місцезнаходження і почати отримувати нагадування.",
"start_selection_yes": "✅ Готово! Ви будете отримувати нагадування про вивезення сміття для **{name}** за {offset} д. заздалегідь о {time}.\n\nБудь ласка, скористайтесь /help, якщо Ви хочете дізнатися, як змінити час сповіщень або вимкнути їх.",
"start": "👋 Вітання!\n\nЦей невеличкий бот з відкритим вихідним кодом створений для того, щоб трохи спростити Вам життя, надсилаючи сповіщення про вивіз сміття у вашому регіоні.\n\nКористуючись цим ботом, Ви приймаєте [Умови надання послуг]({terms_of_service}) та [Політику конфіденційності]({privacy_policy}), в іншому випадку, будь ласка, заблокуйте та видаліть цього бота перед подальшою взаємодією.\n\nТепер офіційна частина закінчена, тож Ви можете зануритися в бота.",
"start_selection_yes": "✅ Готово! Ваша локація тепер **{name}**. Ви будете отримувати нагадування про вивезення сміття за {offset} д. заздалегідь о {time}.\n\nБудь ласка, скористайтесь /help, якщо Ви хочете дізнатися, як змінити час сповіщень або вимкнути їх.",
"start": "👋 Вітання!\n\nЦей невеличкий бот з відкритим вихідним кодом створений для того, щоб трохи спростити Вам життя, надсилаючи сповіщення про вивіз сміття у вашому регіоні.\n\nКористуючись цим ботом, Ви приймаєте [Політику конфіденційності]({privacy_policy}), в іншому випадку, будь ласка, заблокуйте та видаліть цього бота перед подальшою взаємодією.\n\nТепер офіційна частина закінчена, тож Ви можете зануритися в бота.",
"toggle_disabled": "🔕 Сповіщення було вимкнено.",
"toggle_enabled_location": "🔔 Сповіщення увімкнено за {offset} д. до вивезення сміття о {time} для локації **{name}**.",
"toggle_enabled": "🔔 Сповіщення було увімкнено за {offset} д. до вивезення сміття о {time}. Оберіть своє розташування за допомогою /setup.",
"toggle": "Використовуйте /toggle, щоб увімкнути сповіщення.",
"upcoming_empty": "Не знайдено записів про вивезення сміття на найближчі 30 днів для **{name}**",
"upcoming": "Найближчі вивози сміття:\n\n{entries}",
"update_available": "Доступна нова версія GarbageBot!\n\nВерсія: `{version_current}` -> `{version_new}`\n\n[Сторінка релізу]({release_url}) | [Інструкція з оновлення](https://garbagebot.eu/bot_telegram/upgrading)"
"upcoming": "Найближчі вивози сміття:\n\n{entries}"
},
"buttons": {
"delete_confirm": "Я погоджуюсь і хочу продовжити",

View File

@@ -35,16 +35,14 @@ with contextlib.suppress(ImportError):
def main():
if args.migrate:
migrate_database()
logger.info("Migration finished. Exiting...")
exit()
client = PyroClient(
scheduler=scheduler, commands_source=sync.json_read(Path("commands.json"))
)
Conversation(client)
if args.migrate:
migrate_database()
try:
client.run()
except KeyboardInterrupt:

View File

@@ -1,16 +0,0 @@
from libbot import sync
from mongodb_migrations.base import BaseMigration
class Migration(BaseMigration):
def upgrade(self):
sync.config_set("update_checker", True)
sync.config_set(
"url_updater",
"https://git.end-play.xyz/api/v1/repos/GarbageReminder/TelegramBot/releases/latest",
"strings",
)
def downgrade(self):
sync.config_delete("update_checker", missing_ok=True)
sync.config_delete("url_updater", "strings")

View File

@@ -1,21 +0,0 @@
from libbot import sync
from mongodb_migrations.base import BaseMigration
class Migration(BaseMigration):
def upgrade(self):
sync.config_set("api", {"url": "https://api.garbagebot.eu"})
sync.config_delete("database_api", missing_ok=True)
def downgrade(self):
sync.config_delete("api", missing_ok=True)
sync.config_set(
"database_api",
{
"user": None,
"password": None,
"host": "127.0.0.1",
"port": 27017,
"name": "garbage_reminder",
},
)

View File

@@ -20,12 +20,7 @@ from modules.utils import from_utc
async def command_start(app: PyroClient, message: Message):
user = await app.find_user(message.from_user)
await message.reply_text(
app._("start", "messages", locale=user.locale).format(
terms_of_service="https://garbagebot.eu/community/public/terms-of-service",
privacy_policy="https://garbagebot.eu/community/public/privacy-policy",
)
)
await message.reply_text(app._("start", "messages", locale=user.locale))
join_code = None if len(message.command) == 1 else message.command[1]

View File

@@ -1,13 +1,11 @@
aiohttp~=3.9.5
apscheduler~=3.10.4
convopyro==0.5
mongodb-migrations==1.3.1
mongodb-migrations==1.3.0
tgcrypto==1.2.5
ujson>=5.0.0
uvloop==0.19.0
--extra-index-url https://git.end-play.xyz/api/packages/profitroll/pypi/simple
async_pymongo==0.1.4
libbot[speed,pyrogram]==3.2.2
pykeyboard==0.1.7
--extra-index-url https://git.end-play.xyz/api/packages/GarbageReminder/pypi/simple
garbageapi-client==0.1.0
libbot[speed,pyrogram]==3.0.0
pykeyboard==0.1.7