def add_new_account(username): address = generate_account() private = address["private"] address = address["account"] sql = "INSERT INTO accounts (username, private_key, address, minimum, auto_receive, silence, active, percentage, opt_in) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)" val = ( username, private, address, to_raw(RECIPIENT_MINIMUM), True, False, False, 10, True, ) MYCURSOR.execute(sql, val) MYDB.commit() return { "username": username, "address": address, "private_key": private, "minimum": to_raw(RECIPIENT_MINIMUM), "silence": False, "balance": 0, "account_exists": True, }
def handle_projects(message): """ Handles creation and updates of crowdfunding (NanoCenter) projects """ parsed_text = parse_text(str(message.body)) response = text.CROWD_FUNDING["projects"] if (str(message.author).lower() in DONATION_ADMINS + TIPBOT_OWNER) and len(parsed_text) > 2: sql = "INSERT INTO projects (project, address) VALUES(%s, %s) ON DUPLICATE KEY UPDATE address=%s" val = (parsed_text[1], parsed_text[2], parsed_text[2]) MYCURSOR.execute(sql, val) MYDB.commit() add_history_record( username=str(message.author), action="project", comment_text=str(message.body)[:255], comment_or_message="message", comment_id=message.name, ) sql = "SELECT project, address FROM projects" MYCURSOR.execute(sql) results = MYCURSOR.fetchall() for result in results: response += "%s %s \n" % (result[0], result[1]) return response
def handle_balance(message): username = str(message.author) message_time = datetime.utcfromtimestamp( message.created_utc) # time the reddit message was created add_history_record( username=str(message.author), comment_or_message="message", reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"), action="balance", comment_id=message.name, comment_text=str(message.body)[:255], ) sql = "SELECT address FROM accounts WHERE username=%s" val = (username, ) MYCURSOR.execute(sql, val) result = MYCURSOR.fetchall() if len(result) > 0: results = check_balance(result[0][0]) response = text.BALANCE % ( result[0][0], from_raw(results[0]), from_raw(results[1]), result[0][0], ) return response return text.NOT_OPEN
def auto_receive(): count = 0 MYCURSOR.execute("SELECT username, address, private_key FROM accounts") myresult = MYCURSOR.fetchall() addresses = [str(result[1]) for result in myresult] private_keys = [str(result[2]) for result in myresult] MYDB.commit() pendings = get_pendings(addresses, threshold=nano_to_raw(PROGRAM_MINIMUM)) # get any pending blocks from our address for address, private_key in zip(addresses, private_keys): # allow 5 transactions to be received per cycle. If the bot gets transaction spammed, at least it won't be # locked up receiving. if count >= 5: break try: if pendings["blocks"][address]: for sent_hash in pendings["blocks"][address]: # address, private_key, dictionary where the blocks are the keys open_or_receive_block(address, private_key, sent_hash) count += 1 if count >= 2: break except KeyError: pass except Exception as e: print(e)
def handle_balance(message): username = str(message.author) message_time = datetime.utcfromtimestamp( message.created_utc) # time the reddit message was created add_history_record( username=str(message.author), comment_or_message="message", reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"), action="balance", comment_id=message.name, comment_text=str(message.body)[:255], ) sql = "SELECT address FROM accounts WHERE username=%s" val = (username, ) MYCURSOR.execute(sql, val) result = MYCURSOR.fetchall() if len(result) > 0: results = check_balance(result[0][0]) response = ( "At address %s:\n\nAvailable: %s Nano\n\nUnpocketed: %s Nano\n\nNano " "will be pocketed automatically unless the transaction is below " "0.0001 Nano." "\n\nhttps://nanocrawler.cc/explorer/account/%s" % (result[0][0], results[0] / 10**30, results[1] / 10**30, result[0][0])) return response return "You do not have an open account yet"
def handle_silence(message): message_time = datetime.utcfromtimestamp( message.created_utc) # time the reddit message was created username = str(message.author) add_history_record( username=str(message.author), action="silence", comment_or_message="message", comment_id=message.name, reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"), ) parsed_text = parse_text(str(message.body)) if len(parsed_text) < 2: response = text.SILENCE["parse_error"] return response if parsed_text[1] == "yes": sql = "UPDATE accounts SET silence = TRUE WHERE username = %s " val = (username, ) MYCURSOR.execute(sql, val) response = text.SILENCE["yes"] elif parsed_text[1] == "no": sql = "UPDATE accounts SET silence = FALSE WHERE username = %s" val = (username, ) MYCURSOR.execute(sql, val) response = text.SILENCE["no"] else: response = text.SILENCE["yes_no"] MYDB.commit() return response
def handle_create(message): message_time = datetime.utcfromtimestamp( message.created_utc) # time the reddit message was created add_history_record( username=str(message.author), comment_or_message="message", reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"), action="create", comment_id=message.name, comment_text=str(message.body)[:255], ) username = str(message.author) sql = "SELECT address FROM accounts WHERE username=%s" val = (username, ) MYCURSOR.execute(sql, val) result = MYCURSOR.fetchall() if len(result) is 0: address = tipper_functions.add_new_account(username)["address"] response = WELCOME_CREATE % (address, address) message_recipient = TIP_BOT_USERNAME subject = "send" message_text = "send 0.001 %s" % username sql = "INSERT INTO messages (username, subject, message) VALUES (%s, %s, %s)" val = (message_recipient, subject, message_text) MYCURSOR.execute(sql, val) MYDB.commit() # reddit.redditor(message_recipient).message(subject, message_text) else: response = text.ALREADY_EXISTS % (result[0][0], result[0][0]) return response
def list_messages(): MYCURSOR.execute("SELECT * FROM messages") myresult = MYCURSOR.fetchall() MYDB.commit() for res in myresult: print(res) return myresult
def get_user_settings(recipient_username, recipient_address=""): """ :param recipient_username: str :param recipient_address: str :return: 3 items to unpack - int, str, bool """ user_minimum = -1 silence = False if recipient_username: sql = "SELECT minimum, address, silence FROM accounts WHERE username = %s" val = (recipient_username,) MYCURSOR.execute(sql, val) myresult = MYCURSOR.fetchall() if len(myresult) > 0: user_minimum = int(myresult[0][0]) silence = myresult[0][2] if not recipient_address: recipient_address = myresult[0][1] return { "name": recipient_username, "minimum": user_minimum, "address": recipient_address, "silence": silence, }
def backup_keys(): sql = "SELECT username, address, private_key FROM accounts" MYCURSOR.execute(sql) results = MYCURSOR.fetchall() MYDB.commit() with open("../backup", "w") as f: for result in results: f.write(result[0] + "," + result[1] + "," + result[2] + "\n")
def init_projects(): MYCURSOR.execute( "CREATE TABLE projects (" "project VARCHAR(255) PRIMARY KEY, " "address VARCHAR(255)" ")" ) MYDB.commit()
def query_sql(sql, val=None): if val: MYCURSOR.execute(sql, val) else: MYCURSOR.execute(sql) results = MYCURSOR.fetchall() MYDB.commit() return results
def exec_sql(sql, val): """ Makes sql stuff easier to mock, rather than mocking execute and fetchall :param sql: :param val: :return: """ MYCURSOR.execute(sql, val) MYDB.commit()
def backup_history(): sql = "SELECT * FROM history" MYCURSOR.execute(sql) results = MYCURSOR.fetchall() MYDB.commit() with open("../backup_history", "w") as f: for result in results: for r in result: f.write(str(r) + ";") f.write("\n")
def init_subreddits(): MYCURSOR.execute( "CREATE TABLE subreddits (" "subreddit VARCHAR(255) PRIMARY KEY, " "reply_to_comments BOOL, " "footer VARCHAR(255), " "status VARCHAR(255) " ")" ) MYDB.commit()
def list_returns(status=None): if status: MYCURSOR.execute("SELECT * FROM returns WHERE return_status=%s", (status,)) else: MYCURSOR.execute("SELECT * FROM returns") myresult = MYCURSOR.fetchall() MYDB.commit() for res in myresult: print(res) return myresult
def init_messages(): MYCURSOR.execute( "CREATE TABLE messages (" "id INT AUTO_INCREMENT PRIMARY KEY, " "username VARCHAR(255), " "subject VARCHAR(255), " "message VARCHAR(5000) " ")" ) MYDB.commit()
def check_registered_by_address(address): address = address.split("_")[1] if shared.CURRENCY == "Nano": sql = "SELECT username FROM accounts WHERE address=%s" val = ("nano_" + address,) MYCURSOR.execute(sql, val) result = MYCURSOR.fetchall() if len(result) > 0: return result[0][0] sql = "SELECT username FROM accounts WHERE address=%s" val = ("xrb_" + address,) MYCURSOR.execute(sql, val) result = MYCURSOR.fetchall() if len(result) > 0: return result[0][0] elif shared.CURRENCY == "Banano": sql = "SELECT username FROM accounts WHERE address=%s" val = ("ban_" + address,) MYCURSOR.execute(sql, val) result = MYCURSOR.fetchall() if len(result) > 0: return result[0][0] return None
def add_subreddit( subreddit, reply_to_comments=True, footer="", status="friendly", minimum=PROGRAM_MINIMUM, ): sql = "INSERT INTO subreddits (subreddit, reply_to_comments, footer, status, minimum) VALUES (%s, %s, %s, %s, %s)" val = (subreddit, reply_to_comments, footer, status, minimum) MYCURSOR.execute(sql, val) MYDB.commit()
def message_in_database(message): sql = "SELECT * FROM history WHERE comment_id = %s" val = (message.name,) MYCURSOR.execute(sql, val) results = MYCURSOR.fetchall() if len(results) > 0: LOGGER.info("Found previous messages for %s: " % message.name) for result in results: LOGGER.info(result) return True return False
def all_pendings(threshold): threshold = float(threshold) MYCURSOR.execute("SELECT username, address FROM accounts") myresult = MYCURSOR.fetchall() usernames = [str(result[0]) for result in myresult] addresses = [str(result[1]) for result in myresult] MYDB.commit() pendings = tipper_rpc.get_pendings(addresses, threshold=to_raw(threshold)) for username, address in zip(usernames, addresses): if pendings["blocks"][address]: print(username, address, pendings["blocks"][address])
def handle_opt_in(message): add_history_record( username=str(message.author), action="opt-in", comment_or_message="message", comment_id=message.name, reddit_time=datetime.utcfromtimestamp( message.created_utc).strftime("%Y-%m-%d %H:%M:%S"), ) sql = "UPDATE accounts SET opt_in = TRUE WHERE username = %s" MYCURSOR.execute(sql, (str(message.author), )) MYDB.commit() response = text.OPT_IN return response
def total_funds(): MYCURSOR.execute("SELECT username, address FROM accounts") myresult = MYCURSOR.fetchall() usernames = [str(result[0]) for result in myresult] addresses = [str(result[1]) for result in myresult] MYDB.commit() balance = 0 for username, address in zip(usernames, addresses): balance new_balance = tipper_rpc.check_balance(address) temp_balance = new_balance[0] / 10**30 + new_balance[1] / 10**30 if temp_balance >= 50: print(username, temp_balance, address) balance += temp_balance print("Total Nano: ", balance)
def send_pm(recipient, subject, body, bypass_opt_out=False): opt_in = True # If there is not a bypass to opt in, check the status if not bypass_opt_out: sql = "SELECT opt_in FROM accounts WHERE username=%s" MYCURSOR.execute(sql, (recipient,)) opt_in = MYCURSOR.fetchall()[0][0] MYDB.commit() # if the user has opted in, or if there is an override to send the PM even if they have not if opt_in or not bypass_opt_out: sql = "INSERT INTO messages (username, subject, message) VALUES (%s, %s, %s)" val = (recipient, subject, body) MYCURSOR.execute(sql, val) MYDB.commit()
def allowed_request(username, seconds=30, num_requests=5): """Spam prevention :param username: str (username) :param seconds: int (time period to allow the num_requests) :param num_requests: int (number of allowed requests) :return: """ sql = "SELECT sql_time FROM history WHERE username=%s" val = (str(username), ) MYCURSOR.execute(sql, val) myresults = MYCURSOR.fetchall() if len(myresults) < num_requests: return True else: return (datetime.fromtimestamp(time.time()) - myresults[-5][0]).total_seconds() > seconds
def handle_delete_project(message): parsed_text = parse_text(str(message.body)) if ((str(message.author) == TIPBOT_OWNER) or (str(message.author).lower() == "rockmsockmjesus")) and len(parsed_text) > 1: sql = "DELETE FROM projects WHERE project=%s" val = (parsed_text[1], ) MYCURSOR.execute(sql, val) MYDB.commit() response = text.CROWD_FUNDING["projects"] sql = "SELECT project, address FROM projects" MYCURSOR.execute(sql) results = MYCURSOR.fetchall() for result in results: response += "%s %s \n" % (result[0], result[1]) return response
def handle_opt_in(message): add_history_record( username=str(message.author), action="opt-in", comment_or_message="message", comment_id=message.name, reddit_time=datetime.utcfromtimestamp( message.created_utc).strftime("%Y-%m-%d %H:%M:%S"), ) sql = "UPDATE accounts SET opt_in = TRUE WHERE username = %s" MYCURSOR.execute(sql, (str(message.author), )) MYDB.commit() response = ( "Welcome back! You have opted back in. Your account will be restored with the same address, " "though any Nano you had may have already been returned or donated already." ) return response
def add_history_record( username=None, action=None, sql_time=None, address=None, comment_or_message=None, recipient_username=None, recipient_address=None, amount=None, hash=None, comment_id=None, notes=None, reddit_time=None, comment_text=None, subreddit=None, ): if sql_time is None: sql_time = time.strftime("%Y-%m-%d %H:%M:%S") sql = ( "INSERT INTO history (username, action, sql_time, address, comment_or_message, recipient_username, " "recipient_address, amount, hash, comment_id, notes, reddit_time, comment_text, return_status, subreddit) " "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" ) val = ( username, action, sql_time, address, comment_or_message, recipient_username, recipient_address, amount, hash, comment_id, notes, reddit_time, comment_text, None, subreddit, ) # todo make sure the row id is atomic MYCURSOR.execute(sql, val) MYDB.commit() return MYCURSOR.lastrowid
def init_accounts(): MYCURSOR.execute( "CREATE TABLE accounts (" "username VARCHAR(255) PRIMARY KEY, " "address VARCHAR(255), " "private_key VARCHAR(255), " "key_released BOOL, " "minimum VARCHAR(255), " "notes VARCHAR(255), " "auto_receive BOOL, " "silence BOOL, " "active BOOL, " "percentage VARCHAR(255), " "opt_in BOOL" ")" ) MYDB.commit()
def init_returns(): MYCURSOR.execute( "CREATE TABLE returns (" "id INT AUTO_INCREMENT PRIMARY KEY, " "username VARCHAR(255), " "reddit_time TIMESTAMP, " "sql_time TIMESTAMP, " "recipient_username VARCHAR(255), " "recipient_address VARCHAR(255), " "amount VARCHAR(255), " "hash VARCHAR(255), " "comment_id VARCHAR(255), " "return_status VARCHAR(255), " "history_id INT" ")" ) MYDB.commit()