diff --git a/.run/Run greed.run.xml b/.run/Run greed.run.xml
index 26a964f..963e58e 100644
--- a/.run/Run greed.run.xml
+++ b/.run/Run greed.run.xml
@@ -1,24 +1,24 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/template_config.toml b/config/template_config.toml
index fc7c0b0..89b599c 100644
--- a/config/template_config.toml
+++ b/config/template_config.toml
@@ -2,99 +2,99 @@
# Language parameters
[Language]
- # Available languages:
- # it - Italian, by https://github.com/Steffo99
- # en - English, by https://github.com/DarrenWestwood
- # uk - Ukrainian, by https://github.com/pzhuk
- # ru - Russian, by https://github.com/pzhuk
- # zh_cn - Simplified Chinese, by https://github.com/zhihuiyuze
- # he - Hebrew, by https://github.com/netanelkoli
- # The lanugages that messages can be displayed in
- enabled_languages = ["it", "en", "uk", "ru", "zh_cn", "he"]
- # The default language to be set for users whose language cannot be autodetected or whose language is not enabled
- default_language = "it"
- # The language to fallback to if a string is missing in a specific language
- fallback_language = "en"
+# Available languages:
+# it - Italian, by https://github.com/Steffo99
+# en - English, by https://github.com/DarrenWestwood
+# uk - Ukrainian, by https://github.com/pzhuk
+# ru - Russian, by https://github.com/pzhuk
+# zh_cn - Simplified Chinese, by https://github.com/zhihuiyuze
+# he - Hebrew, by https://github.com/netanelkoli
+# The lanugages that messages can be displayed in
+enabled_languages = ["it", "en", "uk", "ru", "zh_cn", "he"]
+# The default language to be set for users whose language cannot be autodetected or whose language is not enabled
+default_language = "it"
+# The language to fallback to if a string is missing in a specific language
+fallback_language = "en"
# Database parameters
[Database]
- # The database engine you want to use.
- # Refer to http://docs.sqlalchemy.org/en/latest/core/engines.html for the possible settings.
- engine = "sqlite:///database.sqlite"
+# The database engine you want to use.
+# Refer to http://docs.sqlalchemy.org/en/latest/core/engines.html for the possible settings.
+engine = "sqlite:///database.sqlite"
# Telegram bot parameters
[Telegram]
- # Your bot token goes here. Get one from https://t.me/BotFather!
- token = "123456789:YOUR_TOKEN_GOES_HERE_______________"
- # Time in seconds before a conversation (thread) with no new messages expires
- # A lower value reduces memory usage, but can be inconvenient for the users
- conversation_timeout = 7200
- # Time to wait before sending another update request if there are no messages
- long_polling_timeout = 30
- # Time in seconds before retrying a request if it times out
- timed_out_pause = 1
- # Time in seconds before retrying a request that returned an error
- error_pause = 5
+# Your bot token goes here. Get one from https://t.me/BotFather!
+token = "123456789:YOUR_TOKEN_GOES_HERE_______________"
+# Time in seconds before a conversation (thread) with no new messages expires
+# A lower value reduces memory usage, but can be inconvenient for the users
+conversation_timeout = 7200
+# Time to wait before sending another update request if there are no messages
+long_polling_timeout = 30
+# Time in seconds before retrying a request if it times out
+timed_out_pause = 1
+# Time in seconds before retrying a request that returned an error
+error_pause = 5
# General payment settings
[Payments]
- # ISO currency code
- currency = "EUR"
- # Currency exp parameter. You can find that on https://core.telegram.org/bots/payments/currencies.json.
- # It has a value of 2 in most currencies (EUR, USD, GBP...)
- currency_exp = 2
- # Currency symbol which is show to the client users when displaying prices and transaction values
- # If not defined here, default language specific currency symbol from strings would be used
- currency_symbol = "€"
+# ISO currency code
+currency = "EUR"
+# Currency exp parameter. You can find that on https://core.telegram.org/bots/payments/currencies.json.
+# It has a value of 2 in most currencies (EUR, USD, GBP...)
+currency_exp = 2
+# Currency symbol which is show to the client users when displaying prices and transaction values
+# If not defined here, default language specific currency symbol from strings would be used
+currency_symbol = "€"
- # Credit card payment settings
- [Payments.CreditCard]
- # Telegram Payments provider token obtainable at https://t.me/BotFather in the bot's Payments menu
- # If empty, credit card payments are disabled.
- # credit_card_token =
- credit_card_token = "123456789:YOUR_TOKEN_HERE_"
- # Minimum wallet payment accepted (in miniumum currency units, $1.00 = 100 units)
- min_amount = 1000
- # Maximum wallet payment accepted (in miniumum currency units, $1.00 = 100 units)
- max_amount = 10000
- # The preset selections that can be made when adding credit to the wallet with a credit card
- # Presets are pipe-separated |, and should never be outside the bounds provided by the min_amount and max_amount options
- payment_presets = [10.00, 25.00, 50.00, 100.00]
- # Make the user pay a extra fee when adding credit to the wallet with a credit card
- # The formula for determining the total cost is:
- # cost = added_funds + added_funds * fee_percentage / 100 + fee_fixed
- # Set these values to 0 to disable the feature.
- fee_percentage = 2.9
- fee_fixed = 30
- # "Shipping" information
- # Telegram can ask for extra information when charging the user for a credit card transaction
- # Set to yes the data you want to be required
- # This data will be stored in the database
- name_required = true
- email_required = true
- phone_required = true
+# Credit card payment settings
+[Payments.CreditCard]
+# Telegram Payments provider token obtainable at https://t.me/BotFather in the bot's Payments menu
+# If empty, credit card payments are disabled.
+# credit_card_token =
+credit_card_token = "123456789:YOUR_TOKEN_HERE_"
+# Minimum wallet payment accepted (in miniumum currency units, $1.00 = 100 units)
+min_amount = 1000
+# Maximum wallet payment accepted (in miniumum currency units, $1.00 = 100 units)
+max_amount = 10000
+# The preset selections that can be made when adding credit to the wallet with a credit card
+# Presets are pipe-separated |, and should never be outside the bounds provided by the min_amount and max_amount options
+payment_presets = [10.00, 25.00, 50.00, 100.00]
+# Make the user pay a extra fee when adding credit to the wallet with a credit card
+# The formula for determining the total cost is:
+# cost = added_funds + added_funds * fee_percentage / 100 + fee_fixed
+# Set these values to 0 to disable the feature.
+fee_percentage = 2.9
+fee_fixed = 30
+# "Shipping" information
+# Telegram can ask for extra information when charging the user for a credit card transaction
+# Set to yes the data you want to be required
+# This data will be stored in the database
+name_required = true
+email_required = true
+phone_required = true
# Bot appearance settings
[Appearance]
- # Display the full order information to the customers instead of the shortened version
- # The full order information includes the order number and the timestamp of the order placement
- full_order_info = false
- # Allow balance refill during the order checkout in case of unsufficient balance
- refill_on_checkout = true
- # Display welcome message (conversation_after_start) when the user sends /start
- display_welcome_message = true
+# Display the full order information to the customers instead of the shortened version
+# The full order information includes the order number and the timestamp of the order placement
+full_order_info = false
+# Allow balance refill during the order checkout in case of unsufficient balance
+refill_on_checkout = true
+# Display welcome message (conversation_after_start) when the user sends /start
+display_welcome_message = true
# Logging settings
[Logging]
- # The output format for the messages printed to the console
- # See https://docs.python.org/3/library/logging.html#logrecord-attributes for information about the {}-attributes
- format = "{asctime} | {threadName} | {name} | {message}"
- # Logging level: ignore all log entries with a level lower than the specified one
- # Valid options are FATAL, ERROR, WARNING, INFO, and DEBUG
- level = "INFO"
+# The output format for the messages printed to the console
+# See https://docs.python.org/3/library/logging.html#logrecord-attributes for information about the {}-attributes
+format = "{asctime} | {threadName} | {name} | {message}"
+# Logging level: ignore all log entries with a level lower than the specified one
+# Valid options are FATAL, ERROR, WARNING, INFO, and DEBUG
+level = "INFO"
diff --git a/core.py b/core.py
index dec6d04..6c6a8a4 100644
--- a/core.py
+++ b/core.py
@@ -1,16 +1,18 @@
+import logging
import os
import sys
-import telegram
-import worker
-import nuconfig
import threading
-import localization
-import logging
-import duckbot
+
import sqlalchemy
-import sqlalchemy.orm
import sqlalchemy.ext.declarative as sed
+import sqlalchemy.orm
+import telegram
+
import database
+import duckbot
+import localization
+import nuconfig
+import worker
try:
import coloredlogs
@@ -38,7 +40,7 @@ def main():
log.debug("config/config.toml does not exist.")
with open("config/template_config.toml", encoding="utf8") as template_cfg_file, \
- open("config/config.toml", "w", encoding="utf8") as user_cfg_file:
+ open("config/config.toml", "w", encoding="utf8") as user_cfg_file:
# Copy the template file to the config file
user_cfg_file.write(template_cfg_file.read())
@@ -48,7 +50,7 @@ def main():
# Compare the template config with the user-made one
with open("config/template_config.toml", encoding="utf8") as template_cfg_file, \
- open("config/config.toml", encoding="utf8") as user_cfg_file:
+ open("config/config.toml", encoding="utf8") as user_cfg_file:
template_cfg = nuconfig.NuConfig(template_cfg_file)
user_cfg = nuconfig.NuConfig(user_cfg_file)
if not template_cfg.cmplog(user_cfg):
@@ -173,7 +175,8 @@ def main():
receiving_worker = chat_workers.get(update.callback_query.from_user.id)
# Ensure a worker exists for the chat
if receiving_worker is None:
- log.debug(f"Received a callback query in a chat without worker: {update.callback_query.from_user.id}")
+ log.debug(
+ f"Received a callback query in a chat without worker: {update.callback_query.from_user.id}")
# Suggest that the user restarts the chat with /start
bot.send_message(update.callback_query.from_user.id, default_loc.get("error_no_worker_for_chat"))
# Skip the update
diff --git a/database.py b/database.py
index 1066cad..4264366 100644
--- a/database.py
+++ b/database.py
@@ -1,22 +1,24 @@
-import typing
-from sqlalchemy import create_engine, Column, ForeignKey, UniqueConstraint
-from sqlalchemy import Integer, BigInteger, String, Text, LargeBinary, DateTime, Boolean
-from sqlalchemy.orm import relationship, backref
-from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
-import telegram
-import requests
-import utils
import logging
+import typing
+
+import requests
+import telegram
+from sqlalchemy import Column, ForeignKey, UniqueConstraint
+from sqlalchemy import Integer, BigInteger, String, Text, LargeBinary, DateTime, Boolean
+from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
+from sqlalchemy.orm import relationship, backref
+
+import utils
if typing.TYPE_CHECKING:
import worker
-
log = logging.getLogger(__name__)
# Create a base class to define all the database subclasses
TableDeclarativeBase = declarative_base()
+
# Define all the database tables using the sqlalchemy declarative base
class User(DeferredReflection, TableDeclarativeBase):
"""A Telegram user who used the bot at least once."""
diff --git a/duckbot.py b/duckbot.py
index 59f6cb0..b36a786 100644
--- a/duckbot.py
+++ b/duckbot.py
@@ -1,9 +1,11 @@
-import nuconfig
-import telegram.error
import logging
+import sys
import time
import traceback
-import sys
+
+import telegram.error
+
+import nuconfig
log = logging.getLogger(__name__)
diff --git a/localization.py b/localization.py
index 329aea1..ad1acf3 100644
--- a/localization.py
+++ b/localization.py
@@ -1,15 +1,15 @@
-from typing import *
import importlib
-import types
-import logging
import json
-
+import logging
+import types
+from typing import *
log = logging.getLogger(__name__)
class IgnoreDict(dict):
"""A dictionary that if passed to format_map, ignores the missing replacement fields."""
+
def __missing__(self, key):
return "{" + key + "}"
diff --git a/nuconfig.py b/nuconfig.py
index e77cca8..d790b22 100644
--- a/nuconfig.py
+++ b/nuconfig.py
@@ -1,7 +1,7 @@
-from typing import *
-import toml
import logging
+from typing import *
+import toml
log = logging.getLogger(__name__)
CompareReport = Dict[str, Union[str, List[str], "Missing"]]
diff --git a/strings/en.py b/strings/en.py
index 34bbc4d..c83b171 100644
--- a/strings/en.py
+++ b/strings/en.py
@@ -110,7 +110,7 @@ conversation_live_orders_start = "You are in Live Orders mode\n" \
# Live orders mode: stop receiving messages
conversation_live_orders_stop = "Press the Stop button below this message to stop the" \
- " feed."
+ " feed."
# Conversation: help menu has been opened
conversation_open_help_menu = "What kind of help do you need?"
diff --git a/strings/ru.py b/strings/ru.py
index 6ecd264..18b8be9 100644
--- a/strings/ru.py
+++ b/strings/ru.py
@@ -71,8 +71,8 @@ conversation_open_user_menu = "Что бы Вы хотели сделать?\n"
conversation_open_admin_menu = "Вы 💼 Менеджер этого магазина!\n" \
"Что бы Вы хотели сделать?\n" \
"\n" \
- "Выберите опцию из вариантов на клавиатуре.\n" \
- "Если клавиатуры не видно - её можно активировать кнопкой с квардатами внизу."
+ "Выберите опцию из вариантов на клавиатуре.\n" \
+ "Если клавиатуры не видно - её можно активировать кнопкой с квардатами внизу."
# Conversation: select a payment method
conversation_payment_method = "Как бы Вы хотели пополнить ваш кошелек?"
@@ -104,7 +104,7 @@ conversation_live_orders_start = "Вы в режиме Новые заказ
"Все новые заказы появятся в этом чате в режиме реального времени," \
" и их можно отметить ✅ Выполнено" \
" или ✴️ Возвращено в случае возврата денег." \
-
+ \
# Live orders mode: stop receiving messages
conversation_live_orders_stop = "Нажмите Стоп в этом чате, чтобы остановить этот режим."
diff --git a/strings/uk.py b/strings/uk.py
index 5844d45..cff4529 100644
--- a/strings/uk.py
+++ b/strings/uk.py
@@ -71,8 +71,8 @@ conversation_open_user_menu = "Щоб ви хотіли зробити?\n" \
conversation_open_admin_menu = "Ви є 💼 Менеджером цього магазину!\n" \
"Що б ви хотіли зробити?\n" \
"\n" \
- "Виберіть опцію з варіантів на клавіатурі.\n" \
- "Якщо клавіатури не видно - її можна активувати кнопкою з чотирма квадратами внизу."
+ "Виберіть опцію з варіантів на клавіатурі.\n" \
+ "Якщо клавіатури не видно - її можна активувати кнопкою з чотирма квадратами внизу."
# Conversation: select a payment method
conversation_payment_method = "Як би Ви хотіли поповнити гаманець?"
diff --git a/strings/zh_cn.py b/strings/zh_cn.py
index 9a68ee6..fd34a0e 100644
--- a/strings/zh_cn.py
+++ b/strings/zh_cn.py
@@ -52,7 +52,7 @@ transactions_page = "Page {page}:\n" \
# transactions.csv caption
csv_caption = "生成了一个📄.csv文件,其中包含bot的数据库中多所有事物\n" \
"您可以使用其他程序(例如LibreOffice Calc)打开此文件并进行处理数据" \
-
+ \
# Conversation: the start command was sent and the bot should welcome the user
conversation_after_start = "您好!\n" \
"欢迎使用greed系统!\n" \
diff --git a/worker.py b/worker.py
index 5aadf32..ad7db71 100644
--- a/worker.py
+++ b/worker.py
@@ -1,26 +1,29 @@
-import threading
-from typing import *
-import uuid
import datetime
-import telegram
-import nuconfig
-import sys
-import queue as queuem
-import database as db
-import re
-import os
-import traceback
-from html import escape
-import requests
import logging
-import localization
+import os
+import queue as queuem
+import re
+import sys
+import threading
+import traceback
+import uuid
+from html import escape
+from typing import *
+
+import requests
import sqlalchemy.orm
+import telegram
+
+import database as db
+import localization
+import nuconfig
log = logging.getLogger(__name__)
class StopSignal:
"""A data class that should be sent to the worker when the conversation has to be stopped abnormally."""
+
def __init__(self, reason: str = ""):
self.reason = reason
@@ -39,7 +42,7 @@ class Worker(threading.Thread):
telegram_user: telegram.User,
cfg: nuconfig.NuConfig,
engine,
- *args,
+ *args,
**kwargs):
# Initialize the thread
super().__init__(name=f"Worker {chat.id}", *args, **kwargs)
@@ -662,8 +665,8 @@ class Worker(threading.Thread):
if self.cfg["Payments"]["CreditCard"]["credit_card_token"] != "" \
and self.cfg["Appearance"]["refill_on_checkout"] == 'yes' \
and self.Price(self.cfg["Payments"]["CreditCard"]["min_amount"]) <= \
- credit_required <= \
- self.Price(self.cfg["Payments"]["CreditCard"]["max_amount"]):
+ credit_required <= \
+ self.Price(self.cfg["Payments"]["CreditCard"]["max_amount"]):
self.__make_payment(self.Price(credit_required))
# If afer requested payment credit is still insufficient (either payment failure or cancel)
if self.user.credit < self.__get_cart_value(cart):
@@ -759,8 +762,9 @@ class Worker(threading.Thread):
self.bot.send_message(self.chat.id, self.loc.get("conversation_payment_method"),
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
# Wait for a reply from the user
- selection = self.__wait_for_specific_message([self.loc.get("menu_cash"), self.loc.get("menu_credit_card"), self.loc.get("menu_cancel")],
- cancellable=True)
+ selection = self.__wait_for_specific_message(
+ [self.loc.get("menu_cash"), self.loc.get("menu_credit_card"), self.loc.get("menu_cancel")],
+ cancellable=True)
# If the user has selected the Cash option...
if selection == self.loc.get("menu_cash"):
# Go to the pay with cash function
@@ -790,7 +794,8 @@ class Worker(threading.Thread):
self.bot.send_message(self.chat.id, self.loc.get("payment_cc_amount"),
reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True))
# Wait until a valid amount is sent
- selection = self.__wait_for_regex(r"([0-9]+(?:[.,][0-9]+)?|" + self.loc.get("menu_cancel") + r")", cancellable=True)
+ selection = self.__wait_for_regex(r"([0-9]+(?:[.,][0-9]+)?|" + self.loc.get("menu_cancel") + r")",
+ cancellable=True)
# If the user cancelled the action
if isinstance(selection, CancelSignal):
# Exit the loop
@@ -801,11 +806,13 @@ class Worker(threading.Thread):
# Ensure the amount is within the range
if value > self.Price(self.cfg["Payments"]["CreditCard"]["max_amount"]):
self.bot.send_message(self.chat.id,
- self.loc.get("error_payment_amount_over_max", max_amount=self.Price(self.cfg["Credit Card"]["max_amount"])))
+ self.loc.get("error_payment_amount_over_max",
+ max_amount=self.Price(self.cfg["Credit Card"]["max_amount"])))
continue
elif value < self.Price(self.cfg["Payments"]["CreditCard"]["min_amount"]):
self.bot.send_message(self.chat.id,
- self.loc.get("error_payment_amount_under_min", min_amount=self.Price(self.cfg["Credit Card"]["min_amount"])))
+ self.loc.get("error_payment_amount_under_min",
+ min_amount=self.Price(self.cfg["Credit Card"]["min_amount"])))
continue
break
# If the user cancelled the action...
@@ -1019,8 +1026,8 @@ class Worker(threading.Thread):
if product:
self.bot.send_message(self.chat.id,
self.loc.get("edit_current_value",
- value=(str(self.Price(product.price))
- if product.price is not None else 'Non in vendita')),
+ value=(str(self.Price(product.price))
+ if product.price is not None else 'Non in vendita')),
reply_markup=cancel)
# Wait for an answer
price = self.__wait_for_regex(r"([0-9]+(?:[.,][0-9]{1,2})?|[Xx])",
@@ -1162,7 +1169,8 @@ class Worker(threading.Thread):
message_id=update.message.message_id)
# Notify the user of the completition
self.bot.send_message(order.user_id,
- self.loc.get("notification_order_completed", order=order.text(w=self, session=self.session, user=True)))
+ self.loc.get("notification_order_completed",
+ order=order.text(w=self, session=self.session, user=True)))
# If the user pressed the refund order button, refund the order...
elif update.data == "order_refund":
# Ask for a refund reason
@@ -1302,7 +1310,8 @@ class Worker(threading.Thread):
telegram.InlineKeyboardButton(self.loc.get("menu_next"), callback_data="cmd_next")
)
# Add a Done button
- inline_keyboard_list.append([telegram.InlineKeyboardButton(self.loc.get("menu_done"), callback_data="cmd_done")])
+ inline_keyboard_list.append(
+ [telegram.InlineKeyboardButton(self.loc.get("menu_done"), callback_data="cmd_done")])
# Create the inline keyboard markup
inline_keyboard = telegram.InlineKeyboardMarkup(inline_keyboard_list)
# Create the message text