1 Commits

Author SHA1 Message Date
1c7095a40b WIP: #50 2024-05-30 12:50:47 +02:00
14 changed files with 102 additions and 138 deletions

21
classes/api_client.py Normal file
View File

@@ -0,0 +1,21 @@
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

@@ -8,6 +8,7 @@ from libbot.pyrogram.classes import PyroClient as LibPyroClient
from pymongo import ASCENDING, GEOSPHERE, TEXT from pymongo import ASCENDING, GEOSPHERE, TEXT
from pyrogram.types import User from pyrogram.types import User
from classes.api_client import APIClient
from classes.location import Location from classes.location import Location
from classes.pyrouser import PyroUser from classes.pyrouser import PyroUser
from classes.updater import Updater from classes.updater import Updater
@@ -25,6 +26,7 @@ class PyroClient(LibPyroClient):
self.updater = Updater(ClientSession()) self.updater = Updater(ClientSession())
self.contexts = [] self.contexts = []
self.api_client = APIClient()
if self.scheduler is not None: if self.scheduler is not None:
self.scheduler.add_job( self.scheduler.add_job(

View File

@@ -1,6 +1,5 @@
import logging import logging
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from typing import Any, Union from typing import Any, Union
from bson import ObjectId from bson import ObjectId
@@ -43,7 +42,7 @@ class PyroUser:
enabled: bool = True, enabled: bool = True,
location_id: int = 0, location_id: int = 0,
offset: int = 1, offset: int = 1,
time_hour: int = 16, time_hour: int = 18,
time_minute: int = 0, time_minute: int = 0,
): ):
db_entry = await col_users.find_one({"id": id}) db_entry = await col_users.find_one({"id": id})
@@ -89,32 +88,26 @@ class PyroUser:
""" """
logger.debug("%s's locale has been set to %s", self.id, locale) logger.debug("%s's locale has been set to %s", self.id, locale)
await col_users.update_one({"_id": self._id}, {"$set": {"locale": locale}}) await col_users.update_one({"_id": self._id}, {"$set": {"locale": locale}})
self.locale = locale
async def update_state(self, enabled: bool = False) -> None: async def update_state(self, enabled: bool = False) -> None:
logger.debug("%s's state has been set to %s", self.id, enabled) logger.debug("%s's state has been set to %s", self.id, enabled)
await col_users.update_one({"_id": self._id}, {"$set": {"enabled": enabled}}) await col_users.update_one({"_id": self._id}, {"$set": {"enabled": enabled}})
self.enabled = enabled
async def update_location(self, location_id: int = 0) -> None: async def update_location(self, location_id: int = 0) -> None:
logger.debug("%s's location has been set to %s", self.id, location_id) logger.debug("%s's location has been set to %s", self.id, location_id)
await col_users.update_one( await col_users.update_one(
{"_id": self._id}, {"$set": {"location": location_id}} {"_id": self._id}, {"$set": {"location": location_id}}
) )
self.location = await Location.get(location_id)
async def update_offset(self, offset: int = 1) -> None: async def update_offset(self, offset: int = 1) -> None:
logger.debug("%s's offset has been set to %s", self.id, offset) logger.debug("%s's offset has been set to %s", self.id, offset)
await col_users.update_one({"_id": self._id}, {"$set": {"offset": offset}}) await col_users.update_one({"_id": self._id}, {"$set": {"offset": offset}})
self.offset = offset
async def update_time(self, hour: int = 16, minute: int = 0) -> None: async def update_time(self, hour: int = 18, minute: int = 0) -> None:
logger.debug("%s's time has been set to %s h. %s m.", self.id, hour, minute) logger.debug("%s's time has been set to %s h. %s m.", self.id, hour, minute)
await col_users.update_one( await col_users.update_one(
{"_id": self._id}, {"$set": {"time_hour": hour, "time_minute": minute}} {"_id": self._id}, {"$set": {"time_hour": hour, "time_minute": minute}}
) )
self.time_hour = hour
self.time_minute = minute
async def delete(self) -> None: async def delete(self) -> None:
logger.debug("%s's data has been deleted", self.id) logger.debug("%s's data has been deleted", self.id)
@@ -132,60 +125,3 @@ class PyroUser:
del db_entry["_id"] # type: ignore del db_entry["_id"] # type: ignore
return db_entry return db_entry
def get_reminder_date(self) -> datetime:
"""Get next reminder date (year, month and day)
### Raises:
* `AttributeError`: Some attribute(s) are missing
### Returns:
* `datetime`: Datetime object of the next reminder date
"""
if self.location is None:
logger.warning(
"Could not get the reminder date for %s: User does not have some attribute(s) set",
self.id,
)
raise AttributeError(
f"Could not get the reminder date for {self.id}: User does not have some attribute(s) set"
)
if not self.location.timezone:
logger.warning("Location %s does not have a timezone set", self.location.id)
return (
datetime.now(self.location.timezone or timezone.utc) + timedelta(days=1)
).replace(hour=0, minute=0, second=0, microsecond=0)
def get_reminder_time(self) -> datetime:
"""Get reminder time (hour and minute)
### Raises:
* `AttributeError`: Some attribute(s) are missing
### Returns:
* `datetime`: Datetime object of the next reminder date
"""
if self.time_hour is None or self.time_minute is None or self.location is None:
logger.warning(
"Could not get the reminder time for %s: User does not have some attribute(s) set",
self.id,
)
raise AttributeError(
f"Could not get the reminder time for {self.id}: User does not have some attribute(s) set"
)
if not self.location.timezone:
logger.warning("Location %s does not have a timezone set", self.location.id)
return (
datetime.now(timezone.utc)
.replace(
hour=self.time_hour,
minute=self.time_minute,
second=0,
microsecond=0,
)
.astimezone(self.location.timezone or timezone.utc)
)

