Compare commits
1 Commits
i18n
...
41bd849dc6
Author | SHA1 | Date | |
---|---|---|---|
41bd849dc6 |
@@ -1,20 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
|
|
||||||
class Importer(ABC):
|
|
||||||
"""
|
|
||||||
The Importer class represents the object with
|
|
||||||
functionality to import/export garbage collection
|
|
||||||
records and convert them to other object types.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def import_data(self, data: Any) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def export_data(self, data: Any) -> None:
|
|
||||||
pass
|
|
@@ -1,64 +0,0 @@
|
|||||||
from codecs import decode
|
|
||||||
from csv import DictReader
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Any, Dict, List, Union
|
|
||||||
|
|
||||||
from bson import ObjectId
|
|
||||||
|
|
||||||
from classes.importer.abstract import Importer
|
|
||||||
from modules.database import col_entries
|
|
||||||
|
|
||||||
|
|
||||||
class ImporterCSV(Importer):
|
|
||||||
"""
|
|
||||||
The ImporterCSV class represents the object with
|
|
||||||
functionality to import/export garbage collection
|
|
||||||
records and convert them to other object types
|
|
||||||
from CSV files.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(Importer, self).__init__()
|
|
||||||
|
|
||||||
async def import_data(self, data: bytes) -> List[ObjectId]:
|
|
||||||
entries: List[Dict[str, Any]] = list(
|
|
||||||
DictReader(decode(data).split("\n"), delimiter=";")
|
|
||||||
)
|
|
||||||
|
|
||||||
for entry in entries:
|
|
||||||
entry["locations"] = (
|
|
||||||
[int(entry["locations"])]
|
|
||||||
if "," not in entry["locations"]
|
|
||||||
else [int(id) for id in entry["locations"].split(",")]
|
|
||||||
)
|
|
||||||
entry["garbage_type"] = int(entry["garbage_type"])
|
|
||||||
|
|
||||||
for key in ("locations", "garbage_type", "date"):
|
|
||||||
if (
|
|
||||||
key not in entry
|
|
||||||
or (key == "garbage_type" and not isinstance(entry[key], int))
|
|
||||||
or (key == "locations" and not isinstance(entry[key], list))
|
|
||||||
):
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
if key == "date":
|
|
||||||
try:
|
|
||||||
datetime.fromisoformat(str(entry[key]))
|
|
||||||
except (ValueError, TypeError) as exc:
|
|
||||||
raise ValueError from exc
|
|
||||||
|
|
||||||
entries_clean: List[Dict[str, Union[str, int, datetime]]] = [
|
|
||||||
{
|
|
||||||
"locations": entry["locations"],
|
|
||||||
"garbage_type": entry["garbage_type"],
|
|
||||||
"date": datetime.fromisoformat(str(entry["date"])),
|
|
||||||
}
|
|
||||||
for entry in entries
|
|
||||||
]
|
|
||||||
|
|
||||||
inserted = await col_entries.insert_many(entries_clean)
|
|
||||||
|
|
||||||
return [] if inserted is None else inserted.inserted_ids
|
|
||||||
|
|
||||||
async def export_data(self, data: Any) -> Any:
|
|
||||||
return None
|
|
@@ -1,56 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
from typing import Any, Dict, List, Union
|
|
||||||
|
|
||||||
from bson import ObjectId
|
|
||||||
from ujson import loads
|
|
||||||
|
|
||||||
from classes.importer.abstract import Importer
|
|
||||||
from modules.database import col_entries
|
|
||||||
|
|
||||||
|
|
||||||
class ImporterJSON(Importer):
|
|
||||||
"""
|
|
||||||
The ImporterJSON class represents the object with
|
|
||||||
functionality to import/export garbage collection
|
|
||||||
records and convert them to other object types
|
|
||||||
from JSON files.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(Importer, self).__init__()
|
|
||||||
|
|
||||||
async def import_data(self, data: bytes) -> List[ObjectId]:
|
|
||||||
entries: List[Dict[str, Any]] = loads(data)
|
|
||||||
|
|
||||||
for entry in entries:
|
|
||||||
for key in ("locations", "garbage_type", "date"):
|
|
||||||
if (
|
|
||||||
key not in entry
|
|
||||||
or (key == "garbage_type" and not isinstance(entry[key], int))
|
|
||||||
or (key == "locations" and not isinstance(entry[key], list))
|
|
||||||
):
|
|
||||||
print("keys", entry)
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
if key == "date":
|
|
||||||
try:
|
|
||||||
datetime.fromisoformat(str(entry[key]))
|
|
||||||
except (ValueError, TypeError) as exc:
|
|
||||||
print("date", entry)
|
|
||||||
raise ValueError from exc
|
|
||||||
|
|
||||||
entries_clean: List[Dict[str, Union[str, int, datetime]]] = [
|
|
||||||
{
|
|
||||||
"locations": entry["locations"],
|
|
||||||
"garbage_type": entry["garbage_type"],
|
|
||||||
"date": datetime.fromisoformat(str(entry["date"])),
|
|
||||||
}
|
|
||||||
for entry in entries
|
|
||||||
]
|
|
||||||
|
|
||||||
inserted = await col_entries.insert_many(entries_clean)
|
|
||||||
|
|
||||||
return [] if inserted is None else inserted.inserted_ids
|
|
||||||
|
|
||||||
async def export_data(self, data: Any) -> Any:
|
|
||||||
return None
|
|
@@ -42,9 +42,9 @@
|
|||||||
"help": "🔔 Dieser Bot sendet Ihnen Benachrichtigungen über die Müllabfuhr nach Ihrem lokalen Zeitplan.\n\n**Verfügbare Kommandos**\n/help - Diese Menü anzeigen\n/setup - Standort wählen\n/toggle - Deaktivieren/Aktivieren der Benachrichtigungen\n/set_time - Einstellen der Erinnerungszeit\n/set_offset - Offset zwischen Erinnerung und Abholung einstellen\n/upcoming - Zeigt die nächste Abholung an\n/language - Die Sprache des Bots wählen\n/checkout - Daten exportieren oder löschen\n\n💭 Sie können auch vorschlagen, Ihre Stadt/Ihren Bezirk in den Bot aufzunehmen, indem Sie die Administratoren über [diesen Link]({url_contact}) kontaktieren und Ihren Zeitplan angeben.\n\n⚙️ Möchten Sie diesen Bot selbst hosten oder Änderungen vornehmen? Er ist Open-Source, Sie können ihn also forken. Werfen Sie einen Blick auf das [Bot-Repository]({url_repo}) für Details.\n\nViel Spaß beim Benutzen! 🤗",
|
"help": "🔔 Dieser Bot sendet Ihnen Benachrichtigungen über die Müllabfuhr nach Ihrem lokalen Zeitplan.\n\n**Verfügbare Kommandos**\n/help - Diese Menü anzeigen\n/setup - Standort wählen\n/toggle - Deaktivieren/Aktivieren der Benachrichtigungen\n/set_time - Einstellen der Erinnerungszeit\n/set_offset - Offset zwischen Erinnerung und Abholung einstellen\n/upcoming - Zeigt die nächste Abholung an\n/language - Die Sprache des Bots wählen\n/checkout - Daten exportieren oder löschen\n\n💭 Sie können auch vorschlagen, Ihre Stadt/Ihren Bezirk in den Bot aufzunehmen, indem Sie die Administratoren über [diesen Link]({url_contact}) kontaktieren und Ihren Zeitplan angeben.\n\n⚙️ Möchten Sie diesen Bot selbst hosten oder Änderungen vornehmen? Er ist Open-Source, Sie können ihn also forken. Werfen Sie einen Blick auf das [Bot-Repository]({url_repo}) für Details.\n\nViel Spaß beim Benutzen! 🤗",
|
||||||
"import_finished": "Sie haben erfolgreich {count} Einträge eingefügt.",
|
"import_finished": "Sie haben erfolgreich {count} Einträge eingefügt.",
|
||||||
"import_invalid_date": "Die Einträge enthalten ungültige Datumsformate. Verwenden Sie das Datumsformat **ISO 8601**.",
|
"import_invalid_date": "Die Einträge enthalten ungültige Datumsformate. Verwenden Sie das Datumsformat **ISO 8601**.",
|
||||||
"import_invalid_filetype": "Ungültige Eingabe. Bitte senden Sie mir eine JSON- oder CSV-Datei mit Einträgen. {cancel_notice}",
|
"import_invalid_filetype": "Ungültige Eingabe. Bitte senden Sie mir eine JSON-Datei mit Einträgen. {cancel_notice}",
|
||||||
"import_invalid": "Dies ist keine gültige Abfalltermine-Datei.",
|
"import_invalid": "Dies ist kein gültiges Abfallterminen JSON.",
|
||||||
"import": "Okay. Senden Sie mir eine gültige Datei. Sie kann im JSON- oder CSV-Format sein. Lesen Sie mehr über die unterstützten Formate in der Dokumentation",
|
"import": "Okay. Senden Sie mir ein gültiges JSON.",
|
||||||
"locale_choice": "Prima. Bitte wählen Sie die Sprache mit der Tastatur unten.",
|
"locale_choice": "Prima. Bitte wählen Sie die Sprache mit der Tastatur unten.",
|
||||||
"location_empty": "Sie haben keinen Standort festgelegt. Verwenden Sie /setup, um Ihren Standort auszuwählen.",
|
"location_empty": "Sie haben keinen Standort festgelegt. Verwenden Sie /setup, um Ihren Standort auszuwählen.",
|
||||||
"location_name_empty": "Es konnten keine Orte mit diesem Namen gefunden werden. Versuchen Sie, ihn umzuformulieren, oder stellen Sie sicher, dass Sie dieselbe Sprache und denselben Namen verwenden, wie er von Ihren örtlichen Behörden im Müllabfuhrplan angegeben ist.\n\n{cancel_notice}",
|
"location_name_empty": "Es konnten keine Orte mit diesem Namen gefunden werden. Versuchen Sie, ihn umzuformulieren, oder stellen Sie sicher, dass Sie dieselbe Sprache und denselben Namen verwenden, wie er von Ihren örtlichen Behörden im Müllabfuhrplan angegeben ist.\n\n{cancel_notice}",
|
||||||
|
@@ -42,9 +42,9 @@
|
|||||||
"help": "🔔 This bot sends you notifications about garbage collection according to your local schedule.\n\n**Available commands**\n/help - Show this message\n/setup - Select the location\n/toggle - Disable/enable the reminders\n/set_time - Set the reminders' time\n/set_offset - Set offset between reminders and collection\n/upcoming - Show the upcoming collection\n/language - Select the bot's language\n/checkout - Export or remove your data\n\n💭 You can also suggest adding your town/district to the bot by contacting the admins using [this link]({url_contact}) and providing your schedule.\n\n⚙️ Want to host this bot yourself or make some changes? It's open-source, so you can basically fork it. Take a look at [bot's repository]({url_repo}) for details.\n\nHappy using! 🤗",
|
"help": "🔔 This bot sends you notifications about garbage collection according to your local schedule.\n\n**Available commands**\n/help - Show this message\n/setup - Select the location\n/toggle - Disable/enable the reminders\n/set_time - Set the reminders' time\n/set_offset - Set offset between reminders and collection\n/upcoming - Show the upcoming collection\n/language - Select the bot's language\n/checkout - Export or remove your data\n\n💭 You can also suggest adding your town/district to the bot by contacting the admins using [this link]({url_contact}) and providing your schedule.\n\n⚙️ Want to host this bot yourself or make some changes? It's open-source, so you can basically fork it. Take a look at [bot's repository]({url_repo}) for details.\n\nHappy using! 🤗",
|
||||||
"import_finished": "You have successfully inserted {count} entries.",
|
"import_finished": "You have successfully inserted {count} entries.",
|
||||||
"import_invalid_date": "Entries contain invalid date formats. Use **ISO 8601** date format.",
|
"import_invalid_date": "Entries contain invalid date formats. Use **ISO 8601** date format.",
|
||||||
"import_invalid_filetype": "Invalid input. Please, send me a JSON or CSV file with entries. {cancel_notice}",
|
"import_invalid_filetype": "Invalid input. Please, send me a JSON file with entries. {cancel_notice}",
|
||||||
"import_invalid": "This is not a valid garbage collection file.",
|
"import_invalid": "This is not a valid garbage collection JSON.",
|
||||||
"import": "Alright. Send me a valid file. It can be in JSON or CSV format. Read more about supported formats in the documentation",
|
"import": "Alright. Send me a valid JSON.",
|
||||||
"locale_choice": "Alright. Please choose the language using keyboard below.",
|
"locale_choice": "Alright. Please choose the language using keyboard below.",
|
||||||
"location_empty": "You have no location set. Use /setup to select your location first.",
|
"location_empty": "You have no location set. Use /setup to select your location first.",
|
||||||
"location_name_empty": "Could not find any locations by this name. Try rephrasing it or make sure you use the same location language and name itself as it in written by your local authorities in garbage collection schedule.\n\n{cancel_notice}",
|
"location_name_empty": "Could not find any locations by this name. Try rephrasing it or make sure you use the same location language and name itself as it in written by your local authorities in garbage collection schedule.\n\n{cancel_notice}",
|
||||||
|
@@ -18,9 +18,9 @@
|
|||||||
"help": "🔔 Цей бот надсилає сповіщення про вивезення сміття згідно з Вашим місцевим графіком.\n\n**Доступні команди**\n/help - Показати це повідомлення\n/setup - Вибрати місце розташування\n/toggle - Увімкнути/вимкнути нагадування\n/set_time - Встановити час нагадувань\n/set_offset - Встановити зсув між нагадуваннями та вивозом\n/upcoming - Показати майбутні вивезення\n/language - Обрати мову бота\n/checkout - Експортувати або видалити дані\n\nВи також можете запропонувати додати своє місто/район до бота, зв'язавшись з адміністраторами за [цим посиланням]({url_contact}) та вказавши свій розклад.\n\n⚙️ Бажаєте розмістити цього бота самостійно або внести деякі зміни? Бот має відкритий вихідний код, тож ви можете форкнути його. Ознайомтесь із [репозиторієм бота]({url_repo}) щоб дізнатись деталі.\n\nПриємного користування! 🤗",
|
"help": "🔔 Цей бот надсилає сповіщення про вивезення сміття згідно з Вашим місцевим графіком.\n\n**Доступні команди**\n/help - Показати це повідомлення\n/setup - Вибрати місце розташування\n/toggle - Увімкнути/вимкнути нагадування\n/set_time - Встановити час нагадувань\n/set_offset - Встановити зсув між нагадуваннями та вивозом\n/upcoming - Показати майбутні вивезення\n/language - Обрати мову бота\n/checkout - Експортувати або видалити дані\n\nВи також можете запропонувати додати своє місто/район до бота, зв'язавшись з адміністраторами за [цим посиланням]({url_contact}) та вказавши свій розклад.\n\n⚙️ Бажаєте розмістити цього бота самостійно або внести деякі зміни? Бот має відкритий вихідний код, тож ви можете форкнути його. Ознайомтесь із [репозиторієм бота]({url_repo}) щоб дізнатись деталі.\n\nПриємного користування! 🤗",
|
||||||
"import_finished": "Ви успішно вставили {count} записів.",
|
"import_finished": "Ви успішно вставили {count} записів.",
|
||||||
"import_invalid_date": "Записи містять невірні формати дат. Використовуйте формат дати **ISO 8601**.",
|
"import_invalid_date": "Записи містять невірні формати дат. Використовуйте формат дати **ISO 8601**.",
|
||||||
"import_invalid_filetype": "Неправильний ввід. Будь ласка, надішліть мені JSON або CSV файл із записами. {cancel_notice}",
|
"import_invalid_filetype": "Неправильний ввід. Будь ласка, надішліть мені JSON-файл із записами. {cancel_notice}",
|
||||||
"import_invalid": "Це недійсний файл з даними про збір сміття.",
|
"import_invalid": "Це недійсний JSON даних збору сміття.",
|
||||||
"import": "Гаразд. Надішліть мені правильний файл. Він може бути у форматі JSON або CSV. Дізнайтеся більше про підтримувані формати в документації",
|
"import": "Гаразд. Надішліть правильний JSON.",
|
||||||
"locale_choice": "Гаразд. Будь ласка, оберіть мову за допомогою клавіатури нижче.",
|
"locale_choice": "Гаразд. Будь ласка, оберіть мову за допомогою клавіатури нижче.",
|
||||||
"location_empty": "У Вас не встановлено локацію вивозу. Оберіть свою локацію за допомогою /setup.",
|
"location_empty": "У Вас не встановлено локацію вивозу. Оберіть свою локацію за допомогою /setup.",
|
||||||
"location_name_empty": "Не вдалося знайти жодного населеного пункту з такою назвою. Спробуйте перефразувати назву або переконайтеся, що Ви використовуєте ту саму мову та назву, що й місцева влада у графіку вивезення сміття.\n\n{cancel_notice}",
|
"location_name_empty": "Не вдалося знайти жодного населеного пункту з такою назвою. Спробуйте перефразувати назву або переконайтеся, що Ви використовуєте ту саму мову та назву, що й місцева влада у графіку вивезення сміття.\n\n{cancel_notice}",
|
||||||
|
@@ -42,9 +42,9 @@
|
|||||||
"help": "🔔 Цей бот надсилає сповіщення про вивезення сміття згідно з Вашим місцевим графіком.\n\n**Доступні команди**\n/help - Показати це повідомлення\n/setup - Вибрати місце розташування\n/toggle - Увімкнути/вимкнути нагадування\n/set_time - Встановити час нагадувань\n/set_offset - Встановити зсув між нагадуваннями та вивозом\n/upcoming - Показати майбутні вивезення\n/language - Обрати мову бота\n/checkout - Експортувати або видалити дані\n\nВи також можете запропонувати додати своє місто/район до бота, зв'язавшись з адміністраторами за [цим посиланням]({url_contact}) та вказавши свій розклад.\n\n⚙️ Бажаєте розмістити цього бота самостійно або внести деякі зміни? Бот має відкритий вихідний код, тож ви можете форкнути його. Ознайомтесь із [репозиторієм бота]({url_repo}) щоб дізнатись деталі.\n\nПриємного користування! 🤗",
|
"help": "🔔 Цей бот надсилає сповіщення про вивезення сміття згідно з Вашим місцевим графіком.\n\n**Доступні команди**\n/help - Показати це повідомлення\n/setup - Вибрати місце розташування\n/toggle - Увімкнути/вимкнути нагадування\n/set_time - Встановити час нагадувань\n/set_offset - Встановити зсув між нагадуваннями та вивозом\n/upcoming - Показати майбутні вивезення\n/language - Обрати мову бота\n/checkout - Експортувати або видалити дані\n\nВи також можете запропонувати додати своє місто/район до бота, зв'язавшись з адміністраторами за [цим посиланням]({url_contact}) та вказавши свій розклад.\n\n⚙️ Бажаєте розмістити цього бота самостійно або внести деякі зміни? Бот має відкритий вихідний код, тож ви можете форкнути його. Ознайомтесь із [репозиторієм бота]({url_repo}) щоб дізнатись деталі.\n\nПриємного користування! 🤗",
|
||||||
"import_finished": "Ви успішно вставили {count} записів.",
|
"import_finished": "Ви успішно вставили {count} записів.",
|
||||||
"import_invalid_date": "Записи містять невірні формати дат. Використовуйте формат дати **ISO 8601**.",
|
"import_invalid_date": "Записи містять невірні формати дат. Використовуйте формат дати **ISO 8601**.",
|
||||||
"import_invalid_filetype": "Неправильний ввід. Будь ласка, надішліть мені JSON або CSV файл із записами. {cancel_notice}",
|
"import_invalid_filetype": "Неправильний ввід. Будь ласка, надішліть мені JSON-файл із записами. {cancel_notice}",
|
||||||
"import_invalid": "Це недійсний файл з даними про збір сміття.",
|
"import_invalid": "Це недійсний JSON даних збору сміття.",
|
||||||
"import": "Гаразд. Надішліть мені правильний файл. Він може бути у форматі JSON або CSV. Дізнайтеся більше про підтримувані формати в документації",
|
"import": "Гаразд. Надішліть правильний JSON.",
|
||||||
"locale_choice": "Гаразд. Будь ласка, оберіть мову за допомогою клавіатури нижче.",
|
"locale_choice": "Гаразд. Будь ласка, оберіть мову за допомогою клавіатури нижче.",
|
||||||
"location_empty": "У Вас не встановлено локацію вивозу. Оберіть свою локацію за допомогою /setup.",
|
"location_empty": "У Вас не встановлено локацію вивозу. Оберіть свою локацію за допомогою /setup.",
|
||||||
"location_name_empty": "Не вдалося знайти жодного населеного пункту з такою назвою. Спробуйте перефразувати назву або переконайтеся, що Ви використовуєте ту саму мову та назву, що й місцева влада у графіку вивезення сміття.\n\n{cancel_notice}",
|
"location_name_empty": "Не вдалося знайти жодного населеного пункту з такою назвою. Спробуйте перефразувати назву або переконайтеся, що Ви використовуєте ту саму мову та назву, що й місцева влада у графіку вивезення сміття.\n\n{cancel_notice}",
|
||||||
|
@@ -1,26 +1,33 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from typing import List, Mapping, Union
|
||||||
|
|
||||||
from convopyro import listen_message
|
from convopyro import listen_message
|
||||||
from pyrogram import filters
|
from pyrogram import filters
|
||||||
from pyrogram.types import ForceReply, Message, ReplyKeyboardRemove
|
from pyrogram.types import ForceReply, Message, ReplyKeyboardRemove
|
||||||
|
from ujson import loads
|
||||||
|
|
||||||
from classes.importer.csv import ImporterCSV
|
|
||||||
from classes.importer.json import ImporterJSON
|
|
||||||
from classes.pyroclient import PyroClient
|
from classes.pyroclient import PyroClient
|
||||||
from modules import custom_filters
|
from modules import custom_filters
|
||||||
|
from modules.database import col_entries
|
||||||
|
|
||||||
|
|
||||||
@PyroClient.on_message(
|
@PyroClient.on_message(
|
||||||
~filters.scheduled & filters.private & custom_filters.owner & filters.command(["import"], prefixes=["/"]) # type: ignore
|
~filters.scheduled & filters.private & custom_filters.owner & filters.command(["import"], prefixes=["/"]) & ~custom_filters.context # type: ignore
|
||||||
)
|
)
|
||||||
async def command_import(app: PyroClient, message: Message):
|
async def command_import(app: PyroClient, message: Message):
|
||||||
user = await app.find_user(message.from_user)
|
user = await app.find_user(message.from_user)
|
||||||
|
|
||||||
await message.reply_text(
|
await message.reply_text(
|
||||||
app._("import", "messages", locale=user.locale),
|
app._("import", "messages", locale=user.locale),
|
||||||
reply_markup=ForceReply(placeholder=""),
|
reply_markup=ForceReply(
|
||||||
|
placeholder=app._("import", "force_replies", locale=user.locale)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
app.contexts.append(message.from_user.id)
|
||||||
answer = await listen_message(app, message.chat.id, 300)
|
answer = await listen_message(app, message.chat.id, 300)
|
||||||
|
app.contexts.remove(message.from_user.id)
|
||||||
|
|
||||||
if answer is None or answer.text == "/cancel":
|
if answer is None or answer.text == "/cancel":
|
||||||
await message.reply_text(
|
await message.reply_text(
|
||||||
@@ -29,10 +36,7 @@ async def command_import(app: PyroClient, message: Message):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
if answer.document is None or answer.document.mime_type not in [
|
if answer.document is None or answer.document.mime_type != "application/json":
|
||||||
"application/json",
|
|
||||||
"text/csv",
|
|
||||||
]:
|
|
||||||
await answer.reply_text(
|
await answer.reply_text(
|
||||||
app._("import_invalid_filetype", "messages", locale=user.locale).format(
|
app._("import_invalid_filetype", "messages", locale=user.locale).format(
|
||||||
cancel_notice=app._("cancel", "messages", locale=user.locale)
|
cancel_notice=app._("cancel", "messages", locale=user.locale)
|
||||||
@@ -44,36 +48,51 @@ async def command_import(app: PyroClient, message: Message):
|
|||||||
|
|
||||||
file = await app.download_media(answer, in_memory=True)
|
file = await app.download_media(answer, in_memory=True)
|
||||||
|
|
||||||
data: bytes = bytes(file.getbuffer()) # type: ignore
|
entries: List[Mapping[str, Union[str, int]]] = loads(bytes(file.getbuffer())) # type: ignore
|
||||||
|
|
||||||
# I'd like to replace it with switch-case, but 3.9 compatibility
|
for entry in entries:
|
||||||
# is still more important to be there. Although refactor may be
|
if not isinstance(entries, list):
|
||||||
# done in the near future as Python 3.9 EOL gets nearer.
|
await answer.reply_text(
|
||||||
if answer.document.mime_type == "application/json":
|
app._("import_invalid", "messages", locale=user.locale),
|
||||||
importer = ImporterJSON()
|
reply_markup=ReplyKeyboardRemove(),
|
||||||
elif answer.document.mime_type == "text/csv":
|
)
|
||||||
importer = ImporterCSV()
|
return
|
||||||
else:
|
|
||||||
await answer.reply_text(
|
|
||||||
app._("import_invalid_filetype", "messages", locale=user.locale).format(
|
|
||||||
cancel_notice=""
|
|
||||||
),
|
|
||||||
reply_markup=ReplyKeyboardRemove(),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
for key in ("locations", "garbage_type", "date"):
|
||||||
import_result = await importer.import_data(data)
|
if (
|
||||||
except ValueError:
|
key not in entry
|
||||||
await answer.reply_text(
|
or (key == "garbage_type" and not isinstance(entry[key], int))
|
||||||
app._("import_invalid", "messages", locale=user.locale),
|
or (key == "locations" and not isinstance(entry[key], list))
|
||||||
reply_markup=ReplyKeyboardRemove(),
|
):
|
||||||
)
|
await answer.reply_text(
|
||||||
return
|
app._("import_invalid", "messages", locale=user.locale),
|
||||||
|
reply_markup=ReplyKeyboardRemove(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if key == "date":
|
||||||
|
try:
|
||||||
|
datetime.fromisoformat(str(entry[key]))
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
await answer.reply_text(
|
||||||
|
app._("import_invalid_date", "messages", locale=user.locale),
|
||||||
|
reply_markup=ReplyKeyboardRemove(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
entries_clean: List[Mapping[str, Union[str, int, datetime]]] = [
|
||||||
|
{
|
||||||
|
"locations": entry["locations"],
|
||||||
|
"garbage_type": entry["garbage_type"],
|
||||||
|
"date": datetime.fromisoformat(str(entry["date"])),
|
||||||
|
}
|
||||||
|
for entry in entries
|
||||||
|
]
|
||||||
|
|
||||||
|
await col_entries.insert_many(entries_clean)
|
||||||
|
|
||||||
await answer.reply_text(
|
await answer.reply_text(
|
||||||
app._("import_finished", "messages", locale=user.locale).format(
|
app._("import_finished", "messages", locale=user.locale).format(
|
||||||
count=len(import_result)
|
count=len(entries_clean)
|
||||||
),
|
),
|
||||||
reply_markup=ReplyKeyboardRemove(),
|
reply_markup=ReplyKeyboardRemove(),
|
||||||
)
|
)
|
||||||
|
@@ -5,7 +5,7 @@ mongodb-migrations==1.3.0
|
|||||||
pykeyboard==0.1.5
|
pykeyboard==0.1.5
|
||||||
tgcrypto==1.2.5
|
tgcrypto==1.2.5
|
||||||
ujson>=5.0.0
|
ujson>=5.0.0
|
||||||
uvloop==0.19.0
|
uvloop==0.18.0
|
||||||
--extra-index-url https://git.end-play.xyz/api/packages/profitroll/pypi/simple
|
--extra-index-url https://git.end-play.xyz/api/packages/profitroll/pypi/simple
|
||||||
async_pymongo==0.1.4
|
async_pymongo==0.1.4
|
||||||
libbot[speed,pyrogram]==2.0.1
|
libbot[speed,pyrogram]==40
|
Reference in New Issue
Block a user