diff --git a/tipbot.py b/tipbot.py
index 656dcb2..e64c805 100644
--- a/tipbot.py
+++ b/tipbot.py
@@ -1,7 +1,6 @@
"""
- Developed by @vsnation(t.me/vsnation)
- Email: vsnation.v@gmail.com
- If you'll need the support use the contacts ^(above)!
+Created by @vsnation(t.me/vsnation) vsnation.v@gmail.com
+Updated for use with Firo by Likho Jiba (likho) and Joshua Babb (sneurlax@gmail.com).
"""
import json
import logging
@@ -15,18 +14,23 @@
import matplotlib.pyplot as plt
import datetime
import time
-from pymongo import MongoClient
+from pymongo import MongoClient, ReturnDocument
from telegram import Bot, InlineKeyboardMarkup, InlineKeyboardButton
import uuid
+from decimal import Decimal, getcontext
from api.firo_wallet_api import FiroWalletAPI
plt.style.use('seaborn-whitegrid')
-logger = logging.getLogger()
-logger.setLevel(logging.ERROR)
+logger = logging.getLogger(__name__)
+logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
+handler = logging.StreamHandler()
+handler.setFormatter(formatter)
+logger.addHandler(handler)
-AV_FEE = 0.002
+AV_FEE = Decimal('0.002')
+getcontext().prec = 8 # Set precision for Decimal.
with open('services.json') as conf_file:
conf = json.load(conf_file)
@@ -36,7 +40,7 @@
dictionary = conf['dictionary']
LOG_CHANNEL = conf['log_ch']
-SATS_IN_BTC = 1e8
+SATS_IN_BTC = Decimal('1e8')
wallet_api = FiroWalletAPI(httpprovider)
@@ -46,16 +50,18 @@
bold_high = ImageFont.truetype(font="fonts/ProximaNova-Bold.ttf", size=int(26 * point_to_pixels))
WELCOME_MESSAGE = """
-Welcome to the Firo telegram tip bot!
+Welcome to the Firo telegram tip bot!
"""
+def to_decimal(value):
+ return Decimal(str(value))
class TipBot:
def __init__(self, wallet_api):
- # INIT
+ # INIT.
self.bot = Bot(bot_token)
self.wallet_api = wallet_api
- # firo Butler Initialization
+ # Firo Butler Initialization.
client = MongoClient(connectionString)
db = client.get_default_database()
self.col_captcha = db['captcha']
@@ -84,11 +90,11 @@ def __init__(self, wallet_api):
while True:
try:
self._is_user_in_db = None
- # get chat updates
+ # Get chat updates.
new_messages = self.wait_new_message()
self.processing_messages(new_messages)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def pending_tasks(self):
while True:
@@ -104,26 +110,22 @@ def processing_messages(self, new_messages):
else self.new_message.callback_query.message
self.text, self._is_video = self.get_action(self.new_message)
self.message_text = str(self.text).lower()
- # init user data
+ # Init user data.
self.first_name = self.new_message.effective_user.first_name
self.username = self.new_message.effective_user.username
self.user_id = int(self.new_message.effective_user.id)
self.firo_address, self.balance_in_firo, self.locked_in_firo, self.is_withdraw = self.get_user_data()
- self.balance_in_groth = self.balance_in_firo * SATS_IN_BTC if self.balance_in_firo is not None else 0
+ self.balance_in_groth = self.balance_in_firo * SATS_IN_BTC if self.balance_in_firo is not None else Decimal('0')
try:
self._is_verified = self.col_users.find_one({"_id": self.user_id})['IsVerified']
self._is_user_in_db = self._is_verified
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
self._is_verified = True
self._is_user_in_db = False
- #
- print(self.username)
- print(self.user_id)
- print(self.first_name)
- print(self.message_text, '\n')
+
self.group_id = self.message.chat.id
self.group_username = self.get_group_username()
@@ -133,13 +135,11 @@ def processing_messages(self, new_messages):
else:
args = None
- # Check if user changed his username
+ # Check if user changed his username.
self.check_username_on_change()
self.action_processing(str(split[0]).lower(), args)
- # self.check_group_msg()
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def send_to_logs(self, text):
try:
@@ -149,11 +149,11 @@ def send_to_logs(self, text):
parse_mode='HTML'
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def get_group_username(self):
"""
- Get group username
+ Get group username
"""
try:
return str(self.message.chat.username)
@@ -162,7 +162,7 @@ def get_group_username(self):
def get_user_username(self):
"""
- Get User username
+ Get User username
"""
try:
return str(self.message.from_user.username)
@@ -196,7 +196,7 @@ def get_action(message):
def action_processing(self, cmd, args):
"""
- Check each user actions
+ Check each user actions
"""
# ***** Tip bot section begin *****
if cmd.startswith("/tip") or cmd.startswith("/atip"):
@@ -228,7 +228,7 @@ def action_processing(self, cmd, args):
parse_mode='HTML'
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
self.incorrect_parametrs_image()
self.send_message(
self.user_id,
@@ -263,7 +263,7 @@ def action_processing(self, cmd, args):
else:
self.incorrect_parametrs_image()
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
self.incorrect_parametrs_image()
@@ -278,11 +278,10 @@ def action_processing(self, cmd, args):
envelope_id = cmd.split("|")[1]
self.catch_envelope(envelope_id)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
self.incorrect_parametrs_image()
-
elif cmd.startswith("/balance"):
if not self._is_user_in_db:
self.send_message(self.group_id,
@@ -307,7 +306,7 @@ def action_processing(self, cmd, args):
else:
self.incorrect_parametrs_image()
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
traceback.print_exc()
elif cmd.startswith("/deposit"):
@@ -338,7 +337,7 @@ def action_processing(self, cmd, args):
def check_username_on_change(self):
"""
- Check username on change in the bot
+ Check username on change in the bot
"""
_is_username_in_db = self.col_users.find_one(
{"username": self.username}) is not None \
@@ -376,163 +375,138 @@ def get_wallet_balance(self):
try:
r = self.wallet_api.listsparkmints()
result = sum([_x['amount'] for _x in r['result'] if not _x['isUsed']])
- print("Current Balance", result / 1e8)
+ logger.info(f"Current Balance: {result / SATS_IN_BTC} FIRO")
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def update_balance(self):
"""
- Update user's balance using transactions history
+ Update user's balance using transactions history
"""
- print("Handle TXs")
- # First get unused mints for the wallet, check if mint is confirmed in the tx list
- unused_mints = []
- mints = wallet_api.listsparkmints()
-
- for mnt in mints['result']:
- if not mnt['isUsed']:
- unused_mints.append(mnt)
+ logger.info("Handle TXs")
+ unused_mints = [mnt for mnt in wallet_api.listsparkmints()['result'] if not mnt['isUsed']]
response = self.wallet_api.get_txs_list()
for _tx in response['result']:
- for unused_mnt in unused_mints:
- try:
- if unused_mnt['txid'] == _tx['txid']:
- """
- Check withdraw txs
- """
- sparkcoin_addr = wallet_api.get_spark_coin_address(unused_mnt['txid'])
- _user_receiver = self.col_users.find_one(
- {"Address": sparkcoin_addr[0]['address']}
- )
-
- _is_tx_exist_deposit = self.col_txs.find_one(
- {"txId": _tx['txid'], "type": "deposit"}
- ) is not None
- if _user_receiver is not None and \
- not _is_tx_exist_deposit and \
- _tx['confirmations'] >= 2 and _tx['category'] == 'receive':
-
- value_in_coins = float(_tx['amount'])
- new_balance = _user_receiver['Balance'] + value_in_coins
- _id = str(uuid.uuid4())
- self.col_txs.insert_one({
- '_id': _id,
- 'txId': _tx['txid'],
- **_tx,
- 'type': "deposit",
- 'timestamp': datetime.datetime.now()
- })
- self.col_users.update_one(
- _user_receiver,
- {
- "$set":
- {
- "Balance": float("{0:.8f}".format(float(new_balance)))
- }
- }
- )
- self.create_receive_tips_image(
- _user_receiver['_id'],
- "{0:.8f}".format(value_in_coins),
- "Deposit")
-
- print("*Deposit Success*\n"
- "Balance of address %s has recharged on *%s* firos." % (
- sparkcoin_addr[0]['address'], value_in_coins
- ))
- continue
-
- _is_tx_exist_withdraw = self.col_txs.find_one(
- {"txId": _tx['txid'], "type": "withdraw"}
- ) is not None
-
- pending_sender = self.col_senders.find_one(
- {"txId": _tx['txid'], "status": "pending"}
- )
- if not pending_sender:
- continue
- _user_sender = self.col_users.find_one({"_id": pending_sender['user_id']})
- if _user_sender is not None and not _is_tx_exist_withdraw and _tx['category'] == "spend":
-
- value_in_coins = float((abs(_tx['amount'])))
-
- if _tx['confirmations'] >= 2:
- _id = str(uuid.uuid4())
- self.col_txs.insert_one({
- '_id': _id,
- "txId": _tx['txid'],
- **_tx,
- 'type': "withdraw",
- 'timestamp': datetime.datetime.now()
- })
- new_locked = float(_user_sender['Locked']) - value_in_coins
- if new_locked >= 0:
- self.col_users.update_one(
- {
- "_id": _user_sender['_id']
- },
- {
- "$set":
- {
- "Locked": float("{0:.8f}".format(new_locked)),
- "IsWithdraw": False
- }
- }
- )
- else:
- new_balance = float(_user_sender['Balance']) - value_in_coins
- self.col_users.update_one(
- {
- "_id": _user_sender['_id']
- },
- {
- "$set":
- {
- "Balance": float("{0:.8f}".format(new_balance)),
- "IsWithdraw": False
- }
- }
- )
-
- self.create_send_tips_image(_user_sender['_id'],
- "{0:.8f}".format(float(abs(_tx['amount']))),
- "%s..." % _user_sender['Address'][0][:8])
-
- self.col_senders.update_one(
- {"txId": _tx['txid'], "status": "pending", "user_id": _user_sender['_id']},
- {"$set": {"status": "completed"}}
- )
- print("*Withdrawal Success*\n"
- "Balance of address %s has recharged on *%s* firos." % (
- _user_sender['Address'], value_in_coins
- ))
- continue
-
- except Exception as exc:
- print(exc)
- traceback.print_exc()
+ if self.col_txs.find_one({"txId": _tx['txid']}) is None: # Avoid processing duplicate transactions.
+ for unused_mnt in unused_mints:
+ try:
+ if unused_mnt['txid'] == _tx['txid']:
+ with client.start_session() as session:
+ with session.start_transaction():
+ try:
+ sparkcoin_addr = wallet_api.get_spark_coin_address(unused_mnt['txid'])
+ _user_receiver = self.col_users.find_one(
+ {"Address": sparkcoin_addr[0]['address']},
+ session=session
+ )
+
+ if _user_receiver and \
+ not self.col_txs.find_one({"txId": _tx['txid'], "type": "deposit"}, session=session) and \
+ _tx['confirmations'] >= 2 and _tx['category'] == 'receive':
+
+ value_in_coins = to_decimal(_tx['amount'])
+ new_balance = to_decimal(_user_receiver['Balance']) + value_in_coins
+ _id = str(uuid.uuid4())
+ self.col_txs.insert_one({
+ '_id': _id,
+ 'txId': _tx['txid'],
+ **_tx,
+ 'type': "deposit",
+ 'timestamp': datetime.datetime.now()
+ }, session=session)
+ self.col_users.update_one(
+ {"_id": _user_receiver['_id']},
+ {"$set": {"Balance": new_balance}},
+ session=session
+ )
+ self.create_receive_tips_image(
+ _user_receiver['_id'],
+ "{0:.8f}".format(value_in_coins),
+ "Deposit"
+ )
+ logger.info(f"*Deposit Success*\nBalance of address {sparkcoin_addr[0]['address']} "
+ f"has recharged on *{value_in_coins}* FIRO.")
+ continue
+
+ pending_sender = self.col_senders.find_one(
+ {"txId": _tx['txid'], "status": "pending"},
+ session=session
+ )
+ if pending_sender and not self.col_txs.find_one({"txId": _tx['txid'], "type": "withdraw"}, session=session) and _tx['category'] == "spend":
+ _user_sender = self.col_users.find_one({"_id": pending_sender['user_id']}, session=session)
+ if _user_sender:
+
+ value_in_coins = to_decimal(abs(_tx['amount']))
+ if _tx['confirmations'] >= 2:
+ _id = str(uuid.uuid4())
+ self.col_txs.insert_one({
+ '_id': _id,
+ "txId": _tx['txid'],
+ **_tx,
+ 'type': "withdraw",
+ 'timestamp': datetime.datetime.now()
+ }, session=session)
+
+ new_locked = to_decimal(_user_sender['Locked']) - value_in_coins
+ if new_locked >= 0:
+ self.col_users.update_one(
+ {"_id": _user_sender['_id']},
+ {"$set": {
+ "Locked": new_locked,
+ "IsWithdraw": False
+ }},
+ session=session
+ )
+ else:
+ new_balance = to_decimal(_user_sender['Balance']) - value_in_coins
+ self.col_users.update_one(
+ {"_id": _user_sender['_id']},
+ {"$set": {
+ "Balance": new_balance,
+ "IsWithdraw": False
+ }},
+ session=session
+ )
+
+ self.create_send_tips_image(_user_sender['_id'],
+ "{0:.8f}".format(value_in_coins),
+ f"{_user_sender['Address'][0][:8]}...")
+
+ self.col_senders.update_one(
+ {"txId": _tx['txid'], "status": "pending", "user_id": _user_sender['_id']},
+ {"$set": {"status": "completed"}},
+ session=session
+ )
+ logger.info(f"*Withdrawal Success*\nBalance of address {sparkcoin_addr[0]['address']} "
+ f"has been deducted by *{value_in_coins}* FIRO.")
+ continue
+ except Exception as e:
+ logger.error(f"Error updating balance: {str(e)}", exc_info=True)
+ session.abort_transaction()
+
+ except Exception as exc:
+ logger.error(exc, exc_info=True)
def get_user_data(self):
"""
- Get user data
+ Get user data
"""
try:
_user = self.col_users.find_one({"_id": self.user_id})
self.update_address_and_balance(_user)
return _user['Address'], _user['Balance'], _user['Locked'], _user['IsWithdraw']
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
return None, None, None, None
def update_address_and_balance(self, _user):
mints = wallet_api.listsparkmints()
if len(mints) > 0:
- # Check if User has a Lelantus address
+ # Check if User has a Lelantus address.
valid = wallet_api.validate_address(_user['Address'][0])['result']
is_valid_firo = 'isvalid'
- # User still has Lelantus address, Update address and balance
+ # User still has Lelantus address, Update address and balance.
if is_valid_firo in valid:
spark_address = wallet_api.create_user_wallet()
self.col_users.update_one(
@@ -547,99 +521,66 @@ def update_address_and_balance(self, _user):
def withdraw_coins(self, address, amount, comment=""):
"""
- Withdraw coins to address with params:
- address
- amount
+ Withdraw coins to address with params:
+ address
+ amount
"""
try:
-
- try:
- amount = float(amount)
- except Exception as exc:
- self.send_message(self.user_id,
- dictionary['incorrect_amount'],
- parse_mode='HTML')
- print(exc)
- traceback.print_exc()
- return
-
- _is_address_valid = False
+ amount = to_decimal(amount)
+ total_amount = amount + AV_FEE
validate = self.wallet_api.validate_address(address)['result']
is_valid_spark = 'isvalidSpark'
is_valid_firo = 'isvalid'
- if is_valid_spark in validate or is_valid_firo in validate:
- _is_address_valid = True
-
- if not _is_address_valid:
- self.send_message(
- self.user_id,
- "You specified incorrect address",
- parse_mode='HTML'
- )
+ if is_valid_spark not in validate and is_valid_firo not in validate:
+ self.send_message(self.user_id, "You specified an incorrect address", parse_mode='HTML')
return
- if float(self.balance_in_firo) >= float("{0:.8f}".format(amount)) and float(self.balance_in_firo) >= AV_FEE:
-
- _user = self.col_users.find_one({"_id": self.user_id})
-
- new_balance = float("{0:.8f}".format(float(self.balance_in_firo - amount)))
- new_locked = float("{0:.8f}".format(float(self.locked_in_firo + amount - AV_FEE)))
- response = self.wallet_api.spendspark(
- address,
- float(amount),
- comment
- )
- print(response, "withdraw")
- if response.get('error'):
- self.send_message(
- self.user_id, "Not enough inputs. Try to repeat a bit later!"
+ # Atomic operation to lock the user's balance and update it.
+ with client.start_session() as session:
+ with session.start_transaction():
+ user = self.col_users.find_one_and_update(
+ {"_id": self.user_id, "Balance": {"$gte": total_amount}},
+ {"$inc": {"Balance": -total_amount, "Locked": total_amount}},
+ return_document=ReturnDocument.AFTER,
+ session=session
)
- self.send_to_logs(f"Unavailable Withdraw\n{str(response)}")
- return
-
- self.col_senders.insert_one(
- {"txId": response['result'], "status": "pending", "user_id": self.user_id}
- )
- self.col_users.update_one(
- {
- "_id": self.user_id
- },
- {
- "$set":
- {
- "Balance": new_balance,
- "Locked": new_locked,
- }
- }
- )
- self.withdraw_image(self.user_id,
- "{0:.8f}".format(float(amount)),
- address,
- msg=f"Your txId {response['result']}")
-
- else:
- self.insufficient_balance_image()
+ if not user:
+ self.insufficient_balance_image()
+ return
+
+ # Proceed with the withdrawal.
+ response = self.wallet_api.spendspark(address, amount, comment)
+ if response.get('error'):
+ # Rollback if spend failed.
+ self.col_users.update_one(
+ {"_id": self.user_id},
+ {"$inc": {"Balance": amount, "Locked": -total_amount}},
+ session=session
+ )
+ self.send_message(self.user_id, "Not enough inputs. Try again later!")
+ self.send_to_logs(f"Unavailable Withdraw\n{str(response)}")
+ return
+
+ # Insert the transaction into the senders collection.
+ self.col_senders.insert_one(
+ {"txId": response['result'], "status": "pending", "user_id": self.user_id},
+ session=session
+ )
+ self.withdraw_image(self.user_id, "{0:.8f}".format(amount), address, msg=f"Your txId {response['result']}")
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def tip_user(self, username, amount, comment, _type=None):
"""
- Tip user with params:
- username
- amount
+ Tip user with params:
+ username
+ amount
"""
try:
- try:
- amount = float(amount)
- if amount < 0.00000001:
- raise Exception
- except Exception as exc:
- self.incorrect_parametrs_image()
- print(exc)
- traceback.print_exc()
- return
+ amount = to_decimal(amount)
+ if amount < Decimal('0.00000001'):
+ raise ValueError("Amount too small")
username = username.replace('@', '')
@@ -655,23 +596,17 @@ def tip_user(self, username, amount, comment, _type=None):
self.send_tip(_user['_id'], amount, _type, comment)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
+ self.incorrect_parametrs_image()
def tip_in_the_chat(self, amount, comment="", _type=None):
"""
- Send a tip to user in the chat
+ Send a tip to user in the chat
"""
try:
- try:
- amount = float(amount)
- if amount < 0.00000001:
- raise Exception
- except Exception as exc:
- self.incorrect_parametrs_image()
- print(exc)
- traceback.print_exc()
- return
+ amount = to_decimal(amount)
+ if amount < Decimal('0.00000001'):
+ raise ValueError("Amount too small")
self.send_tip(
self.message.reply_to_message.from_user.id,
@@ -681,111 +616,60 @@ def tip_in_the_chat(self, amount, comment="", _type=None):
)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
+ self.incorrect_parametrs_image()
def send_tip(self, user_id, amount, _type, comment):
"""
- Send tip to user with params
- user_id - user identificator
- addrees - user address
- amount - amount of a tip
+ Send tip to user with params
+ user_id - user identifier
+ amount - amount of a tip
"""
try:
if self.user_id == user_id:
- self.send_message(
- self.user_id,
- "You can't send tips to yourself!",
- parse_mode='HTML'
- )
+ self.send_message(self.user_id, "You can't send tips to yourself!", parse_mode='HTML')
return
- _user_receiver = self.col_users.find_one({"_id": user_id})
-
- if _user_receiver is None or _user_receiver['IsVerified'] is False:
- self.send_message(self.user_id,
- dictionary['username_error'],
- parse_mode='HTML')
- return
-
- if _type == 'anonymous':
- sender_name = str(_type).title()
- # sender_user_id = 0000000
- else:
- sender_name = self.first_name
- # sender_user_id = self.user_id
-
- if self.balance_in_firo >= amount > 0:
- try:
-
- self.create_send_tips_image(
- self.user_id,
- "{0:.8f}".format(float(amount)),
- _user_receiver['first_name'],
- comment
+ with client.start_session() as session:
+ with session.start_transaction():
+ _user_receiver = self.col_users.find_one({"_id": user_id}, session=session)
+ if not _user_receiver or _user_receiver['IsVerified'] is False:
+ self.send_message(self.user_id, dictionary['username_error'], parse_mode='HTML')
+ return
+
+ user_sender = self.col_users.find_one_and_update(
+ {"_id": self.user_id, "Balance": {"$gte": amount}},
+ {"$inc": {"Balance": -amount}},
+ return_document=ReturnDocument.AFTER,
+ session=session
)
- self.create_receive_tips_image(
- _user_receiver['_id'],
- "{0:.8f}".format(float(amount)),
- sender_name,
- comment
- )
+ if not user_sender:
+ self.insufficient_balance_image()
+ return
+ # Update receiver's balance.
self.col_users.update_one(
- {
- "_id": self.user_id
- },
- {
- "$set":
- {
- "Balance": float(
- "{0:.8f}".format(float(float(self.balance_in_firo) - float(amount))))
- }
- }
- )
- self.col_users.update_one(
- {
- "_id": _user_receiver['_id']
- },
- {
- "$set":
- {
- "Balance": float(
- "{0:.8f}".format(float(float(_user_receiver['Balance']) + float(amount))))
- }
- }
+ {"_id": user_id},
+ {"$inc": {"Balance": amount}},
+ session=session
)
- if _type == 'anonymous':
- self.col_tip_logs.insert(
- {
- "type": "atip",
- "from_user_id": self.user_id,
- "to_user_id": _user_receiver['_id'],
- "amount": amount
- }
- )
-
- else:
- self.col_tip_logs.insert(
- {
- "type": "tip",
- "from_user_id": self.user_id,
- "to_user_id": _user_receiver['_id'],
- "amount": amount
- }
- )
+ # Log the tip.
+ tip_log = {
+ "type": "atip" if _type == "anonymous" else "tip",
+ "from_user_id": self.user_id,
+ "to_user_id": user_id,
+ "amount": amount
+ }
+ self.col_tip_logs.insert_one(tip_log, session=session)
- except Exception as exc:
- print(exc)
- traceback.print_exc()
+ # Create images.
+ self.create_send_tips_image(self.user_id, "{0:.8f}".format(amount), _user_receiver['first_name'], comment)
+ self.create_receive_tips_image(user_id, "{0:.8f}".format(amount), str(_type).title() if _type else self.first_name, comment)
- else:
- self.insufficient_balance_image()
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def create_receive_tips_image(self, user_id, amount, first_name, comment=""):
try:
@@ -822,15 +706,7 @@ def create_receive_tips_image(self, user_id, amount, first_name, comment=""):
except Exception as exc:
- try:
- print(exc)
- if 'blocked' in str(exc):
- self.send_message(self.group_id,
- "User needs to unblock the bot in order to check their balance!" % user_id,
- parse_mode='HTML')
- traceback.print_exc()
- except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def create_send_tips_image(self, user_id, amount, first_name, comment=""):
try:
@@ -858,16 +734,7 @@ def create_send_tips_image(self, user_id, amount, first_name, comment=""):
)
except Exception as exc:
- try:
- print(exc)
- if 'blocked' in str(exc):
- self.send_message(self.group_id,
- "User needs to unblock the bot in order to check their balance!" % user_id,
- parse_mode='HTML')
- traceback.print_exc()
- except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def withdraw_image(self, user_id, amount, address, msg=None):
try:
@@ -891,8 +758,7 @@ def withdraw_image(self, user_id, amount, address, msg=None):
caption=f'{msg}'
)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def create_wallet_image(self, public_address):
try:
@@ -913,8 +779,7 @@ def create_wallet_image(self, public_address):
timeout=200
)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def withdraw_failed_image(self, user_id):
try:
@@ -934,8 +799,7 @@ def withdraw_failed_image(self, user_id):
parse_mode='HTML'
)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def insufficient_balance_image(self):
try:
@@ -958,10 +822,9 @@ def insufficient_balance_image(self):
parse_mode='HTML'
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def red_envelope_catched(self, amount):
try:
@@ -983,10 +846,9 @@ def red_envelope_catched(self, amount):
open(image_name, 'rb')
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def red_envelope_created(self, first_name, envelope_id):
im = Image.open("images/red_envelope_created.png")
@@ -1013,7 +875,7 @@ def red_envelope_created(self, first_name, envelope_id):
)
return response['message_id']
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
return 0
def red_envelope_ended(self):
@@ -1033,7 +895,7 @@ def red_envelope_ended(self):
open(image_name, 'rb'),
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def incorrect_parametrs_image(self):
try:
@@ -1055,14 +917,13 @@ def incorrect_parametrs_image(self):
parse_mode='HTML'
)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def create_red_envelope(self, amount):
try:
- amount = float(amount)
+ amount = to_decimal(amount)
- if amount < 0.001:
+ if amount < Decimal('0.001'):
self.incorrect_parametrs_image()
return
@@ -1076,7 +937,7 @@ def create_red_envelope(self, amount):
{
"$set":
{
- "Balance": float("{0:.8f}".format(float(self.balance_in_firo) - amount))
+ "Balance": to_decimal(self.balance_in_firo) - amount
}
}
)
@@ -1101,103 +962,104 @@ def create_red_envelope(self, amount):
self.insufficient_balance_image()
except Exception as exc:
+ logger.error(exc, exc_info=True)
self.incorrect_parametrs_image()
- print(exc)
def catch_envelope(self, envelope_id):
try:
- envelope = self.col_envelopes.find_one({"_id": envelope_id})
- _is_envelope_exist = envelope is not None
- _is_ended = envelope['remains'] == 0
- _is_user_catched = str(self.user_id) in str(envelope['takers'])
-
- if _is_user_catched:
- self.answer_call_back(text="❗️You have already caught Firo from this envelope❗️",
- query_id=self.new_message.callback_query.id)
- return
-
- if _is_ended:
- self.answer_call_back(text="❗RED ENVELOPE ENDED❗️",
- query_id=self.new_message.callback_query.id)
- self.red_envelope_ended()
- self.delete_tg_message(self.group_id, self.message.message_id)
- return
-
- if _is_envelope_exist:
- minimal_amount = 0.001
- if envelope['remains'] <= minimal_amount:
- catch_amount = envelope['remains']
- else:
- if len(envelope['takers']) < 5:
- catch_amount = float(
- "{0:.8f}".format(float(random.uniform(minimal_amount, envelope['remains'] / 2))))
- else:
- catch_amount = float(
- "{0:.8f}".format(float(random.uniform(minimal_amount, envelope['remains']))))
-
- new_remains = float("{0:.8f}".format(envelope['remains'] - catch_amount))
- if new_remains < 0:
- new_remains = 0
- catch_amount = envelope['remains']
-
- self.col_envelopes.update_one(
- {
- "_id": envelope_id,
- },
- {
- "$push": {
- "takers": [self.user_id, catch_amount]
- },
- "$set": {
- "remains": new_remains
- }
- }
- )
- self.col_users.update_one(
- {
- "_id": self.user_id
- },
- {
- "$set":
+ with client.start_session() as session:
+ with session.start_transaction():
+ envelope = self.col_envelopes.find_one({"_id": envelope_id}, session=session)
+ _is_envelope_exist = envelope is not None
+ _is_ended = envelope['remains'] == 0
+ _is_user_catched = str(self.user_id) in str(envelope['takers'])
+
+ if _is_user_catched:
+ self.answer_call_back(text="❗️You have already caught Firo from this envelope❗️",
+ query_id=self.new_message.callback_query.id)
+ return
+
+ if _is_ended:
+ self.answer_call_back(text="❗RED ENVELOPE ENDED❗️",
+ query_id=self.new_message.callback_query.id)
+ self.red_envelope_ended()
+ self.delete_tg_message(self.group_id, self.message.message_id)
+ return
+
+ if _is_envelope_exist:
+ minimal_amount = Decimal('0.001')
+ if envelope['remains'] <= minimal_amount:
+ catch_amount = envelope['remains']
+ else:
+ if len(envelope['takers']) < 5:
+ catch_amount = to_decimal(random.uniform(minimal_amount, envelope['remains'] / 2))
+ else:
+ catch_amount = to_decimal(random.uniform(minimal_amount, envelope['remains']))
+
+ new_remains = envelope['remains'] - catch_amount
+ if new_remains < 0:
+ new_remains = Decimal('0')
+ catch_amount = envelope['remains']
+
+ self.col_envelopes.update_one(
{
- "Balance": float("{0:.8f}".format(float(self.balance_in_firo) + catch_amount))
- }
- }
- )
- try:
- if envelope['group_username'] != "None":
- msg_text = '%s caught %s Firo from a RED ENVELOPE' % (
- self.user_id,
- self.first_name,
- "{0:.8f}".format(catch_amount),
- envelope['group_username'],
- envelope['msg_id']
+ "_id": envelope_id,
+ },
+ {
+ "$push": {
+ "takers": [self.user_id, catch_amount]
+ },
+ "$set": {
+ "remains": new_remains
+ }
+ },
+ session=session
)
- else:
- msg_text = '%s caught %s Firo from a RED ENVELOPE' % (
- self.user_id,
- self.first_name,
- "{0:.8f}".format(catch_amount),
+ self.col_users.update_one(
+ {
+ "_id": self.user_id
+ },
+ {
+ "$inc": {
+ "Balance": catch_amount
+ }
+ },
+ session=session
)
- self.send_message(
- envelope['group_id'],
- text=msg_text,
- disable_web_page_preview=True,
- parse_mode='HTML'
- )
- except Exception:
- traceback.print_exc()
+ try:
+ if envelope['group_username'] != "None":
+ msg_text = '%s caught %s Firo from a RED ENVELOPE' % (
+ self.user_id,
+ self.first_name,
+ "{0:.8f}".format(catch_amount),
+ envelope['group_username'],
+ envelope['msg_id']
+ )
+ else:
+ msg_text = '%s caught %s Firo from a RED ENVELOPE' % (
+ self.user_id,
+ self.first_name,
+ "{0:.8f}".format(catch_amount),
+ )
+ self.send_message(
+ envelope['group_id'],
+ text=msg_text,
+ disable_web_page_preview=True,
+ parse_mode='HTML'
+ )
+ except Exception:
+ logger.error(exc, exc_info=True)
- self.answer_call_back(text="✅YOU CAUGHT %s Firo from ENVELOPE✅️" % catch_amount,
- query_id=self.new_message.callback_query.id)
- self.red_envelope_catched("{0:.8f}".format(catch_amount))
+ self.answer_call_back(text="✅YOU CAUGHT %s Firo from ENVELOPE✅️" % catch_amount,
+ query_id=self.new_message.callback_query.id)
+ self.red_envelope_catched("{0:.8f}".format(catch_amount))
- else:
- self.insufficient_balance_image()
+ else:
+ self.insufficient_balance_image()
except Exception as exc:
+ logger.error(exc, exc_info=True)
self.incorrect_parametrs_image()
- print(exc)
def delete_tg_message(self, user_id, message_id):
try:
@@ -1213,7 +1075,7 @@ def answer_call_back(self, text, query_id):
show_alert=True
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def auth_user(self):
try:
@@ -1235,8 +1097,8 @@ def auth_user(self):
{
"IsVerified": True,
"Address": public_address,
- "Balance": 0,
- "Locked": 0,
+ "Balance": Decimal('0'),
+ "Locked": Decimal('0'),
"IsWithdraw": False
}
}, upsert=True
@@ -1258,8 +1120,8 @@ def auth_user(self):
"IsVerified": True,
"JoinDate": datetime.datetime.now(),
"Address": public_address,
- "Balance": 0,
- "Locked": 0,
+ "Balance": Decimal('0'),
+ "Locked": Decimal('0'),
"IsWithdraw": False,
}
}, upsert=True
@@ -1290,8 +1152,7 @@ def auth_user(self):
parse_mode='html',
)
except Exception as exc:
- print(exc)
- traceback.print_exc()
+ logger.error(exc, exc_info=True)
def create_qr_code(self):
try:
@@ -1305,7 +1166,7 @@ def create_qr_code(self):
parse_mode='HTML'
)
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def cleanhtml(self, string_html):
cleanr = re.compile('<.*?>')
@@ -1323,7 +1184,7 @@ def send_message(self, user_id, text, parse_mode=None, disable_web_page_preview=
)
return response
except Exception as exc:
- print(exc)
+ logger.error(exc, exc_info=True)
def main():
@@ -1331,8 +1192,7 @@ def main():
TipBot(wallet_api)
except Exception as e:
- print(e)
- traceback.print_exc()
+ logger.error(e, exc_info=True)
if __name__ == '__main__':