View File

@@ -9,6 +9,9 @@
"max_concurrent_transmissions": 1, "max_concurrent_transmissions": 1,
"scoped_commands": true "scoped_commands": true
}, },
"api": {
"url": "https://api.garbagebot.eu"
},
"database": { "database": {
"user": null, "user": null,
"password": null, "password": null,
@@ -16,13 +19,6 @@
"port": 27017, "port": 27017,
"name": "garbage_bot" "name": "garbage_bot"
}, },
"database_api": {
"user": null,
"password": null,
"host": "127.0.0.1",
"port": 27017,
"name": "garbage_reminder"
},
"search": { "search": {
"radius": 0.1 "radius": 0.1
}, },

View File

@@ -0,0 +1,21 @@
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

@@ -1,5 +1,5 @@
import logging import logging
from datetime import datetime, timezone from datetime import datetime, timedelta
from bson import json_util from bson import json_util
from libbot.pyrogram.classes import PyroClient from libbot.pyrogram.classes import PyroClient
@@ -9,12 +9,13 @@ from classes.location import Location
from classes.pyrouser import PyroUser from classes.pyrouser import PyroUser
from modules.database import col_users from modules.database import col_users
from modules.database_api import col_entries from modules.database_api import col_entries
from modules.utils import from_utc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
async def remind(app: PyroClient) -> None: async def remind(app: PyroClient) -> None:
utcnow = datetime.now(timezone.utc) utcnow = datetime.utcnow()
logger.debug("Performing reminder lookup for %s (UTCNOW)", utcnow) logger.debug("Performing reminder lookup for %s (UTCNOW)", utcnow)
@@ -39,16 +40,12 @@ async def remind(app: PyroClient) -> None:
try: try:
location: Location = await app.get_location(user.location.id) # type: ignore location: Location = await app.get_location(user.location.id) # type: ignore
except ValueError: except ValueError:
logger.warning("Skipping reminder for %s due to invalid location", user.id)
continue continue
try: user_date = from_utc(
user_date = user.get_reminder_date() datetime.utcnow() + timedelta(days=user.offset),
except AttributeError: user.location.timezone.zone,
logger.warning( ).replace(hour=0, minute=0, second=0, microsecond=0)
"Skipping reminder for %s due to missing attributes", user.id
)
continue
entries = await col_entries.find( entries = await col_entries.find(
{ {

View File

@@ -6,9 +6,7 @@ from pytz import timezone as pytz_timezone
def to_utc(date: datetime, timezone: Union[str, None] = None) -> datetime: def to_utc(date: datetime, timezone: Union[str, None] = None) -> datetime:
"""*DEPRECATED AND WILL BE REMOVED IN FUTURE RELEASES* """Move timezone unaware datetime object to UTC timezone and return it.
Move timezone unaware datetime object to UTC timezone and return it.
### Args: ### Args:
* date (`datetime`): Datetime to be converted. * date (`datetime`): Datetime to be converted.
@@ -22,9 +20,7 @@ def to_utc(date: datetime, timezone: Union[str, None] = None) -> datetime:
def from_utc(date: datetime, timezone: Union[str, None] = None) -> datetime: def from_utc(date: datetime, timezone: Union[str, None] = None) -> datetime:
"""*DEPRECATED AND WILL BE REMOVED IN FUTURE RELEASES* """Move timezone unaware datetime object to the timezone specified and return it.
Move timezone unaware datetime object to the timezone specified and return it.
### Args: ### Args:
* date (`datetime`): Datetime to be converted. * date (`datetime`): Datetime to be converted.

View File

@@ -1,5 +1,5 @@
import logging import logging
from datetime import datetime, timezone from datetime import datetime
from convopyro import listen_message from convopyro import listen_message
from pyrogram import filters from pyrogram import filters
@@ -7,6 +7,7 @@ from pyrogram.types import ForceReply, Message, ReplyKeyboardRemove
from classes.pyroclient import PyroClient from classes.pyroclient import PyroClient
from modules import custom_filters from modules import custom_filters
from modules.utils import from_utc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -64,19 +65,18 @@ async def command_set_offset(app: PyroClient, message: Message):
logger.info("User %s has set offset to %s", user.id, offset) logger.info("User %s has set offset to %s", user.id, offset)
garbage_time = ( garbage_time = from_utc(
datetime.now(timezone.utc) datetime(1970, 1, 1, user.time_hour, user.time_minute),
.replace(hour=user.time_hour, minute=user.time_minute) None if user.location is None else user.location.timezone.zone,
.astimezone(user.location.timezone or timezone.utc) ).strftime(app._("time", "formats"))
)
await answer.reply_text( await answer.reply_text(
app._("set_offset_finished", "messages", locale=user.locale).format( app._("set_offset_finished", "messages", locale=user.locale).format(
offset=offset, offset=offset,
time=garbage_time.strftime(app._("time", "formats", locale=user.locale)), time=garbage_time,
toggle_notice=( toggle_notice=""
"" if user.enabled else app._("toggle", "messages", locale=user.locale) if user.enabled
), else app._("toggle", "messages", locale=user.locale),
), ),
reply_markup=ReplyKeyboardRemove(), reply_markup=ReplyKeyboardRemove(),
) )

View File

@@ -1,5 +1,5 @@
import logging import logging
from datetime import datetime, timezone from datetime import datetime
from convopyro import listen_message from convopyro import listen_message
from pyrogram import filters from pyrogram import filters
@@ -7,6 +7,7 @@ from pyrogram.types import ForceReply, Message, ReplyKeyboardRemove
from classes.pyroclient import PyroClient from classes.pyroclient import PyroClient
from modules import custom_filters from modules import custom_filters
from modules.utils import to_utc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -57,34 +58,28 @@ async def command_set_time(app: PyroClient, message: Message):
now = datetime.now() now = datetime.now()
parsed_time = datetime.strptime(answer.text, "%H:%M").replace( parsed_time = datetime.strptime(answer.text, "%H:%M").replace(
year=now.year, year=now.year, month=now.month, day=now.day, second=0, microsecond=0
month=now.month,
day=now.day,
second=0,
microsecond=0,
tzinfo=timezone.utc,
) )
user_time = parsed_time.astimezone(user.location.timezone or timezone.utc) user_time = to_utc(parsed_time, user.location.timezone.zone)
await user.update_time(hour=user_time.hour, minute=user_time.minute) await user.update_time(hour=user_time.hour, minute=user_time.minute)
logger.info( logger.info(
"User %s has selected notification time of %s (%s UTC)", "User %s has selected notification time of %s",
user.id, user.id,
parsed_time.strftime("%H:%M"),
user_time.strftime("%H:%M"), user_time.strftime("%H:%M"),
) )
garbage_time = parsed_time.strftime(app._("time", "formats", locale=user.locale)) garbage_time = parsed_time.strftime(app._("time", "formats"))
await answer.reply_text( await answer.reply_text(
app._("set_time_finished", "messages", locale=user.locale).format( app._("set_time_finished", "messages", locale=user.locale).format(
offset=user.offset, offset=user.offset,
time=garbage_time, time=garbage_time,
toggle_notice=( toggle_notice=""
"" if user.enabled else app._("toggle", "messages", locale=user.locale) if user.enabled
), else app._("toggle", "messages", locale=user.locale),
), ),
reply_markup=ReplyKeyboardRemove(), reply_markup=ReplyKeyboardRemove(),
) )

View File

@@ -1,4 +1,5 @@
import logging import logging
from datetime import datetime
from convopyro import listen_message from convopyro import listen_message
from libbot import i18n from libbot import i18n
@@ -10,6 +11,7 @@ from classes.pyroclient import PyroClient
from modules import custom_filters from modules import custom_filters
from modules.search_name import search_name from modules.search_name import search_name
from modules.search_nearby import search_nearby from modules.search_nearby import search_nearby
from modules.utils import from_utc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -72,12 +74,10 @@ async def command_setup(app: PyroClient, message: Message):
await user.update_location(location.id) await user.update_location(location.id)
try: user_time = from_utc(
user_time = user.get_reminder_time().strftime( datetime(1970, 1, 1, user.time_hour, user.time_minute),
app._("time", "formats", locale=user.locale) None if user.location is None else user.location.timezone.zone,
) ).strftime(app._("time", "formats", locale=user.locale))
except AttributeError:
user_time = "N/A"
await message.reply_text( await message.reply_text(
app._("setup_finished", "messages", locale=user.locale).format( app._("setup_finished", "messages", locale=user.locale).format(

View File

@@ -1,3 +1,5 @@
from datetime import datetime
from convopyro import listen_message from convopyro import listen_message
from pyrogram import filters from pyrogram import filters
from pyrogram.types import ( from pyrogram.types import (
@@ -9,6 +11,7 @@ from pyrogram.types import (
from classes.pyroclient import PyroClient from classes.pyroclient import PyroClient
from modules import custom_filters from modules import custom_filters
from modules.utils import from_utc
@PyroClient.on_message( @PyroClient.on_message(
@@ -88,18 +91,13 @@ async def command_start(app: PyroClient, message: Message):
await user.update_location(location.id) await user.update_location(location.id)
try: user_time = from_utc(
user_time = user.get_reminder_time().strftime( datetime(1970, 1, 1, user.time_hour, user.time_minute),
app._("time", "formats", locale=user.locale) None if user.location is None else user.location.timezone.zone,
) ).strftime(app._("time", "formats", locale=user.locale))
except AttributeError:
user_time = "N/A"
await answer.reply_text( await answer.reply_text(
app._("start_selection_yes", "messages", locale=user.locale).format( app._("start_selection_yes", "messages", locale=user.locale).format(
name=location.name, name=location.name, offset=user.offset, time=user_time
offset=user.offset,
time=user_time,
), ),
reply_markup=ReplyKeyboardRemove(), reply_markup=ReplyKeyboardRemove(),
) )

View File

@@ -1,8 +1,11 @@
from datetime import datetime
from pyrogram import filters from pyrogram import filters
from pyrogram.types import Message from pyrogram.types import Message
from classes.pyroclient import PyroClient from classes.pyroclient import PyroClient
from modules import custom_filters from modules import custom_filters
from modules.utils import from_utc
@PyroClient.on_message( @PyroClient.on_message(
@@ -19,12 +22,10 @@ async def command_toggle(app: PyroClient, message: Message):
) )
return return
try: user_time = from_utc(
user_time = user.get_reminder_time().strftime( datetime(1970, 1, 1, user.time_hour, user.time_minute),
app._("time", "formats", locale=user.locale) None if user.location is None else user.location.timezone.zone,
) ).strftime(app._("time", "formats"))
except AttributeError:
user_time = "N/A"
if user.location is None: if user.location is None:
await message.reply_text( await message.reply_text(

View File

@@ -2,7 +2,6 @@ aiohttp~=3.9.5
apscheduler~=3.10.4 apscheduler~=3.10.4
convopyro==0.5 convopyro==0.5
mongodb-migrations==1.3.1 mongodb-migrations==1.3.1
pytz<=2023.2
tgcrypto==1.2.5 tgcrypto==1.2.5
ujson>=5.0.0 ujson>=5.0.0
uvloop==0.19.0 uvloop==0.19.0
@@ -10,3 +9,5 @@ uvloop==0.19.0
async_pymongo==0.1.4 async_pymongo==0.1.4
libbot[speed,pyrogram]==3.2.2 libbot[speed,pyrogram]==3.2.2
pykeyboard==0.1.7 pykeyboard==0.1.7
--extra-index-url https://git.end-play.xyz/api/packages/GarbageReminder/pypi/simple
garbageapi-client==0.1.0

View File

@@ -4,6 +4,6 @@
"enabled": true, "enabled": true,
"location": 1, "location": 1,
"offset": 1, "offset": 1,
"time_hour": 16, "time_hour": 18,
"time_minute": 0 "time_minute": 0
} }