From 6ffdf7a279fc80608e86a37ac56cae2dd41bce34 Mon Sep 17 00:00:00 2001 From: spla Date: Thu, 4 Apr 2024 21:30:23 +0200 Subject: [PATCH] save registered user id, username, created_at and service to Postgresql database --- README.md | 3 +- app/libraries/database.py | 222 ++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + xmpp.py | 16 ++- 4 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 app/libraries/database.py diff --git a/README.md b/README.md index 0652cb6..2a49320 100644 --- a/README.md +++ b/README.md @@ -37,5 +37,6 @@ Before running `python xmpp.py`: Enjoy! -3.4.2024 - total refactor, adding realtime replies thanks to Mastodon's Streaming API +3.4.2024 - total refactor, adding realtime replies thanks to Mastodon's Streaming API +4.4.2024 - save registered user id, username, created_at and service to Postgresql database diff --git a/app/libraries/database.py b/app/libraries/database.py new file mode 100644 index 0000000..225c3f6 --- /dev/null +++ b/app/libraries/database.py @@ -0,0 +1,222 @@ +import os +import sys +import random +import psycopg2 +from psycopg2 import sql +from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT +from getpass import getpass +import pdb + +class Database(): + + name = 'database library' + + def __init__(self, config_file=None, db=None, db_user=None, db_user_password=None, service=None): + + self.config_file = "config/db_config.txt" + self.db = self.__get_parameter("db", self.config_file) + self.db_user = self.__get_parameter("db_user", self.config_file) + self.db_user_password = self.__get_parameter("db_user_password", self.config_file) + self.service = self.__get_parameter("service", self.config_file) + + db_setup = self.__check_dbsetup(self) + + if not db_setup: + + self.db = input("\ndatabase name: ") + self.db_user = input("\ndatabase user: ") + self.db_user_password = getpass("\ndatabase user password: ") + self.service = input("\nservice: ") + + self.__createdb(self) + self.__create_config(self) + self.__write_config(self) + + def user_save(self, id, username, date, service): + + insert_sql = "INSERT INTO users(id, username, created_at, service) VALUES(%s,%s,%s,%s) ON CONFLICT DO NOTHING" + + conn = None + + try: + + conn = psycopg2.connect(database=self.db, user=self.db_user, password="", host="/var/run/postgresql", port="5432") + + cur = conn.cursor() + + cur.execute(insert_sql, (id, username, date, service)) + + conn.commit() + + cur.close() + + except (Exception, psycopg2.DatabaseError) as error: + + print(error) + + finally: + + if conn is not None: + + conn.close() + + @staticmethod + def __check_dbsetup(self): + + db_setup = False + + try: + + conn = None + + conn = psycopg2.connect(database = self.db, user = self.db_user, password = self.db_user_password, host = "/var/run/postgresql", port = "5432") + + cur = conn.cursor() + + cur.execute("select * from information_schema.tables where table_name=(%s)", (self.db,)) + + db_setup = bool(cur.rowcount) + + except (Exception, psycopg2.DatabaseError) as error: + + print(error) + + return db_setup + + @staticmethod + def __createdb(self): + + conn = None + + try: + + conn = psycopg2.connect(dbname='postgres', + user=self.db_user, host='', + password=self.db_user_password) + + conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) + + cur = conn.cursor() + + print(f"Creating database {self.db}. Please wait...") + + cur.execute(sql.SQL("CREATE DATABASE {}").format( + sql.Identifier(self.db)) + ) + print(f"Database {self.db} created!\n") + + self.__dbtables_schemes(self) + + except (Exception, psycopg2.DatabaseError) as error: + + print(error) + + finally: + + if conn is not None: + + conn.close() + + @staticmethod + def __dbtables_schemes(self): + + table = "users" + sql = f"create table {table} (id bigint, username varchar, created_at date, service varchar)" + self.__create_table(self, table, sql) + + index = "users_pkey" + sql_index = f'CREATE UNIQUE INDEX {index} ON {table} (id, username)' + self.__create_index(self, table, index, sql_index) + + @staticmethod + def __create_table(self, table, sql): + + conn = None + + try: + + conn = psycopg2.connect(database = self.db, user = self.db_user, password = self.db_user_password, host = "/var/run/postgresql", port = "5432") + + cur = conn.cursor() + + print(f"Creating table {table}") + + cur.execute(sql) + + conn.commit() + + print(f"Table {table} created!\n") + + except (Exception, psycopg2.DatabaseError) as error: + + print(error) + + finally: + + if conn is not None: + + conn.close() + + @staticmethod + def __create_index(self, table, index, sql_index): + + conn = None + + try: + + conn = psycopg2.connect(database = self.db, user = self.db_user, password = "", host = "/var/run/postgresql", port = "5432") + cur = conn.cursor() + + print(f"Creating index...{index}") + # Create the table in PostgreSQL database + cur.execute(sql_index) + + conn.commit() + + print(f"Index {index} created!\n") + + except (Exception, psycopg2.DatabaseError) as error: + + print(error) + + finally: + + if conn is not None: + + conn.close() + + def __get_parameter(self, parameter, config_file): + + if not os.path.isfile(config_file): + print(f"File {config_file} not found..") + return + + with open( config_file ) as f: + for line in f: + if line.startswith( parameter ): + return line.replace(parameter + ":", "").strip() + + print(f"{config_file} Missing parameter {parameter}") + + sys.exit(0) + + @staticmethod + def __create_config(self): + + if not os.path.exists('config'): + + os.makedirs('config') + + if not os.path.exists(self.config_file): + + print(self.config_file + " created!") + with open(self.config_file, 'w'): pass + + @staticmethod + def __write_config(self): + + with open(self.config_file, 'a') as the_file: + + the_file.write(f'db: {self.db}\ndb_user: {self.db_user}\ndb_user_password: {self.db_user_password}\nservice: {self.service}') + + print(f"adding parameters to {self.config_file}\n") diff --git a/requirements.txt b/requirements.txt index bdfcd87..68c9e34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ Mastodon.py unidecode +psycopg2 diff --git a/xmpp.py b/xmpp.py index d51ecad..d03f97c 100644 --- a/xmpp.py +++ b/xmpp.py @@ -2,19 +2,21 @@ from app.libraries.setup import Setup from app.libraries.mentions import Mentions from app.libraries.ejabberdapi import Ejabberd from app.libraries.strings import Strings +from app.libraries.database import Database from mastodon import Mastodon, StreamListener import sys import humanize import datetime as dt -from datetime import datetime, timedelta +from datetime import datetime, date, timedelta +import pdb def check_activity(username): active = False - account_id = mastodon.account_lookup(username).id + account = mastodon.account_lookup(username) - act_st = mastodon.account_statuses(account_id) + act_st = mastodon.account_statuses(account.id) active_post = 0 @@ -28,7 +30,7 @@ def check_activity(username): active = True - return active + return active, account class Listener(StreamListener): @@ -48,7 +50,7 @@ class Listener(StreamListener): if query_word == strings.register_str: - active = check_activity(username) + active, account = check_activity(username) if active: @@ -68,6 +70,8 @@ class Listener(StreamListener): mastodon.status_post(post, in_reply_to_id=status_id, visibility='direct') + db.user_save(account.id, username, date.today(), db.service) + else: mastodon.status_post(f'@{username}, {text}', in_reply_to_id=status_id, visibility='direct') @@ -164,4 +168,6 @@ if __name__ == '__main__': strings = Strings() + db = Database() + mastodon.stream_user(Listener())