Skip to content

Commit

Permalink
Cleanup config module
Browse files Browse the repository at this point in the history
Remove code repetition by putting variables in class attributes so they
are set automatically from environment based on their names and types.

Signed-off-by: alfred richardsn <rchrdsn@protonmail.ch>
  • Loading branch information
r4rdsn committed Nov 22, 2019
1 parent e921d9e commit ba6d0ff
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 63 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ ORDERS_LIMIT_COUNT=10
# Escrow
ESCROW_ENABLED=true
WIF_FILENAME=/run/secrets/wif.json
OP_CHECK_TIMEOUT_HOURS=24
58 changes: 36 additions & 22 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,39 @@ def getenv_bool(key, default=None):
return env == "true" if env in ("true", "false") else default


TOKEN_FILENAME = getenv("TOKEN_FILENAME")
INTERNAL_HOST = getenv("INTERNAL_HOST", "127.0.0.1")
SERVER_HOST = getenv("SERVER_HOST")
SERVER_PORT = getenv_int("SERVER_PORT")
WEBHOOK_PATH = getenv("WEBHOOK_PATH")
DATABASE_NAME = getenv("DATABASE_NAME", "tellerbot")
DATABASE_HOST = getenv("DATABASE_HOST", "127.0.0.1")
DATABASE_USERNAME = getenv("DATABASE_USERNAME")
DATABASE_PASSWORD_FILENAME = getenv("DATABASE_PASSWORD_FILENAME")

LOGGER_LEVEL = getenv("LOGGER_LEVEL")
LOG_FILENAME = getenv("LOG_FILENAME")

SUPPORT_CHAT_ID = getenv_int("SUPPORT_CHAT_ID")
EXCEPTIONS_CHAT_ID = getenv_int("EXCEPTIONS_CHAT_ID")

ORDERS_COUNT = getenv_int("ORDERS_COUNT")
ORDERS_LIMIT_HOURS = getenv_int("ORDERS_LIMIT_HOURS")
ORDERS_LIMIT_COUNT = getenv_int("ORDERS_LIMIT_COUNT")

ESCROW_ENABLED = getenv_bool("ESCROW_ENABLED")
WIF_FILENAME = getenv("WIF_FILENAME")
class Config:
"""Data holder for configuration values."""

TOKEN_FILENAME: str
INTERNAL_HOST: str = "127.0.0.1"
SERVER_HOST: str
SERVER_PORT: int
WEBHOOK_PATH: str
DATABASE_NAME: str = "tellerbot"
DATABASE_HOST: str = "127.0.0.1"
DATABASE_USERNAME: str
DATABASE_PASSWORD_FILENAME: str

LOGGER_LEVEL: str
LOG_FILENAME: str

SUPPORT_CHAT_ID: int
EXCEPTIONS_CHAT_ID: int

ORDERS_COUNT: int
ORDERS_LIMIT_HOURS: int
ORDERS_LIMIT_COUNT: int

ESCROW_ENABLED: bool
WIF_FILENAME: str


for name, annotation in Config.__annotations__.items():
if annotation == int:
value = getenv_int(name)
elif annotation == bool:
value = getenv_bool(name)
else:
value = getenv(name)
if value:
setattr(Config, name, value)
16 changes: 8 additions & 8 deletions src/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@
from aiogram.dispatcher.storage import BaseStorage
from motor.motor_asyncio import AsyncIOMotorClient

from src import config
from src.config import Config


if config.DATABASE_USERNAME and config.DATABASE_PASSWORD_FILENAME:
with open(config.DATABASE_PASSWORD_FILENAME, "r") as password_file:
try:
with open(Config.DATABASE_PASSWORD_FILENAME, "r") as password_file:
client = AsyncIOMotorClient(
config.DATABASE_HOST,
username=config.DATABASE_USERNAME,
Config.DATABASE_HOST,
username=Config.DATABASE_USERNAME,
password=password_file.read(),
)
else:
client = AsyncIOMotorClient(config.DATABASE_HOST)
database = client[config.DATABASE_NAME]
except (AttributeError, FileNotFoundError):
client = AsyncIOMotorClient(Config.DATABASE_HOST)
database = client[Config.DATABASE_NAME]

STATE_KEY = "state"

Expand Down
4 changes: 2 additions & 2 deletions src/escrow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with TellerBot. If not, see <https://www.gnu.org/licenses/>.
from src import config
from src.config import Config


if config.ESCROW_ENABLED:
if Config.ESCROW_ENABLED:
from src.escrow.blockchain.golos_blockchain import GolosBlockchain

