def execute(self, bot, update, args): username = update.effective_user.username if not Bismuth.wallet_exists(username): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return if len(args) < 2 or len(args) > 4: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return send_to = args[0] amount = args[1] operation = "" if len(args) > 2: operation = args[2] data = "" if len(args) > 3: data = args[3] if not BismuthUtil.valid_address(send_to): update.message.reply_text( text=f"{emo.ERROR} Bismuth address is not valid", parse_mode=ParseMode.MARKDOWN) return if not utl.is_numeric(amount) or float(amount) < 0: update.message.reply_text( text=f"{emo.ERROR} Specified amount is not valid", parse_mode=ParseMode.MARKDOWN) return message = update.message.reply_text(text=f"{emo.WAIT} Sending...", parse_mode=ParseMode.MARKDOWN) bis = Bismuth(username) bis.load_wallet() trx = bis.send(send_to, amount, operation, data) url = f"{self.BLCK_EXPL_URL}{utl.encode_url(trx)}" if trx: bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.DONE} Done!\n[View on Block Explorer]({url})\n" f"(Available after ~1 minute)", parse_mode=ParseMode.MARKDOWN) else: bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Not able to send Transaction")
def execute(self, bot, update, args): username = update.effective_user.username if not Bismuth.wallet_exists(username): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return message = update.message.reply_text( text=f"{emo.WAIT} Checking balance...", parse_mode=ParseMode.MARKDOWN) bis = Bismuth(username) bis.load_wallet() balance = bis.get_balance() if utl.is_numeric(balance): balance = f"`{balance}` BIS" bot.edit_message_text(chat_id=message.chat_id, message_id=message.message_id, text=f"Balance: {balance}", parse_mode=ParseMode.MARKDOWN)
def execute(self, bot, update, args): user = update.effective_user.username if len(args) < 2 or len(args) > 4: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return address = args[0] amount = args[1] operation = "" if len(args) > 2: operation = args[2] data = "" if len(args) > 3: data = args[3] # Check if provided amount is valid if not utl.is_numeric(amount) or float(amount) < 0: update.message.reply_text( text=f"{emo.ERROR} Specified amount is not valid", parse_mode=ParseMode.MARKDOWN) return # Check if provided address is valid if not BismuthUtil.valid_address(address): update.message.reply_text( text=f"{emo.ERROR} Provided address is not valid", parse_mode=ParseMode.MARKDOWN) return # Check if user has a wallet if not Bismuth.wallet_exists(user): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return message = update.message.reply_text(text=f"{emo.WAIT} Processing...", parse_mode=ParseMode.MARKDOWN) bis = Bismuth(user) bis.load_wallet() balance = bis.get_balance() total = float(amount) + BismuthUtil.fee_for_tx(data) # Check for sufficient funds if not utl.is_numeric(balance) or float(balance) < total: bot.edit_message_text(chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Not enough funds") return try: # Execute withdrawing trx = bis.send(address, amount, operation, data) except Exception as e: error = f"Error withdrawing {amount} BIS " \ f"from @{user} " \ f"to {address} " \ f"with '{operation}' " \ f"and '{data}': {e}" logging.error(error) self.notify(error) trx = None if trx: logging.debug(f"Withdraw {amount} BIS " f"from @{user} " f"to {address} " f"with '{operation}' " f"and '{data}'") # Save withdrawing to database insert = self.get_resource("insert_withdraw.sql") self.execute_sql(insert, user, address, amount) url = f"{self.BLCK_EXPL_URL}{utl.encode_url(trx)}" # Send success message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.DONE} DONE!\n[View on Block Explorer]({url})\n" f"(Available after ~1 minute)", parse_mode=ParseMode.MARKDOWN) else: # Send error message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text= f"{emo.ERROR} Withdrawing not executed. Something went wrong..." )
def _update_plugin(self, bot, update): """ Update a plugin by uploading a file to the bot. If you provide a .ZIP file then the content will be extracted into the plugin with the same name as the file. For example the file 'about.zip' will be extracted into the 'about' plugin folder. It's also possible to provide a .PY file. In this case the file will replace the plugin implementation with the same name. For example the file 'about.py' will replace the same file in the 'about' plugin. All of this will only work in a private chat with the bot. """ # Check if in a private chat if bot.get_chat(update.message.chat_id).type != Chat.PRIVATE: return # Check if user that triggered the command is allowed to execute it if update.effective_user.id not in self.config.get("admin", "ids"): return name = update.message.effective_attachment.file_name.lower() zipped = False try: if name.endswith(".py"): plugin_name = name.replace(".py", "") elif name.endswith(".zip"): if len(name) == 18: msg = f"{emo.ERROR} Only backups of plugins are supported" update.message.reply_text(msg) return zipped = True if utl.is_numeric(name[:13]): plugin_name = name[14:].replace(".zip", "") else: plugin_name = name.replace(".zip", "") else: msg = f"{emo.ERROR} Wrong file format" update.message.reply_text(msg) return file = bot.getFile(update.message.document.file_id) if zipped: os.makedirs(con.DIR_TMP, exist_ok=True) zip_path = os.path.join(con.DIR_TMP, name) file.download(zip_path) with ZipFile(zip_path, 'r') as zip_file: plugin_path = os.path.join(con.DIR_SRC, con.DIR_PLG, plugin_name) zip_file.extractall(plugin_path) else: file.download( os.path.join(con.DIR_SRC, con.DIR_PLG, plugin_name, name)) self.remove_plugin(plugin_name) self.add_plugin(plugin_name) shutil.rmtree(con.DIR_TMP, ignore_errors=True) update.message.reply_text(f"{emo.DONE} Plugin successfully loaded") except Exception as e: logging.error(e) msg = f"{emo.ERROR} {e}" update.message.reply_text(msg)
def execute(self, bot, update, args): reply = update.message.reply_to_message # Tip the user that you reply to if reply: # Determine amount to tip if len(args) == 0: # Tip default BIS amount amount = self.DEFAULT_TIP elif len(args) == 1: # Tip specified BIS amount try: amount = float(args[0]) except: msg = f"{emo.ERROR} Specified amount is not valid" update.message.reply_text(msg) return else: msg = "You are tipping the user you reply to. " \ "Only allowed argument is the amount." update.message.reply_text(msg) return to_user = reply.from_user.username # Provide username to be tipped else: if not args: msg = f"Usage:\n{self.get_usage()}" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return # Determine amount to tip if len(args) == 1: # Tip default BIS amount amount = self.DEFAULT_TIP elif len(args) == 2: # Tip specified BIS amount try: amount = float(args[1]) except: msg = f"{emo.ERROR} Specified amount is not valid" update.message.reply_text(msg) return else: # Wrong syntax msg = f"{emo.ERROR} Wrong number of arguments:\n{self.get_usage()}" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return to_user = args[0] # Check if username starts with @ if not to_user.startswith("@"): msg = f"{emo.ERROR} Username not valid:\n{self.get_usage()}" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return to_user = to_user[1:] from_user = update.effective_user.username # Check if sender has a wallet if not Bismuth.wallet_exists(from_user): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return # Check if recipient has a wallet if not Bismuth.wallet_exists(to_user): msg = f"{emo.ERROR} User @{utl.esc_md(to_user)} doesn't have a wallet yet" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return msg = f"{emo.WAIT} Processing..." message = update.message.reply_text(msg) # Init sender wallet bis = Bismuth(from_user) bis.load_wallet() balance = bis.get_balance() total = amount + con.TRX_FEE # Check for sufficient funds if not utl.is_numeric(balance) or float(balance) < total: bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Not enough funds") return try: # Execute tipping trx = bis.tip(to_user, amount) except Exception as e: error = f"Error executing tip from @{from_user} to @{to_user} with {amount}: {e}" logging.error(error) self.notify(error) trx = None if trx: logging.debug(f"Tip from '{from_user}' to '{to_user}' with {amount} BIS - TRX: {trx}") # Save tipping to database insert = self.get_resource("insert_tip.sql") self.execute_sql(insert, from_user, to_user, amount) # Send success message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.DONE} @{utl.esc_md(to_user)} received `{amount}` BIS", parse_mode=ParseMode.MARKDOWN) # Get user ID from tipped user sql = self.get_resource("get_user_id.sql") res = self.execute_sql(sql, to_user, plugin="wallet") to_user_id = res["data"][0][0] if res["success"] else None if to_user_id: try: # Send success message to tipped user msg = f"You've been tipped with `{amount}` BIS by @{utl.esc_md(from_user)}" bot.send_message(to_user_id, msg, parse_mode=ParseMode.MARKDOWN) except Exception as e: error = f"Can't notify user '{to_user}' about tip" logging.debug(f"{error}: {e}") else: error = f"Can't notify user '{to_user}' about tip. User ID not found in DB" logging.error(error) self.notify(error) else: # Send error message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Tipping not executed. Something went wrong...")
def execute(self, bot, update, args): if not args: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return # command <total amount> <number of users> if len(args) == 2: amount = args[0] users = args[1] # command <total amount>/<number of users> elif len(args) == 1 and "/" in args[0]: lst = args[0].split("/") if len(lst) == 2: amount = lst[0] users = lst[1] else: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return else: update.message.reply_text(text=f"Usage:\n{self.get_usage()}", parse_mode=ParseMode.MARKDOWN) return # Make sure that 'amount' and 'users' are valid values try: amount = float(amount) users = int(users) except: msg = f"{emo.ERROR} Arguments not valid" update.message.reply_text(msg) return if users < 1: msg = f"{emo.ERROR} You have to rain on at least one user" update.message.reply_text(msg) return multiplier = 10**2 user_amount = math.floor(amount / users * multiplier) / multiplier if user_amount < 0.01: msg = f"{emo.ERROR} Amount per user to small. Has to be at least `0.01`" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return from_user = update.effective_user.username from_user_id = update.effective_user.id # Check if sender has a wallet if not Bismuth.wallet_exists(from_user): msg = "Accept terms and create a wallet first with:\n/accept" update.message.reply_text(msg) return # Get all users from database sql = self.get_resource("read_users.sql") res = self.execute_sql(sql, plugin="wallet") if not res["success"]: msg = f"{emo.ERROR} Not possible to retrieve users" update.message.reply_text(msg) error = res["data"] logging.error(error) self.notify(error) return # Remove own user from list of users to rain on user_list = [x for x in res["data"] if x[1] != from_user] # Check if enough users available to be rained on if len(user_list) < users: msg = f"{emo.ERROR} Not enough users. {len(user_list)} available" update.message.reply_text(msg, parse_mode=ParseMode.MARKDOWN) return # Randomly choose users from all users chosen = random.sample(user_list, users) msg = f"{emo.WAIT} Processing..." message = update.message.reply_text(msg) # Init sender wallet bis = Bismuth(from_user) bis.load_wallet() balance = bis.get_balance() total = amount + (users * con.TRX_FEE) # Check for sufficient funds if not utl.is_numeric(balance) or float(balance) < total: bot.edit_message_text(chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Not enough funds") return result = f"{emo.DONE} @{utl.esc_md(from_user)} sent `{user_amount}` BIS each to: " for to_data in chosen: to_user_id = to_data[0] to_user = to_data[1] try: # Execute tipping trx = bis.tip(to_user, user_amount) except Exception as e: error = f"Error executing rain from @{from_user} to @{to_user} with {user_amount} BIS: {e}" logging.error(error) self.notify(error) trx = None if trx: logging.debug( f"Rain from '{from_user}' to '{to_user}' with {user_amount} BIS - TRX: {trx}" ) # Save tipping to database # TODO: Do i have to lock the DB while writing? insert = self.get_resource("insert_rain.sql") self.execute_sql(insert, from_user, to_user, amount) # Add username of tipped user to confirmation message result += f"@{utl.esc_md(to_user)} " try: # Send success message to tipped user msg = f"You've been tipped with `{user_amount}` BIS by @{utl.esc_md(from_user)}" bot.send_message(to_user_id, msg, parse_mode=ParseMode.MARKDOWN) except Exception as e: error = f"Not possible to notify user '{to_user}' about rain" logging.debug(f"{error}: {e}") else: try: # Send error message to tipping user msg = f"{emo.ERROR} Not possible to send `{user_amount}` BIS to @{utl.esc_md(to_user)}" bot.send_message(from_user_id, msg, parse_mode=ParseMode.MARKDOWN) except Exception as e: error = f"Not possible to notify tipping user '{from_user}' about failed rain" logging.debug(f"{error}: {e}") # Check if at least one user got tipped if result.count("@") > 1: # TODO: Use 'split_msg' from utils here # Send success message bot.edit_message_text(chat_id=message.chat_id, message_id=message.message_id, text=result, parse_mode=ParseMode.MARKDOWN) else: # Send error message bot.edit_message_text( chat_id=message.chat_id, message_id=message.message_id, text=f"{emo.ERROR} Rain not executed. Something went wrong...")