4 Commits

14 changed files with 138 additions and 102 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

@@ -8,7 +8,6 @@ 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
@@ -26,7 +25,6 @@ class PyroClient(LibPyroClient):
self.updater = Updater(ClientSession())
self.contexts = []
self.api_client = APIClient()
if self.scheduler is not None:
self.scheduler.add_job(

View File

@@ -1,5 +1,6 @@
import logging
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from typing import Any, Union
from bson import ObjectId
@@ -42,7 +43,7 @@ class PyroUser:
enabled: bool = True,
location_id: int = 0,
offset: int = 1,
time_hour: int = 18,
time_hour: int = 16,
time_minute: int = 0,
):
db_entry = await col_users.find_one({"id": id})
@@ -88,26 +89,32 @@ class PyroUser:
"""
logger.debug("%s's locale has been set to %s", self.id, locale)
await col_users.update_one({"_id": self._id}, {"$set": {"locale": locale}})
self.locale = locale
async def update_state(self, enabled: bool = False) -> None:
logger.debug("%s's state has been set to %s", self.id, 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:
logger.debug("%s's location has been set to %s", self.id, location_id)
await col_users.update_one(
{"_id": self._id}, {"$set": {"location": location_id}}
)
self.location = await Location.get(location_id)
async def update_offset(self, offset: int = 1) -> None:
logger.debug("%s's offset has been set to %s", self.id, offset)
await col_users.update_one({"_id": self._id}, {"$set": {"offset": offset}})
self.offset = offset
async def update_time(self, hour: int = 18, minute: int = 0) -> None:
async def update_time(self, hour: int = 16, minute: int = 0) -> None:
logger.debug("%s's time has been set to %s h. %s m.", self.id, hour, minute)
await col_users.update_one(
{"_id": self._id}, {"$set": {"time_hour": hour, "time_minute": minute}}
)
self.time_hour = hour
self.time_minute = minute
async def delete(self) -> None:
logger.debug("%s's data has been deleted", self.id)
@@ -125,3 +132,60 @@ class PyroUser:
del db_entry["_id"] # type: ignore
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,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
},

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ aiohttp~=3.9.5
apscheduler~=3.10.4
convopyro==0.5
mongodb-migrations==1.3.1
pytz<=2023.2
tgcrypto==1.2.5
ujson>=5.0.0
uvloop==0.19.0
@@ -9,5 +10,3 @@ uvloop==0.19.0
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

View File

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