SUPPORTED_BLOCKCHAINS = [GolosBlockchain()]
Expand Down
2 changes: 2 additions & 0 deletions src/escrow/blockchain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ async def check_transaction(
amount_without_fee: Decimal,
asset: str,
memo: str,
transaction_time: float,
):
"""Add transaction in ``self._queue`` to be checked."""
self._queue.append(
Expand All @@ -120,6 +121,7 @@ async def check_transaction(
"amount_without_fee": amount_without_fee,
"asset": asset,
"memo": memo,
"transaction_time": transaction_time,
}
)
# Start streaming if not already streaming
Expand Down
9 changes: 3 additions & 6 deletions src/escrow/blockchain/golos_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from golos.exceptions import TransactionNotFound
from golos.ws_client import error_handler

from src import config
from src.config import Config
from src.database import database
from src.escrow.blockchain import BaseBlockchain
from src.escrow.blockchain import BlockchainConnectionError
Expand Down Expand Up @@ -115,10 +115,7 @@ async def get_limits(self, asset: str):
return limits.get(asset)

async def transfer(self, to: str, amount: Decimal, asset: str):
if not config.WIF_FILENAME:
raise Exception("WIF_FILENAME is not set")

with open(config.WIF_FILENAME) as wif_file:
with open(Config.WIF_FILENAME) as wif_file:
transaction = await get_running_loop().run_in_executor(
None,
self._golos.transfer,
Expand Down Expand Up @@ -201,7 +198,7 @@ async def _check_operation(
op_amount, asset = op["amount"].split()
amount = Decimal(op_amount)
for req in queue:
if "transaction_time" in req and "timestamp" in op:
if "timestamp" in op:
date = datetime.strptime(op["timestamp"], "%Y-%m-%dT%H:%M:%S")
if timegm(date.timetuple()) < req["transaction_time"]:
continue
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from src.bot import dp
from src.bot import tg
from src.config import EXCEPTIONS_CHAT_ID
from src.config import Config
from src.handlers import start_menu # noqa: F401, noreorder
from src.handlers import creation # noqa: F401
from src.handlers import escrow # noqa: F401
Expand Down Expand Up @@ -84,7 +84,7 @@ async def errors_handler(update: types.Update, exception: Exception):

if chat_id is not None:
await tg.send_message(
EXCEPTIONS_CHAT_ID,
Config.EXCEPTIONS_CHAT_ID,
"Error handling {} {} from {} ({}) in chat {}\n{}".format(
update_type,
update.update_id,
Expand Down
16 changes: 8 additions & 8 deletions src/handlers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from aiogram.utils.emoji import emojize
from pymongo.cursor import Cursor

from src import config
from src.config import Config

from src.bot import ( # noqa: F401, noreorder
dp,
Expand Down Expand Up @@ -97,19 +97,19 @@ async def orders_list(
:param message_id: Telegram ID of message to edit.
:param invert: Invert all prices.
"""
keyboard = types.InlineKeyboardMarkup(row_width=min(config.ORDERS_COUNT // 2, 8))
keyboard = types.InlineKeyboardMarkup(row_width=min(Config.ORDERS_COUNT // 2, 8))

inline_orders_buttons = (
types.InlineKeyboardButton(
emojize(":arrow_left:"),
callback_data="{} {} {}".format(
buttons_data, start - config.ORDERS_COUNT, int(invert)
buttons_data, start - Config.ORDERS_COUNT, int(invert)
),
),
types.InlineKeyboardButton(
emojize(":arrow_right:"),
callback_data="{} {} {}".format(
buttons_data, start + config.ORDERS_COUNT, int(invert)
buttons_data, start + Config.ORDERS_COUNT, int(invert)
),
),
)
Expand All @@ -123,7 +123,7 @@ async def orders_list(
await tg.edit_message_text(text, chat_id, message_id, reply_markup=keyboard)
return

all_orders = await cursor.to_list(length=start + config.ORDERS_COUNT)
all_orders = await cursor.to_list(length=start + Config.ORDERS_COUNT)
orders = all_orders[start:]

lines = []
Expand Down Expand Up @@ -179,7 +179,7 @@ async def orders_list(
types.InlineKeyboardButton(
_("Invert"),
callback_data="{} {} {}".format(
buttons_data, start - config.ORDERS_COUNT, int(not invert)
buttons_data, start - Config.ORDERS_COUNT, int(not invert)
),
)
)
Expand All @@ -189,8 +189,8 @@ async def orders_list(
text = (
"\\["
+ _("Page {} of {}").format(
math.ceil(start / config.ORDERS_COUNT) + 1,
math.ceil(quantity / config.ORDERS_COUNT),
math.ceil(start / Config.ORDERS_COUNT) + 1,
math.ceil(quantity / Config.ORDERS_COUNT),
)
+ "]\n"
+ "\n".join(lines)
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/escrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from src import states
from src.bot import dp
from src.bot import tg
from src.config import SUPPORT_CHAT_ID
from src.config import Config
from src.database import database
from src.escrow import get_escrow_instance
from src.escrow import SUPPORTED_BANKS
Expand Down Expand Up @@ -876,7 +876,7 @@ async def validate_offer(call: types.CallbackQuery, offer: EscrowOffer):
"""Ask support for manual verification of exchange."""
escrow_instance = get_escrow_instance(offer[offer.type])
await tg.send_message(
SUPPORT_CHAT_ID,
Config.SUPPORT_CHAT_ID,
"Unconfirmed escrow.\nTransaction: {}\nMemo: {}".format(
escrow_instance.trx_url(offer.trx_id), markdown.code(offer.memo),
),
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
from bson.objectid import ObjectId
from motor.core import AgnosticBaseCursor as Cursor

from src import config
from src import states
from src.bot import dp
from src.bot import tg
from src.config import Config
from src.database import database
from src.database import STATE_KEY
from src.escrow.escrow_offer import EscrowOffer
Expand Down Expand Up @@ -299,7 +299,7 @@ async def match_button(call: types.CallbackQuery, order: OrderType):
@order_handler
async def escrow_button(call: types.CallbackQuery, order: OrderType):
"""React to "Escrow" button by starting escrow exchange."""
if not config.ESCROW_ENABLED:
if not Config.ESCROW_ENABLED:
await call.answer(
_("Escrow is temporarily unavailable. Sorry for the inconvenience.")
)
Expand Down
9 changes: 4 additions & 5 deletions src/handlers/start_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@

from src import states
from src.bot import tg
from src.config import ORDERS_LIMIT_COUNT
from src.config import ORDERS_LIMIT_HOURS
from src.config import Config
from src.database import database
from src.handlers.base import help_message
from src.handlers.base import inline_control_buttons
Expand Down Expand Up @@ -79,14 +78,14 @@ async def handle_create(message: types.Message, state: FSMContext):
user_orders = await database.orders.count_documents(
{
"user_id": message.from_user.id,
"start_time": {"$gt": current_time - ORDERS_LIMIT_HOURS * 3600},
"start_time": {"$gt": current_time - Config.ORDERS_LIMIT_HOURS * 3600},
}
)
if user_orders >= ORDERS_LIMIT_COUNT:
if user_orders >= Config.ORDERS_LIMIT_COUNT:
await tg.send_message(
message.chat.id,
_("You can't create more than {} orders in {} hours.").format(
ORDERS_LIMIT_COUNT, ORDERS_LIMIT_HOURS
Config.ORDERS_LIMIT_COUNT, Config.ORDERS_LIMIT_HOURS
),
)
return
Expand Down
12 changes: 6 additions & 6 deletions src/handlers/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
from aiogram.utils import markdown
from aiogram.utils.emoji import emojize

from src import config
from src.bot import dp
from src.config import Config
from src.handlers.base import private_handler
from src.handlers.base import start_keyboard
from src.handlers.base import tg
Expand Down Expand Up @@ -54,7 +54,7 @@ async def send_message_to_support(message: types.Message):
username = markdown.link(message.from_user.full_name, message.from_user.url)

await tg.send_message(
config.SUPPORT_CHAT_ID,
Config.SUPPORT_CHAT_ID,
emojize(f":envelope:")
+ f" #chat_{message.chat.id} {message.message_id}\n{username}:\n"
+ message.text,
Expand Down Expand Up @@ -85,7 +85,7 @@ async def handle_reply(message: types.Message):


@dp.message_handler(
lambda msg: msg.chat.id == config.SUPPORT_CHAT_ID
lambda msg: msg.chat.id == Config.SUPPORT_CHAT_ID
and msg.reply_to_message is not None
and msg.reply_to_message.text.startswith(emojize(":envelope: "))
)
Expand All @@ -110,16 +110,16 @@ async def answer_support_ticket(message: types.Message):


@dp.message_handler(
lambda msg: msg.chat.id == config.SUPPORT_CHAT_ID, commands=["toggle_escrow"]
lambda msg: msg.chat.id == Config.SUPPORT_CHAT_ID, commands=["toggle_escrow"]
)
async def toggle_escrow(message: types.Message):
"""Toggle escrow availability.
This command makes creation of new escrow offers unavailable if
escrow is enabled, and makes it available if it's disabled.
"""
config.ESCROW_ENABLED = not config.ESCROW_ENABLED
if config.ESCROW_ENABLED:
Config.ESCROW_ENABLED = not Config.ESCROW_ENABLED
if Config.ESCROW_ENABLED:
await tg.send_message(message.chat.id, _("Escrow was enabled."))
else:
await tg.send_message(message.chat.id, _("Escrow was disabled."))

0 comments on commit ba6d0ff

Please sign in to comment.