Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,9 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/

# End of https://www.toptal.com/developers/gitignore/api/python,pycharm,git
# End of https://www.toptal.com/developers/gitignore/api/python,pycharm,git

/**/*~undo-tree~

.envrc
.direnv
3 changes: 3 additions & 0 deletions app/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import os

BILL_FETCH_HOST = os.environ.get('BILL_FETCH_HOST', '127.0.0.1:8080')
75 changes: 52 additions & 23 deletions app/invoice_decode.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,57 @@
import aiohttp
import typing
import pathlib

from models import Invoice, Item
import config

class BillFetchError(Exception):
pass

async def decode_qr(qr: typing.Union[pathlib.Path, str]):
if isinstance(qr, str):
return await _fetch_bill_query(qr)
elif isinstance(qr, pathlib.Path):
return await _fetch_bill_qr(qr)

async def _fetch_bill_query(query: str):

async with aiohttp.ClientSession() as session:

url = f'http://{config.BILL_FETCH_HOST}/bill/query'
payload = {
'query': query
}

async with session.post(url, json=payload) as res:

return _convert_bill(await res.json())

async def _fetch_bill_qr(qr: pathlib.Path):

async with aiohttp.ClientSession() as session:

url = f'http://{config.BILL_FETCH_HOST}/bill/qr'
files = {'file': open(qr, 'rb')}

async with session.post(url, data=files) as res:

return _convert_bill(await res.json())


def _convert_bill(bill):

if 'error' in bill:
raise BillFetchError(bill['error'])

async def decode_qr(qr):
def dummy(qr):
invoice = {
'total_cost': 2270,
'items': [
{
'total_price': 619,
'name': 'Пицца Чоризо',
'details': 'питца',
},
{
'total_price': 1402,
'name': 'Карбонара+',
'details': 'питца',
},
{
'total_price': 249,
'name': 'Песто',
'details': 'питца',
},
],
def convert_item(item):
return {
'total_price': item['price'] * item['quantity'] / 100,
'name': item['name'],
'details': '🤔'
}
return invoice

return dummy(qr)
return {
'total_cost': bill['total'] / 100,
'items': list(map(convert_item, bill['records']))
}
14 changes: 8 additions & 6 deletions app/pabor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging
import re
import pathlib
import typing

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
Expand Down Expand Up @@ -74,17 +76,17 @@ async def qr_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
author = await User.find_by_tg_id(str(update.message.from_user.id))
user_id = str(author.get('_id'))
photo_file = await update.message.photo[-1].get_file()
await photo_file.download(f"user_{user_id}_qr.jpg")
qr = "random_qr_string" # TODO: decode qr photo
return await _qr(update, context, qr)
file_path = pathlib.Path('/tmp') / f'user_{user_id}_qr.jpg'
await photo_file.download(file_path)
return await _qr(update, context, file_path)


async def qr(update: Update, context: ContextTypes.DEFAULT_TYPE):
qr = update.message.text
return await _qr(update, context, qr)


async def _qr(update: Update, context: ContextTypes.DEFAULT_TYPE, qr: str):
async def _qr(update: Update, context: ContextTypes.DEFAULT_TYPE, qr: typing.Union[pathlib.Path, str]):
author = await User.find_by_tg_id(str(update.message.from_user.id))
user_id = str(author.get('_id'))
try:
Expand Down Expand Up @@ -614,7 +616,7 @@ async def _send_invoice_money_requests(context: ContextTypes.DEFAULT_TYPE, invoi
owner = await User.find_by_id(invoice.get('owner_id'))

for user_id, user_total in users_owe.items():
if user_id == owner['id']:
if user_id == owner['_id']:
continue # comment if you want to check it yourself

operation_id = await Operation.create(invoice_id, user_id, user_total)
Expand Down Expand Up @@ -871,4 +873,4 @@ async def i_owe(update: Update, context: ContextTypes.DEFAULT_TYPE):
user_operation_paid_accepted_handler,
user_operation_paid_declined_handler,
pabor_handler,
]
]
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ services:
MONGO_PORT: 27017
MONGO_DATABASE_NAME: pabor_bot
TG_BOT_KEY: replace_with_real_bot_key
BILL_FETCH_HOST: 127.0.0.1:8080
volumes:
- ./app:/usr/src/app/app
ports:
Expand All @@ -25,4 +26,4 @@ services:
volumes:
- mongodata:/var/lib/mongodb/data
ports:
- 27017:27017
- 27017:27017
4 changes: 2 additions & 2 deletions docker/dev/python/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10.2
FROM python:3.9.12
MAINTAINER debbius3@gmail.com

WORKDIR /usr/shr/app
Expand All @@ -8,4 +8,4 @@ RUN pip3 install -r requirements.txt

COPY ./app ./app

CMD ["python3", "app/main.py"]
CMD ["python3", "app/main.py"]
141 changes: 141 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
description = "Pabor bot";

inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/17b62c338f2a0862a58bb6951556beecd98ccda9";

pypi-deps-db = {
url = "github:DavHau/pypi-deps-db";
inputs.nixpkgs.follows = "nixpkgs";
inputs.mach-nix.follows = "mach-nix";
};
mach-nix = {
url = "github:DavHau/mach-nix/3.5.0";
inputs.nixpkgs.follows = "nixpkgs";
inputs.pypi-deps-db.follows = "pypi-deps-db";
};
};

outputs = { self, nixpkgs, flake-utils, mach-nix, ... }:
flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = nixpkgs.legacyPackages.${system};
machNix = mach-nix.lib.${system};
in
{
devShell = pkgs.mkShell {
buildInputs = with pkgs; [
(machNix.mkPython {
python = "python39";
requirements = builtins.readFile ./requirements.txt;
})

pyright
];
};
}
);
}
Loading