nightly - 2025-09-20

This commit is contained in:
2025-09-21 00:09:19 -04:00
parent cbc20a2897
commit b5afe0ef48
20 changed files with 323 additions and 5 deletions

2
api/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
__pycache__
*/__pycache__

7
api/data/config.ini Normal file
View File

@@ -0,0 +1,7 @@
[db]
host = localhost
port = 3306
user = tam3
password = tam3
database = tam3

10
api/db.py Normal file
View File

@@ -0,0 +1,10 @@
from settings import read_config
from mysql.connector import connect
def session():
config = read_config()
conn = connect(**config["db"])
cur = conn.cursor()
return conn, cur

9
api/exceptions.py Normal file
View File

@@ -0,0 +1,9 @@
from fastapi import HTTPException, status
bad_key = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="API Key is bad, very bad."
)
not_found = HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Resource not found."
)

48
api/key.py Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/env python3
import string
from sys import argv
from repos import ApiKeyRepo
rdm_str = string.ascii_lowercase + string.digits
def generate():
if len(argv) < 3:
print("Please put name after the generate verb.")
quit()
new_key = ApiKeyRepo().create_api(argv[2])
print(new_key)
def list_keys():
result_keys = ApiKeyRepo().get_all()
for key in result_keys:
print(f"pc_name: {key.pc_name}")
print(key.api_key)
print("\n")
def delete_key():
if len(argv) < 3:
print("Please put api key to delete after the delete verb.")
quit()
del_status = ApiKeyRepo().delete(argv[2])
print(del_status)
if len(argv) < 2:
print("Please put action after api.py such as generate, list, or remove.")
quit()
else:
action = argv[1]
match action:
case "generate":
generate()
case "list":
list_keys()
case "delete":
delete_key()

View File

@@ -0,0 +1,13 @@
#!/bin/env python3
from fastapi import FastAPI
from sys import argv
from routers.prefixes import prefix_router
if argv[1] == "run":
app = FastAPI(title="TAM3 API Server", docs_url=None, redoc_url=None)
else:
app = FastAPI(title="TAM3 API Server")
app.include_router(prefix_router)

1
api/repos/__init__.py Normal file
View File

@@ -0,0 +1 @@
from .api_keys import ApiKey, ApiKeyRepo

43
api/repos/api_keys.py Normal file
View File

@@ -0,0 +1,43 @@
import random as r
import string
from dataclasses import dataclass
from .template import Repo
rdm_set = string.ascii_lowercase + string.digits
@dataclass
class ApiKey:
api_key: str
pc_name: str = ""
class ApiKeyRepo(Repo):
def check_api(self, api_key: str) -> bool:
self.cur.execute("SELECT * FROM api_keys WHERE api_key = %s", (api_key,))
result = self.cur.fetchone()
if result:
return True
else:
return False
def create_api(self, name: str) -> str:
while True:
new_key = "".join(r.choice(rdm_set) for i in range(16))
if not self.check_api(new_key):
break
self.cur.execute("INSERT INTO api_keys VALUES (%s, %s)", (new_key, name))
self.conn.commit()
return new_key
def get_all(self) -> list[ApiKey]:
self.cur.execute("SELECT * FROM api_keys")
results = self.cur.fetchall()
if not results:
return []
return [ApiKey(*r) for r in results]
def delete(self, api_key: str) -> str:
self.cur.execute("DELETE FROM api_keys WHERE api_key = %s", (api_key,))
self.conn.commit()
return "Key deleted successfully."

39
api/repos/prefixes.py Normal file
View File

@@ -0,0 +1,39 @@
from .template import Repo
from dataclasses import dataclass
from exceptions import not_found
@dataclass
class Prefix:
name: str
color: str = ""
weight: int = 0
class PrefixRepo(Repo):
def get_all(self) -> list[Prefix]:
self.cur.execute("SELECT * FROM prefixes ORDER BY weight, name")
results = self.cur.fetchall()
if not results:
return []
return [Prefix(*r) for r in results]
def get_one(self, prefix_name: str):
self.cur.execute("SELECT * FROM prefixes WHERE name = %s", (prefix_name,))
result = self.cur.fetchone()
if not result:
raise not_found
return Prefix(*result)
def add_one(self, prefix: Prefix) -> str:
self.cur.execute(
"REPLACE INTO prefixes VALUES (%s, %s, %s)",
(prefix.name, prefix.color, prefix.weight),
)
self.conn.commit()
return "Prefix inserted successfully."
def del_one(self, prefix_name: str) -> str:
self.cur.execute("DELETE FROM prefixes WHERE name = %s", (prefix_name,))
self.conn.commit()
return "Prefix deleted successfully."

6
api/repos/template.py Normal file
View File

@@ -0,0 +1,6 @@
from db import session
class Repo:
def __init__(self):
self.conn, self.cur = session()

0
api/routers/__init__.py Normal file
View File

26
api/routers/prefixes.py Normal file
View File

@@ -0,0 +1,26 @@
from fastapi import APIRouter
from repos.prefixes import Prefix, PrefixRepo
prefix_router = APIRouter(prefix="/api/prefixes")
@prefix_router.get("/")
def get_all_prefixes():
return PrefixRepo().get_all()
@prefix_router.get("/{prefix_name}/")
def get_one_prefix(prefix_name: str):
return PrefixRepo().get_one(prefix_name)
@prefix_router.post("/")
def post_one_prefix(p: Prefix):
rep_detail = PrefixRepo().add_one(p)
return {"detail": rep_detail}
@prefix_router.delete("/")
def del_one_prefix(prefix_name: str):
rep_detail = PrefixRepo().del_one(prefix_name)
return {"detail": rep_detail}

25
api/settings.py Normal file
View File

@@ -0,0 +1,25 @@
import os
from pathlib import Path
from configparser import ConfigParser
data_path = Path(os.getenv("TAM3_DATA_PATH", "data"))
data_path.mkdir(exist_ok=True)
def read_config():
config = ConfigParser()
config_path = data_path / "config.ini"
if config_path.is_file():
config.read(config_path)
return config
else:
config["db"] = {
"host": os.getenv("TAM3_DB_HOST", "localhost"),
"port": os.getenv("TAM3_DB_PORT", "3306"),
"user": os.getenv("TAM3_DB_USER", "tam3"),
"password": os.getenv("TAM3_DB_PASSWD", "tam3"),
"database": os.getenv("TAM3_DB_DATABASE", "tam3"),
}
with open(config_path, "w") as f:
config.write(f)
return config