This repository has been archived on 2025-02-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cctweaked_banking/server.py
2025-01-29 20:33:36 +01:00

746 lines
34 KiB
Python

import logging
import os
import typing_extensions
import websockets.exceptions
from flask import Flask, render_template, request, redirect, session
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin, current_user
from flask_sock import Sock, ConnectionClosed
import tracemalloc
import asyncio
from functools import wraps
import threading
import sys
import time
import json
import code
import queue
import logging
import random
import re
import copy
import sqlite3
from dotenv import load_dotenv, set_key, dotenv_values
from ujson import (
loads as load_json,
JSONDecodeError
)
logger = logging.getLogger("main")
logger.setLevel(logging.DEBUG) # Set global logging level
### --- PAYMENT LOGGER ---
payment_logger = logging.getLogger("logger.payment")
payment_logger.setLevel(logging.INFO)
# Create file handler for payment logs
payment_file_handler = logging.FileHandler("payment.log")
payment_file_handler.setLevel(logging.INFO)
# Custom formatter with "PAYMENT: " prefix
payment_formatter = logging.Formatter("PAYMENT: %(asctime)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
payment_file_handler.setFormatter(payment_formatter)
# Add handler to payment logger
payment_logger.addHandler(payment_file_handler)
### --- GENERAL LOGGER ---
other_logger = logging.getLogger("logger.other")
other_logger.setLevel(logging.DEBUG)
# Create file handler for general logs
other_file_handler = logging.FileHandler("other.log")
other_file_handler.setLevel(logging.DEBUG)
# Standard formatter
other_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
other_file_handler.setFormatter(other_formatter)
# Add handler to general logger
other_logger.addHandler(other_file_handler)
tracemalloc.start()
app = Flask(__name__)
app.secret_key = "goiehdrgiehrigvjikovgruhiojrvuhijvetrwghuijovetrghuighuighuijbvhuijvguhjiverghjuivegrahujvgerasjikvgesarjikovgaerijokpvregtoikjpvegrakjioverga#++#+#56904630873647843634t+34+#g3-34.,tt3ki"
sock = Sock(app)
dointhings = False
print("I am BankingSys server!")
connected_ws = {}
user_asso = {}
class banking_ws:
_lock = threading.Lock()
@classmethod
def send(cls, message):
# Lock to prevent race condition when iterating over connected clients
with cls._lock:
try:
for k, v in user_asso.items():
for i in v[2]:
i.send(message)
print("Send WS-Message to: ", k)
except Exception as e:
print("WS ERROR: ", e)
@classmethod
def extra_send(cls, dict, message):
# Lock to prevent race condition when iterating over connected clients
with cls._lock:
try:
for k in dict.keys():
dict[k][1].send(message)
print("Send Specific Dict WS-Message")
except Exception as e:
print("WS ERROR: ", e)
#DSSQL 5.0 ---
class EnvDB:
def __init__(self, db_file: str = "database.db"):
self.db_file = db_file
self.connection = sqlite3.connect(self.db_file)
self.cursor = self.connection.cursor()
self._initialize_db()
def _initialize_db(self):
"""Creates the key-value store table if it doesn't exist."""
self.cursor.execute("""
CREATE TABLE IF NOT EXISTS env_data (
key TEXT PRIMARY KEY,
value TEXT
)
""")
self.connection.commit()
def write(self, key: str, value: str):
"""Writes a key-value pair to the database."""
self.cursor.execute("REPLACE INTO env_data (key, value) VALUES (?, ?)", (key, value))
self.connection.commit()
def read(self, key: str) -> str:
"""Reads a value from the database by key."""
self.cursor.execute("SELECT value FROM env_data WHERE key = ?", (key,))
result = self.cursor.fetchone()
return result[0] if result else "Key not found"
def key_exists(self, key: str) -> bool:
"""Checks if a key exists in the database."""
self.cursor.execute("SELECT 1 FROM env_data WHERE key = ?", (key,))
return self.cursor.fetchone() is not None
def delete(self, key: str):
"""Deletes a key-value pair from the database."""
self.cursor.execute("DELETE FROM env_data WHERE key = ?", (key,))
self.connection.commit()
def close(self):
"""Closes the database connection."""
self.connection.close()
class internal:
class super_internal:
def send_local(ws, action, id, **kwargs):
msg: dict = {
"action": action,
"id": id,
**kwargs
}
ws.send(json.dumps(msg))
def send_global(ws, action, id, **kwargs):
msg: dict = {
"action": action,
"id": id,
**kwargs
}
banking_ws.send(json.dumps(msg))
class iterators:
def compress_inbox(username, prefix):
username = str(username).lower()
db = EnvDB()
if db.key_exists(f"{username}.{prefix}.count"):
cnt = int(db.read(f"{username}.{prefix}.count"))
else:
return False
new_db = {}
dsc = 0
for i in range(cnt):
if db.key_exists(f"{username}.{prefix}.{i}"):
new_db[f"{username}.{prefix}.{dsc}"] = db.read(f"{username}.{prefix}.{i}")
print("Wrote: ", i)
dsc += 1
else:
print("Key not foundd")
try:
for k, v in new_db.items():
EnvDB().write(k, v)
print("Opressor: ", k, v)
except Exception as e:
print("Compression Error: ", e)
db.write(f"{username}.{prefix}.count", dsc)
def flood_db(username, count):
username = str(username).lower()
EnvDB().write(f"{username}.privatemessage.count", str(count))
for i in range(int(count)):
EnvDB().write(f"{username}.privatemessage.{i}", f"Iteration {i}")
def userasso():
print(user_asso)
class user:
def auth_user(username: str.lower, password):
db = EnvDB()
passwd = db.read(username)
if passwd == password:
return True
else:
return False
def get_all_dict_ws_by_name(name):
ws_dict: list = []
dsses = dict(user_asso)
i = 0
try:
for k, v in dsses.items():
print("V: ", v)
for iv in v[2]:
ws_dict.append(iv)
i += 1
except Exception as e:
print("Name WS error: ", e)
if i > 0:
return ws_dict
else:
return False
def get_dict_pointer_by_ws(ws):
dsses = dict(user_asso)
try:
for k, v in dsses.items():
print("V: ", v)
i = 0
for iv in v[2]:
print(f"Baumis Horcrux: {i} ", iv)
if ws == iv:
return i
i += 1
return False
except Exception as e:
print("Pointer WS error: ", e)
def get_dict_pointer_by_uuid(uuid):
dsses = dict(user_asso)
try:
for k, v in dsses.items():
print("V: ", v)
i = 0
for iv in v[1]:
print(f"Cryings Horcrux: {i} ", iv)
if uuid == iv:
return i
i += 1
return False
except Exception as e:
print("Pointer UUID error: ", e)
def isLoggedIn(ws):
i = None
i = internal.user.get_dict_pointer_by_ws(ws=ws)
if i is False or i is None:
return False
else:
return True
class connection:
class terminate:
def client(username, uuid):
username = str(username).lower()
pointer = internal.user.get_dict_pointer_by_uuid(uuid=uuid)
user_asso[username][2][pointer].close()
del user_asso[username][0][pointer]
del user_asso[username][1][pointer]
del user_asso[username][2][pointer]
print(f"Successfully terminated {uuid}'s connection")
def all(username):
username = str(username).lower()
dsses = dict(user_asso)
try:
for k, v in dsses.items():
print("V: ", v)
i = 0
for iv in v[2]:
print(f"Mologo's Horcrux: {i} ", iv)
iv.close()
i += 1
del user_asso[username]
except Exception as e:
print("Terminate error: ", e)
print(f"Successfully terminated {username}'s connection")
class init:
def passwd(username, password):
username = str(username).lower()
db = EnvDB()
db.write(username, password)
def create(username, password):
username = str(username).lower()
db = EnvDB()
db.write(username, password)
db.write(f"{username}.amount", "0")
db.write(f"{username}.paymentmessage.count", "1")
db.write(f"{username}.paymentmessage.1", "Welcome to BankSYS by CIS and Befator Inc. Financial Systems!")
db.write(f"{username}.privatemessage.count", "1")
db.write(f"{username}.privatemessage.1", "Welcome to your Private messages! Other users can write you and these messages are Shown here.")
print(f"Created {username}")
def reinit(username):
username = str(username).lower()
db = EnvDB()
if db.key_exists(f"{username}.paymentmessage.count"):
for i in range(int(db.read(f"{username}.paymentmessage.count"))):
db.delete(f"{username}.paymentmessage.{i}")
if db.key_exists(f"{username}.privatemessage.count"):
for i in range(int(db.read(f"{username}.privatemessage.count"))):
db.delete(f"{username}.privatemessage.{i}")
db.write(f"{username}.amount", "0")
db.write(f"{username}.paymentmessage.count", "1")
db.write(f"{username}.paymentmessage.1", "Welcome to BankSYS by CIS and Befator Inc. Financial Systems!")
db.write(f"{username}.privatemessage.count", "1")
db.write(f"{username}.privatemessage.1", "Welcome to your Private messages! Other users can write you and these messages are Shown here.")
print(f"Reinitiated {username}")
def delete(username):
username = str(username).lower()
db = EnvDB()
if db.key_exists(f"{username}.paymentmessage.count"):
for i in range(int(db.read(f"{username}.paymentmessage.count"))):
db.delete(f"{username}.paymentmessage.{i}")
if db.key_exists(f"{username}.privatemessage.count"):
for i in range(int(db.read(f"{username}.privatemessage.count"))):
db.delete(f"{username}.privatemessage.{i}")
db.delete(f"{username}.amount")
db.delete(f"{username}.paymentmessage.count")
db.delete(f"{username}.privatemessage.count")
print(f"Deleted {username}")
class fail:
def credentials(ws, id, subject, value1):
internal.super_internal.send_local(ws=ws, id=id, value1=value1, action="displayMessage", value2=f"{subject}.fail.credentials")
def success(ws, id, subject, value1, **kwargs):
internal.super_internal.send_local(ws=ws, id=id, action="displayMessage", value1=value1, value2=f"{subject}.success", **kwargs)
def handle_brequrest(data, ws): #username = value1, password = value2
db = EnvDB()
if data:
print(data)
data: dict = load_json(data)
for key, value in data.items():
print(key, value)
print("C-End bom")
if data["action"] == "authenticate":
print("Trying to auth")
if "value1" in data and "value2" in data:
username = str(data["value1"]).lower()
print(username)
password = data["value2"]
passwd = db.read(username)
if password == passwd:
print(f"Successfully authenticated user {username}")
client_uuid = random.randint(1, 10000)
other_logger.info(f"The User {username} authenticated with uuid {client_uuid} from pc {data['id']}")
if username not in user_asso.keys():
user_asso[username] = [[data["id"]], [client_uuid], [ws]]
else:
user_asso[username][0].append(data["id"])
user_asso[username][1].append(client_uuid)
user_asso[username][2].append(ws)
print("User asso1: ", user_asso)
internal.success(ws=ws, id=-1, subject="auth", value1=f"Authentication Successful as {username}!", value3=client_uuid)
else:
print(f"USR_PASS: {password}, DB_PASS: {passwd} ")
other_logger.info(f"User {username} tried to authenticate from {data['id']} but password is wrong: USR_PASS: {password}, DB_PASS: {passwd} ")
internal.fail.credentials(ws=ws, id=-1, subject="auth", value1="Authentication Failure")
elif data["action"] == "reauth_server":
if "value1" in data and "value2" in data:
username = str(data["value1"]).lower()
password = data["value2"]
passwd = db.read(username)
if password == passwd:
print(f"Reauthed {username}, {data['id']}")
ds = list(user_asso.items())
for k, v in ds:
if v[0] == data["id"]:
user_asso[k][1].close()
del user_asso[k]
user_asso[username] = [data["id"], ws]
print(user_asso)
else:
internal.fail.credentials(ws=ws, id=-1, subject="reauth", value1="Authentication Failure")
elif data['action'] == "register":
if "value1" in data and "value2" in data:
username = str(data["value1"]).lower()
password = data['value2']
print(username, password)
print(db.key_exists(username))
if not db.key_exists(username):
print(f"Successfuly registerd user {username}!")
internal.user.init.create(username=username, password=password)
other_logger.info(f"Successfully registered user {username} form PC: {data['id']}")
internal.success(ws, id=-1, subject="register", value1=f"Registration Successful as {username}!")
else:
print(f"user {username} already taken!")
msg: dict = {
"action": "displayMessage",
"value1": f"Username {username} already taken!",
"value2": "register.fail.usernameTaken",
"id": -1
}
ws.send(json.dumps(msg))
else:
print("Transmission Incomplete")
elif data["action"] == "pay":
if "value1" in data and "value2" in data and "value3" in data and "value4" in data:
user = str(data["value1"]).lower()
passwd = data["value2"]
dest = str(data["value3"]).lower()
amt = data["value4"]
id = data["id"]
if not int(amt) > 0:
print("Negative amount")
msg: dict = {
"action": "displayMessage",
"value1": "Payamount has to be greater than 0 Steam Coins!",
"value2": "pay.fail.negative_amount",
"id": data["id"]
}
banking_ws.send(json.dumps(msg))
return
if not db.read(user):
print("Origin user not known")
msg: dict = {
"action": "displayMessage",
"value1": f"Specified Origint dose not exist! pay.fail.orgi_user for {user}",
"value2": "pay.fail.orig_user_unknown",
"id": data['id']
}
banking_ws.send(json.dumps(msg))
return
if not db.read(dest):
print("Destination user not known")
msg: dict = {
"action": "displayMessage",
"value1": f"Payment destination {dest} not Available! (pay.fail.dest_user for {dest})",
"value2": "pay.fail.unknown_dest",
"id": data['id']
}
banking_ws.send(json.dumps(msg))
return
if not db.read(user) == passwd:
print("Wrong credentials")
internal.fail.credentials(ws, id=-1, subject="pay", value1="Request authenticity could not be Verified (Wrong Username or Password)!")
return
print("No if clauses active")
if db.read(user) == passwd:
if not db.key_exists(f"{user}.amount"):
print("Origin has no Balance Key in DB")
return
if not db.key_exists(f"{dest}.amount"):
print("Origin has no Balance Key in DB")
return
source_amt = int(db.read(f"{user}.amount"))
try:
if source_amt >= amt:
print("Payment Authorized")
new_source_amt = int(int(source_amt) - int(amt))
db.write(f"{user}.amount", str(new_source_amt))
new_dest_amt = int(db.read(f"{dest}.amount")) + int(amt)
db.write(f"{dest}.amount", str(new_dest_amt))
print(f"User {user} paid {dest} {amt} SC from PC {id}")
internal.success(ws=ws, id=-1, subject="pay", value1=f"Payment Succesful! You Paid {dest} {amt} Steam Coins.")
payment_logger.info(f"From: {user}, To: {dest}, Amount: {amt}, PC: {data['id']}")
print("Yes in db" if dest in user_asso else "Not in db")
if dest in user_asso:
for k, v in user_asso.items():
if k == dest:
for i in v[1]:
msg: dict = {
"action": "displayMessage",
"value1": f"You Received {amt} Steam Coins from {user}!",
"value2": "pay.received",
"id": i
}
banking_ws.send(json.dumps(msg))
else:
if not db.key_exists(f"{dest}.paymentmessage.counter"):
db.write(f"{dest}.paymentmessage.counter", "0")
cnt = int(db.read(f"{dest}.paymentmessage.counter"))
db.write(f"{dest}.paymentmessage.{cnt+1}", f"You Received {amt} Steam Coins from {user}!")
cntpl1 = str(cnt+1)
db.write(f"{dest}.paymentmessage.counter", cntpl1)
print("Wrote offline message to db!")
else:
msg: dict = {
"action": "displayMessage",
"value1": "Not enough Steam Coins!",
"value2": "pay.fail.not_enough_money",
"id": data['id']
}
banking_ws.send(json.dumps(msg))
except Exception as e:
print("Payment Failed! ", e)
msg: dict = {
"action": "displayMessage",
"value1": "Payment Failed. Please see Console for Error!",
"value2": "pay.fail.unknown_error",
"id": data['id']
}
banking_ws.send(json.dumps(msg))
elif data["action"] == "get_balance":
if "value1" in data and "value2" in data:
user = str(data["value1"]).lower()
passwd = data["value2"]
if internal.user.auth_user(user, passwd):
balance = int(db.read(f"{user}.amount"))
internal.success(ws=ws, id=id, subject="balance", value1=f"You currently have {balance} Steam Coins in your Account!")
else:
internal.fail.credentials(ws, id=-1, subject="balance", value1="Balance could not be Requested! Wrong username, password.")
elif data["action"] == "logout":
try:
if "value1" in data and "value2" in data:
username = str(data["value1"]).lower()
password = data["value2"]
if internal.user.auth_user(username=username, password=password):
print(f"Logging out {username}!")
if not internal.user.isLoggedIn(ws=ws):
msg: dict = {
"action": "displayMessage",
"value1": "Logout failed",
"value2": "logout.fail.notloggedin",
"id": -1
}
ws.send(json.dumps(msg))
else:
print(f"Dsee'ing {username}")
i = internal.user.get_dict_pointer_by_ws(ws=ws)
del user_asso[username][0][i]
del user_asso[username][1][i]
del user_asso[username][2][i]
print(f"{username} was loggd out")
internal.success(ws=ws, id=-1, subject="logout", value1="Logout was Succesful")
else:
internal.fail.credentials(ws, id=-1, subject="logout", value1="Logout could not be Processed! Wrong username, password.")
else:
internal.super_internal.send_local(ws, id=-1, action="displayMessage", value1="Logout Failed. Missing Data", value2="logout.fail.missingdata")
except Exception as e:
print("Logout error: ", e)
elif data["action"] == "get_inbox":
if "value1" in data and "value2" in data and "value3" in data: #v1: usr, v2: pass, v3: pointer=> int/"cnt" ...
username = str(data["value1"]).lower()
password = data["value2"]
pointer = data["value3"]
if internal.user.auth_user(username, password):
if pointer == "cnt" or pointer == -1:
print("Sending pointer")
if db.key_exists(f"{username}.paymentmessage.count"):
time.sleep(1)
count = int(db.read(f"{username}.paymentmessage.count"))
msg: dict = {
"action": "displayMessage",
"value1": "",
"value2": "message_count",
"value3": count,
"id": data["id"]
}
banking_ws.send(json.dumps(msg))
else:
print("missing db key")
else:
print("Sending message")
time.sleep(1)
pointer = int(pointer)
if db.key_exists(f"{username}.paymentmessage.{pointer}"):
message = db.read(f"{username}.paymentmessage.{pointer}")
print(message)
msg: dict = {
"action": "inbox",
"value1": pointer,
"value2": message,
"id": data["id"]
}
banking_ws.send(json.dumps(msg))
else:
print("Auth Fail 1")
else:
print("Missing data 1")
elif data["action"] == "read_inbox":
if "value1" in data and "value2" in data and "value3" in data: #v1: usr, v2: pass, v3: pointer: int ...
username = str(data["value1"]).lower()
password = data["value2"]
pointer = data["value3"]
if internal.user.auth_user(username, password):
db.delete(f"{username}.paymentmessage.{int(pointer)}")
cur_point = db.read(f"{username}.paymentmessage.count")
db.write(f"{username}.paymentmessage.count", int(cur_point - 1))
internal.super_internal.iterators.compress_inbox(username, "paymentmessage")
print('Deleted message marked as "Read".')
#PRIVATE MESSAGES
elif data["action"] == "get_pm_inbox":
if "value1" in data and "value2" in data and "value3" in data: #v1: usr, v2: pass, v3: pointer=> int/"cnt" ...
username = str(data["value1"]).lower()
password = data["value2"]
pointer = data["value3"]
if internal.user.auth_user(username, password):
if pointer == "cnt" or pointer == -1:
print("Sending pointer")
#if db.key_exists(f"{username}.privatemessage.count"):
time.sleep(1)
count = int(db.read(f"{username}.privatemessage.count"))
msg: dict = {
"action": "displayMessage",
"value1": "",
"value2": "pm_message_count",
"value3": count,
"id": data["id"]
}
ws.send(json.dumps(msg))
# else:
# print("missing db key")
else:
print("Sending message")
time.sleep(1)
pointer = int(pointer)
#if db.key_exists(f"{username}.privatemessage.{pointer}"):
message = db.read(f"{username}.privatemessage.{pointer}")
print(message)
msg: dict = {
"action": "pm_inbox",
"value1": pointer,
"value2": message,
"id": data["id"]
}
ws.send(json.dumps(msg))
else:
print("Auth Fail 1")
else:
print("Missing data 1")
elif data["action"] == "read_pm_inbox":
if "value1" in data and "value2" in data and "value3" in data: #v1: usr, v2: pass, v3: pointer: int ...
username = str(data["value1"]).lower()
password = data["value2"]
pointer = data["value3"]
if internal.user.auth_user(username, password):
db.delete(f"{username}.privatemessage.{int(pointer)}")
cur_point = db.read(f"{username}.privatemessage.count")
db.write(f"{username}.privatemessage.count", int(cur_point - 1))
internal.super_internal.iterators.compress_inbox(username, "privatemessage")
print('Deleted message marked as "Read".')
elif data["action"] == "send_pm": #v 1-2: u/p, v3: destination, v4: message
if "value1" in data and "value2" in data and "value3" in data and data["value4"]:
username = str(data["value1"]).lower()
password = data["value2"]
dest = str(data["value3"]).lower()
message = data["value4"]
if internal.user.auth_user(username, password):
if db.key_exists(dest):
if not db.key_exists(f"{dest}.privatemessage.count"):
db.write(f"{dest}.privatemessage.count", "0")
cnt = int(db.read(f"{dest}.privatemessage.count"))
db.write(f"{dest}.privatemessage.{cnt+1}", message)
cntpl1 = str(cnt+1)
db.write(f"{dest}.privatemessage.count", cntpl1)
print("Wrote offline private message message to db!")
wsses = internal.user.get_all_dict_ws_by_name(dest)
for i in wsses:
msg: dict = {
"action": "displayMessage",
"value1": "You Received a Private message!",
"value2": "pm_inbox.received",
}
i.send(json.dumps(msg))
msg: dict = {
"action": "displayMessage",
"value1": "Message was send Successful!",
"value2": "pm_inbox.send.success",
"id": -1
}
ws.send(json.dumps(msg))
else:
msg: dict = {
"action": "displayMessage",
"value1": "Destination Unknown!",
"value2": "pm_inbox.dest.unknown",
"id": -1
}
ws.send(json.dumps(msg))
else:
internal.fail.credentials(ws=ws, id=data['id'], subject="pm_inbox", value1="Authentication Fail!")
elif data["action"] == "motd":
print("Sending MOTD")
internal.super_internal.send_local(ws=ws, action="motd", id=-1, value1=db.read("motd"))
else:
print("Non Action")
print("end user asso: ", user_asso)
@sock.route('/banking')
def banking(ws):
print("Anonymous added")
try:
while True:
data = ws.receive()
handle_brequrest(data, ws)
except Exception as e:
print(e)
finally:
print("Client disconnected!")
dsses = dict(user_asso)
print("Bommels ist Bommlisch verBömmelst")
try:
for k, v in dsses.items():
print("V: ", v)
i = 0
for iv in v[2]:
print(f"Dsees Horcrux: {i} ", iv)
if ws == iv:
print("Closed")
del user_asso[k][0][i]
del user_asso[k][1][i]
del user_asso[k][2][i]
print("Deleted 0, 1, 2")
break
i += 1
except Exception as e:
print("Closing error: ", e)
def run_flask():
app.run(host='0.0.0.0', port=5000, debug=True)
def repl_loop():
console = code.InteractiveConsole(globals()) # Pass globals for shared context
console.interact() # Start REPL
# Run REPL in a separate thread
threading.Thread(target=repl_loop, daemon=True).start()
if __name__ == "__main__":
print("I am BankingSys server!")
run_flask()
# Starten Sie Sanic im Hauptthread