mirror of
https://github.com/Steffo99/greed.git
synced 2024-11-29 09:04:19 +00:00
Recover from corrupt repo
This commit is contained in:
parent
cf896a8549
commit
c26621223d
5 changed files with 86 additions and 37 deletions
|
@ -3,7 +3,7 @@
|
||||||
# Config file parameters
|
# Config file parameters
|
||||||
[Config]
|
[Config]
|
||||||
; Config file version. DO NOT EDIT THIS!
|
; Config file version. DO NOT EDIT THIS!
|
||||||
version = 7
|
version = 8
|
||||||
; Set this to no when you are done editing the file
|
; Set this to no when you are done editing the file
|
||||||
is_template = yes
|
is_template = yes
|
||||||
|
|
||||||
|
@ -22,19 +22,24 @@ long_polling_timeout = 30
|
||||||
; The database engine you want to use. Refer to http://docs.sqlalchemy.org/en/latest/core/engines.html for the possible settings.
|
; The database engine you want to use. Refer to http://docs.sqlalchemy.org/en/latest/core/engines.html for the possible settings.
|
||||||
engine = sqlite://
|
engine = sqlite://
|
||||||
|
|
||||||
# Enabled payment methods
|
# General payment settings
|
||||||
# To disable, leave the row empty
|
|
||||||
[Payment Methods]
|
|
||||||
# Cash payment is always enabled
|
|
||||||
# Credit card: get the token at @BotFather
|
|
||||||
credit_card_token = 123456789:YOUR_TOKEN_HERE_
|
|
||||||
|
|
||||||
[Payments]
|
[Payments]
|
||||||
# Minimum wallet payment accepted
|
|
||||||
min_amount = 10
|
|
||||||
# Maximum wallet payment accepted
|
|
||||||
max_amount = 100
|
|
||||||
# ISO currency code
|
# ISO currency code
|
||||||
currency = EUR
|
currency = EUR
|
||||||
# Currency exp parameter. You can find that on https://core.telegram.org/bots/payments/currencies.json
|
# Currency exp parameter. You can find that on https://core.telegram.org/bots/payments/currencies.json
|
||||||
currency_exp = 2
|
currency_exp = 2
|
||||||
|
|
||||||
|
# Credit card payment settings
|
||||||
|
[Credit Card]
|
||||||
|
# Provider token: get the token at @BotFather
|
||||||
|
credit_card_token = 123456789:YOUR_TOKEN_HERE_
|
||||||
|
# Minimum wallet payment accepted
|
||||||
|
min_amount = 10
|
||||||
|
# Maximum wallet payment accepted
|
||||||
|
max_amount = 100
|
||||||
|
# Require the name of the credit card owner
|
||||||
|
name_required = yes
|
||||||
|
# Require the email of the credit card owner
|
||||||
|
email_required = yes
|
||||||
|
# Require the phone number of the credit card owner
|
||||||
|
phone_required = yes
|
||||||
|
|
2
core.py
2
core.py
|
@ -116,7 +116,7 @@ def main():
|
||||||
# Forward the update to the corresponding worker
|
# Forward the update to the corresponding worker
|
||||||
receiving_worker = chat_workers.get(update.pre_checkout_query.from_user.id)
|
receiving_worker = chat_workers.get(update.pre_checkout_query.from_user.id)
|
||||||
# Check if it's the active invoice for this chat
|
# Check if it's the active invoice for this chat
|
||||||
if receiving_worker is None or update.pre_checkout_query.payload != receiving_worker.invoice_payload:
|
if receiving_worker is None or update.pre_checkout_query.invoice_payload != receiving_worker.invoice_payload:
|
||||||
# Notify the user that the invoice has expired
|
# Notify the user that the invoice has expired
|
||||||
try:
|
try:
|
||||||
bot.answer_pre_checkout_query(update.pre_checkout_query.id, ok=False, error_message=strings.error_invoice_expired)
|
bot.answer_pre_checkout_query(update.pre_checkout_query.id, ok=False, error_message=strings.error_invoice_expired)
|
||||||
|
|
31
database.py
31
database.py
|
@ -1,6 +1,6 @@
|
||||||
from sqlalchemy import create_engine, Column, ForeignKey, UniqueConstraint, CheckConstraint
|
from sqlalchemy import create_engine, Column, ForeignKey, UniqueConstraint, CheckConstraint
|
||||||
from sqlalchemy import Integer, BigInteger, String, Numeric, Text
|
from sqlalchemy import Integer, BigInteger, String, Numeric, Text
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker, relationship
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
import configloader
|
import configloader
|
||||||
import telegram
|
import telegram
|
||||||
|
@ -28,7 +28,7 @@ class User(TableDeclarativeBase):
|
||||||
username = Column(String)
|
username = Column(String)
|
||||||
|
|
||||||
# Current wallet credit
|
# Current wallet credit
|
||||||
credit = Column(Numeric, nullable=False)
|
credit = Column(Integer, nullable=False)
|
||||||
|
|
||||||
# Extra table parameters
|
# Extra table parameters
|
||||||
__tablename__ = "users"
|
__tablename__ = "users"
|
||||||
|
@ -65,7 +65,7 @@ class Product(TableDeclarativeBase):
|
||||||
# Product description
|
# Product description
|
||||||
description = Column(Text)
|
description = Column(Text)
|
||||||
# Product price, if null product is not for sale
|
# Product price, if null product is not for sale
|
||||||
price = Column(Numeric)
|
price = Column(Integer)
|
||||||
# Image filename
|
# Image filename
|
||||||
image = Column(String)
|
image = Column(String)
|
||||||
# Stock quantity, if null product has infinite stock
|
# Stock quantity, if null product has infinite stock
|
||||||
|
@ -94,26 +94,32 @@ class Transaction(TableDeclarativeBase):
|
||||||
Wallet credit ISN'T calculated from these, but they can be used to recalculate it."""
|
Wallet credit ISN'T calculated from these, but they can be used to recalculate it."""
|
||||||
|
|
||||||
# The internal transaction ID
|
# The internal transaction ID
|
||||||
transaction_id = Column(BigInteger, primary_key=True)
|
transaction_id = Column(Integer, primary_key=True)
|
||||||
# The user whose credit is affected by this transaction
|
# The user whose credit is affected by this transaction
|
||||||
user_id = Column(BigInteger, ForeignKey("users.user_id"), nullable=False)
|
user_id = Column(BigInteger, ForeignKey("users.user_id"), nullable=False)
|
||||||
|
user = relationship("User")
|
||||||
# The value of this transaction. Can be both negative and positive.
|
# The value of this transaction. Can be both negative and positive.
|
||||||
value = Column(Numeric, nullable=False)
|
value = Column(Integer, nullable=False)
|
||||||
# Extra notes on the transaction
|
# Extra notes on the transaction
|
||||||
notes = Column(Text)
|
notes = Column(Text)
|
||||||
|
|
||||||
# Payment provider
|
# Payment provider
|
||||||
provider = Column(String)
|
provider = Column(String)
|
||||||
|
# Transaction ID supplied by Telegram
|
||||||
|
telegram_charge_id = Column(String)
|
||||||
# Transaction ID supplied by the payment provider
|
# Transaction ID supplied by the payment provider
|
||||||
provider_id = Column(BigInteger)
|
provider_charge_id = Column(String)
|
||||||
|
|
||||||
# Extra transaction data, may be required by the payment provider in case of a dispute
|
# Extra transaction data, may be required by the payment provider in case of a dispute
|
||||||
payment_name = Column(String)
|
payment_name = Column(String)
|
||||||
payment_address = Column(String)
|
payment_phone = Column(String)
|
||||||
payment_email = Column(String)
|
payment_email = Column(String)
|
||||||
|
|
||||||
|
# Order ID
|
||||||
|
order_id = Column(Integer)
|
||||||
|
|
||||||
# Extra table parameters
|
# Extra table parameters
|
||||||
__tablename__ = "transactions"
|
__tablename__ = "transactions"
|
||||||
__table_args__ = (UniqueConstraint("provider", "provider_id"),)
|
__table_args__ = (UniqueConstraint("provider", "provider_charge_id"),)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Return the correctly formatted transaction value"""
|
"""Return the correctly formatted transaction value"""
|
||||||
|
@ -128,17 +134,12 @@ class Transaction(TableDeclarativeBase):
|
||||||
return f"<Transaction {self.transaction_id} - User {self.user_id} {str(self)}>"
|
return f"<Transaction {self.transaction_id} - User {self.user_id} {str(self)}>"
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# class Order(TableDeclarativeBase):
|
|
||||||
# """A product order."""
|
|
||||||
# pass
|
|
||||||
|
|
||||||
|
|
||||||
class Admin(TableDeclarativeBase):
|
class Admin(TableDeclarativeBase):
|
||||||
"""A greed administrator with his permissions."""
|
"""A greed administrator with his permissions."""
|
||||||
|
|
||||||
# The telegram id
|
# The telegram id
|
||||||
user_id = Column(BigInteger, ForeignKey("users.user_id"), primary_key=True)
|
user_id = Column(BigInteger, ForeignKey("users.user_id"), primary_key=True)
|
||||||
|
user = relationship("User")
|
||||||
# Permissions
|
# Permissions
|
||||||
# TODO: unfinished
|
# TODO: unfinished
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ conversation_expired = "🕐 Il bot non ha ricevuto messaggi per un po' di tempo
|
||||||
# User menu: order
|
# User menu: order
|
||||||
menu_order = "🛍 Ordina"
|
menu_order = "🛍 Ordina"
|
||||||
|
|
||||||
|
|
||||||
# User menu: order status
|
# User menu: order status
|
||||||
menu_order_status = "❓ Stato ordini"
|
menu_order_status = "❓ Stato ordini"
|
||||||
|
|
||||||
|
|
60
worker.py
60
worker.py
|
@ -1,5 +1,7 @@
|
||||||
import threading
|
import threading
|
||||||
import typing
|
import typing
|
||||||
|
import uuid
|
||||||
|
|
||||||
import telegram
|
import telegram
|
||||||
import strings
|
import strings
|
||||||
import configloader
|
import configloader
|
||||||
|
@ -28,8 +30,8 @@ class ChatWorker(threading.Thread):
|
||||||
# Open a new database session
|
# Open a new database session
|
||||||
self.session = db.Session()
|
self.session = db.Session()
|
||||||
# Get the user db data from the users and admin tables
|
# Get the user db data from the users and admin tables
|
||||||
self.user = self.session.query(db.User).filter(db.User.user_id == self.chat.id).one_or_none()
|
self.user = None
|
||||||
self.admin = self.session.query(db.Admin).filter(db.Admin.user_id == self.chat.id).one_or_none()
|
self.admin = None
|
||||||
# The sending pipe is stored in the ChatWorker class, allowing the forwarding of messages to the chat process
|
# The sending pipe is stored in the ChatWorker class, allowing the forwarding of messages to the chat process
|
||||||
self.queue = queuem.Queue()
|
self.queue = queuem.Queue()
|
||||||
# The current active invoice payload; reject all invoices with a different payload
|
# The current active invoice payload; reject all invoices with a different payload
|
||||||
|
@ -40,6 +42,9 @@ class ChatWorker(threading.Thread):
|
||||||
# TODO: catch all the possible exceptions
|
# TODO: catch all the possible exceptions
|
||||||
# Welcome the user to the bot
|
# Welcome the user to the bot
|
||||||
self.bot.send_message(self.chat.id, strings.conversation_after_start)
|
self.bot.send_message(self.chat.id, strings.conversation_after_start)
|
||||||
|
# Get the user db data from the users and admin tables
|
||||||
|
self.user = self.session.query(db.User).filter(db.User.user_id == self.chat.id).one_or_none()
|
||||||
|
self.admin = self.session.query(db.Admin).filter(db.Admin.user_id == self.chat.id).one_or_none()
|
||||||
# If the user isn't registered, create a new record and add it to the db
|
# If the user isn't registered, create a new record and add it to the db
|
||||||
if self.user is None:
|
if self.user is None:
|
||||||
# Create the new record
|
# Create the new record
|
||||||
|
@ -116,17 +121,31 @@ class ChatWorker(threading.Thread):
|
||||||
return match.group(1)
|
return match.group(1)
|
||||||
|
|
||||||
def __wait_for_precheckoutquery(self) -> telegram.PreCheckoutQuery:
|
def __wait_for_precheckoutquery(self) -> telegram.PreCheckoutQuery:
|
||||||
"""Continue getting updates until a precheckoutquery is received."""
|
"""Continue getting updates until a precheckoutquery is received.
|
||||||
|
The payload is checked by the core before forwarding the message."""
|
||||||
while True:
|
while True:
|
||||||
# Get the next update
|
# Get the next update
|
||||||
update = self.__receive_next_update()
|
update = self.__receive_next_update()
|
||||||
# Ensure the update contains a precheckoutquery
|
# Ensure the update contains a precheckoutquery
|
||||||
if update.pre_checkout_query is None:
|
if update.pre_checkout_query is None:
|
||||||
continue
|
continue
|
||||||
# TODO: something payload
|
|
||||||
# Return the precheckoutquery
|
# Return the precheckoutquery
|
||||||
return update.pre_checkout_query
|
return update.pre_checkout_query
|
||||||
|
|
||||||
|
def __wait_for_successfulpayment(self) -> telegram.SuccessfulPayment:
|
||||||
|
"""Continue getting updates until a successfulpayment is received."""
|
||||||
|
while True:
|
||||||
|
# Get the next update
|
||||||
|
update = self.__receive_next_update()
|
||||||
|
# Ensure the update contains a message
|
||||||
|
if update.message is None:
|
||||||
|
continue
|
||||||
|
# Ensure the message is a successfulpayment
|
||||||
|
if update.message.successful_payment is None:
|
||||||
|
continue
|
||||||
|
# Return the successfulpayment
|
||||||
|
return update.message.successful_payment
|
||||||
|
|
||||||
def __user_menu(self):
|
def __user_menu(self):
|
||||||
"""Function called from the run method when the user is not an administrator.
|
"""Function called from the run method when the user is not an administrator.
|
||||||
Normal bot actions should be placed here."""
|
Normal bot actions should be placed here."""
|
||||||
|
@ -175,7 +194,7 @@ class ChatWorker(threading.Thread):
|
||||||
# Cash
|
# Cash
|
||||||
keyboard.append([telegram.KeyboardButton(strings.menu_cash)])
|
keyboard.append([telegram.KeyboardButton(strings.menu_cash)])
|
||||||
# Telegram Payments
|
# Telegram Payments
|
||||||
if configloader.config["Payment Methods"]["credit_card_token"] != "":
|
if configloader.config["Credit Card"]["credit_card_token"] != "":
|
||||||
keyboard.append([telegram.KeyboardButton(strings.menu_credit_card)])
|
keyboard.append([telegram.KeyboardButton(strings.menu_credit_card)])
|
||||||
# Keyboard: go back to the previous menu
|
# Keyboard: go back to the previous menu
|
||||||
keyboard.append([telegram.KeyboardButton(strings.menu_cancel)])
|
keyboard.append([telegram.KeyboardButton(strings.menu_cancel)])
|
||||||
|
@ -224,17 +243,42 @@ class ChatWorker(threading.Thread):
|
||||||
self.bot.send_message(self.chat.id, strings.error_payment_amount_under_min.format(min_amount=strings.currency_format_string.format(symbol=strings.currency_symbol, value=configloader.config["Payments"]["min_amount"])))
|
self.bot.send_message(self.chat.id, strings.error_payment_amount_under_min.format(min_amount=strings.currency_format_string.format(symbol=strings.currency_symbol, value=configloader.config["Payments"]["min_amount"])))
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
|
# Set the invoice active invoice payload
|
||||||
|
self.invoice_payload = str(uuid.uuid4())
|
||||||
# The amount is valid, send the invoice
|
# The amount is valid, send the invoice
|
||||||
self.bot.send_invoice(self.chat.id,
|
self.bot.send_invoice(self.chat.id,
|
||||||
title=strings.payment_invoice_title,
|
title=strings.payment_invoice_title,
|
||||||
description=strings.payment_invoice_description.format(amount=strings.currency_format_string.format(symbol=strings.currency_symbol, value=selection)),
|
description=strings.payment_invoice_description.format(amount=strings.currency_format_string.format(symbol=strings.currency_symbol, value=selection)),
|
||||||
payload="temppayload", # TODO: how should I use the payload?
|
payload=self.invoice_payload,
|
||||||
provider_token=configloader.config["Payment Methods"]["credit_card_token"],
|
provider_token=configloader.config["Credit Card"]["credit_card_token"],
|
||||||
start_parameter="tempdeeplink", # TODO: no idea on how deeplinks should work
|
start_parameter="tempdeeplink", # TODO: no idea on how deeplinks should work
|
||||||
currency=configloader.config["Payments"]["currency"],
|
currency=configloader.config["Payments"]["currency"],
|
||||||
prices=[telegram.LabeledPrice(label=strings.payment_invoice_label, amount=int(selection * (10 ** int(configloader.config["Payments"]["currency_exp"]))))])
|
prices=[telegram.LabeledPrice(label=strings.payment_invoice_label, amount=int(selection * (10 ** int(configloader.config["Payments"]["currency_exp"]))))],
|
||||||
|
need_name=configloader.config["Credit Card"]["name_required"] == "yes",
|
||||||
|
need_email=configloader.config["Credit Card"]["email_required"] == "yes",
|
||||||
|
need_phone_number=configloader.config["Credit Card"]["phone_required"] == "yes")
|
||||||
# Wait for the invoice
|
# Wait for the invoice
|
||||||
precheckoutquery = self.__wait_for_precheckoutquery()
|
precheckoutquery = self.__wait_for_precheckoutquery()
|
||||||
|
# TODO: ensure the bot doesn't die here!
|
||||||
|
# Accept the checkout
|
||||||
|
self.bot.answer_pre_checkout_query(precheckoutquery.id, ok=True)
|
||||||
|
# Wait for the payment
|
||||||
|
successfulpayment = self.__wait_for_successfulpayment()
|
||||||
|
# Create a new database transaction
|
||||||
|
transaction = db.Transaction(user=self.user,
|
||||||
|
value=successfulpayment.total_amount,
|
||||||
|
provider="Credit Card",
|
||||||
|
telegram_charge_id=successfulpayment.telegram_payment_charge_id,
|
||||||
|
provider_charge_id=successfulpayment.provider_payment_charge_id)
|
||||||
|
if successfulpayment.order_info is not None:
|
||||||
|
transaction.payment_name = successfulpayment.order_info.name
|
||||||
|
transaction.payment_email = successfulpayment.order_info.email
|
||||||
|
transaction.payment_phone = successfulpayment.order_info.phone_number
|
||||||
|
# Add the credit to the user account
|
||||||
|
self.user.credit += successfulpayment.total_amount
|
||||||
|
# Add and commit the transaction
|
||||||
|
self.session.add(transaction)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
def __bot_info(self):
|
def __bot_info(self):
|
||||||
"""Send information about the bot."""
|
"""Send information about the bot."""
|
||||||
|
|
Loading…
Reference in a new issue