BIG rename

This commit is contained in:
C committed 2025-10-26 15:49:11 -07:00
1 parent 77db374418
commit 0bc06358e8
19 files changed
+95 -127

No files matched your search

+1
View File
@@ -33,3 +33,4 @@ studspider.db-journal
.states .states
assets/external/ assets/external/
__pycache__/ __pycache__/
win/
+4 -4
View File
@@ -1,4 +1,4 @@
# Studspider # studspider
![Static Badge](https://img.shields.io/badge/python-3.13.7-blue?logo=python) ![Static Badge](https://img.shields.io/badge/code_style-black-black) ![Static Badge](https://img.shields.io/badge/license-MPL-orange) ![Static Badge](https://img.shields.io/badge/python-3.13.7-blue?logo=python) ![Static Badge](https://img.shields.io/badge/code_style-black-black) ![Static Badge](https://img.shields.io/badge/license-MPL-orange)
@@ -11,14 +11,14 @@ is a tool used to talk to brickset.com and a square inventory to pull lego set i
Clone the project Clone the project
```bash ```bash
git clone http://git.traps.moe/ph0sgene/edderkop.git git clone http://git.traps.moe/ph0sgene/studspider.git
git checkout uv git checkout uv
``` ```
Go to the project directory Go to the project directory
```bash ```bash
cd edderkop cd studspider
``` ```
Install dependencies Install dependencies
@@ -30,7 +30,7 @@ Install dependencies
Start the server Start the server
```bash ```bash
uvx run edderkop.py uvx run studspider.py
``` ```
+1 -1
View File
@@ -1,5 +1,5 @@
[project] [project]
name = "edderkop" name = "studpider"
version = "0.1.0" version = "0.1.0"
description = "" description = ""
authors = [{ name = "CF", email = "ph0sgene@pm.me" }] authors = [{ name = "CF", email = "ph0sgene@pm.me" }]
+9 -9
View File
@@ -1,19 +1,19 @@
from setuptools import setup from setuptools import setup
setup( setup(
name='Edderkop', name="studspider",
version='0.1', version="0.1",
description='Bricket + Square integration application', description="Bricket + Square integration application",
author='CF', author="CF",
author_email='chris-forst@pm.me', author_email="chris-forst@pm.me",
packages=['src'], packages=["src"],
package_dir={'': 'src'}, package_dir={"": "src"},
install_requires=[ install_requires=[
# List your project dependencies here # List your project dependencies here
], ],
entry_points={ entry_points={
'console_scripts': [ "console_scripts": [
'main=main:main', # Adjust this line based on your main function "main=main:main", # Adjust this line based on your main function
], ],
}, },
) )
+3 -2
View File
@@ -9,7 +9,8 @@ import aiohttp
import json import json
import dotenv import dotenv
from typing import Dict, Any from typing import Dict, Any
from . import throttler import throttler
Throttler = throttler.GlobalThrottler Throttler = throttler.GlobalThrottler
dotenv.load_dotenv() dotenv.load_dotenv()
@@ -23,7 +24,7 @@ class AsyncBricksetAPI:
self.password = os.getenv("BRICKSET_PASS") self.password = os.getenv("BRICKSET_PASS")
self.api_key = os.getenv("BRICKSET_API_KEY") self.api_key = os.getenv("BRICKSET_API_KEY")
self.debug = debug self.debug = debug
self.headers = {"UserAgent": "Edderkop/0.1"} self.headers = {"UserAgent": "studspider/0.1"}
self.throttler = Throttler(rate_limit=500, period=60) self.throttler = Throttler(rate_limit=500, period=60)
self.user_hash = None self.user_hash = None
self.logger = logger self.logger = logger
+7 -3
View File
@@ -6,9 +6,9 @@ import uuid
import re import re
from time import time from time import time
from . import db import db
from . import get_sq_env import get_sq_env
def get_set_number(text: str) -> int: def get_set_number(text: str) -> int:
@@ -106,10 +106,14 @@ async def acat2id(cat_id: str):
{ {
"id": obj["id"], "id": obj["id"],
"name": obj.get("item_data", {}).get("name", "Unknown"), "name": obj.get("item_data", {}).get("name", "Unknown"),
"number": None if not obj.get("item_data", {}).get("name", "") else ( "number": (
None
if not obj.get("item_data", {}).get("name", "")
else (
get_set_number(obj.get("item_data", {}).get("name", "")) get_set_number(obj.get("item_data", {}).get("name", ""))
if re.findall(r"\d{5}", obj.get("item_data", {}).get("name", "")) if re.findall(r"\d{5}", obj.get("item_data", {}).get("name", ""))
else None else None
)
), ),
"updated_at": obj.get("updated_at"), "updated_at": obj.get("updated_at"),
"version": obj.get("version"), "version": obj.get("version"),
+2 -2
View File
@@ -14,9 +14,9 @@ debug = False # Set to True to enable debug output
def login(username, password): def login(username, password):
url = "https://brickset.com/api/v3.asmx/login" url = "https://brickset.com/api/v3.asmx/login"
headers = {"UserAgent": "Edderkop/0.1"} headers = {"UserAgent": "studspider/0.1"}
params = { params = {
"UserAgent": "Edderkop/0.1", "UserAgent": "studspider/0.1",
"username": username, "username": username,
"password": password, "password": password,
"apiKey": BRICKSET_API_KEY, "apiKey": BRICKSET_API_KEY,
+15 -7
View File
@@ -1,12 +1,15 @@
import aiosqlite import aiosqlite
from time import time from time import time
time = int(time()) # we dont need no stinkin floats time = int(time()) # we dont need no stinkin floats
# db = await aiosqlite.connect("edderkop.db") # type: ignore # db = await aiosqlite.connect("studspider.db") # type: ignore
async def close(db): async def close(db):
await db.close() await db.close()
async def fetch(table, sqobj): async def fetch(table, sqobj):
""" """
Asynchronously fetch a record from the REVIEW table by sq_object. Asynchronously fetch a record from the REVIEW table by sq_object.
@@ -16,13 +19,16 @@ async def fetch(table, sqobj):
Returns: Returns:
dict or None: The fetched record as a dictionary, or None if not found. dict or None: The fetched record as a dictionary, or None if not found.
""" """
async with aiosqlite.connect("edderkop.db") as db: # type: ignore async with aiosqlite.connect("studspider.db") as db: # type: ignore
async with db.execute(f"SELECT * FROM {table} WHERE sq_object = {sqobj}") as cursor: async with db.execute(
f"SELECT * FROM {table} WHERE sq_object = {sqobj}"
) as cursor:
async for row in cursor: async for row in cursor:
return row return row
return None return None
async def upsert(table: str, data: dict, unique_key: str) -> bool: async def upsert(table: str, data: dict, unique_key: str) -> bool:
""" """
Asynchronously insert or update a record in the specified table. Asynchronously insert or update a record in the specified table.
@@ -37,9 +43,11 @@ async def upsert(table: str, data: dict, unique_key: str) -> bool:
""" """
print(f"Upserting into {table}: {data}") print(f"Upserting into {table}: {data}")
columns = ', '.join(data.keys()) columns = ", ".join(data.keys())
placeholders = ', '.join('?' * len(data)) placeholders = ", ".join("?" * len(data))
updates = ', '.join(f"{col}=excluded.{col}" for col in data.keys() if col != unique_key) updates = ", ".join(
f"{col}=excluded.{col}" for col in data.keys() if col != unique_key
)
sql = f""" sql = f"""
INSERT INTO {table} ({columns}) INSERT INTO {table} ({columns})
@@ -47,7 +55,7 @@ async def upsert(table: str, data: dict, unique_key: str) -> bool:
ON CONFLICT({unique_key}) DO UPDATE SET ON CONFLICT({unique_key}) DO UPDATE SET
{updates}; {updates};
""" """
async with aiosqlite.connect("edderkop.db") as db: # type: ignore async with aiosqlite.connect("studspider.db") as db: # type: ignore
async with db.execute(sql, tuple(data.values())) as cursor: async with db.execute(sql, tuple(data.values())) as cursor:
await db.commit() await db.commit()
return True return True
+1 -1
View File
@@ -15,7 +15,7 @@ class BricksetAPI:
self.password = os.getenv("BRICKSET_PASS") self.password = os.getenv("BRICKSET_PASS")
self.api_key = os.getenv("BRICKSET_API_KEY") self.api_key = os.getenv("BRICKSET_API_KEY")
self.debug = debug self.debug = debug
self.headers = {"UserAgent": "Edderkop/0.1"} self.headers = {"UserAgent": "studspider/0.1"}
self.user_hash = None self.user_hash = None
def login(self) -> Dict[str, Any]: def login(self) -> Dict[str, Any]:
+5 -5
View File
@@ -6,21 +6,21 @@ import os
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Get the absolute path to edderkop.db in the project root # Get the absolute path to studspider.db in the project root
DEFAULT_DB_PATH = os.path.join( DEFAULT_DB_PATH = os.path.join(
os.path.dirname(os.path.dirname(__file__)), "edderkop.db" os.path.dirname(os.path.dirname(__file__)), "studspider.db"
) )
if not os.path.exists(DEFAULT_DB_PATH): if not os.path.exists(DEFAULT_DB_PATH):
raise FileNotFoundError(f"Database file not found at {DEFAULT_DB_PATH}") raise FileNotFoundError(f"Database file not found at {DEFAULT_DB_PATH}")
print('Please run "src/scripts/EDDERKOP.SQL" to setup the database.') print('Please run "src/scripts/studspider.SQL" to setup the database.')
os.exit(0) os.exit(0)
class AsyncSchedulerDB: class AsyncSchedulerDB:
""" """
Asynchronous SQLite database manager for APScheduler. Asynchronous SQLite database manager for APScheduler.
Handles job storage, retrieval, and database operations using the main edderkop.db database. Handles job storage, retrieval, and database operations using the main studspider.db database.
""" """
def __init__(self, db_path: str = DEFAULT_DB_PATH): def __init__(self, db_path: str = DEFAULT_DB_PATH):
@@ -29,7 +29,7 @@ class AsyncSchedulerDB:
Args: Args:
db_path (str, optional): Path to the SQLite database file. db_path (str, optional): Path to the SQLite database file.
Defaults to edderkop.db in project root. Defaults to studspider.db in project root.
""" """
self.db_path = db_path self.db_path = db_path
self._initialized = False self._initialized = False
+2 -2
View File
@@ -74,7 +74,7 @@ async def handle_post(request):
return True return True
else: else:
return aiohttp.web.Response(status=400, text="400 Bad Request.") return aiohttp.web.Response(status=400, text="400 Bad Request.")
result = {"message": f"Edderkop/0.1 received command: {reqdata}"} result = {"message": f"studspider/0.1 received command: {reqdata}"}
return aiohttp.web.json_response(status=200, data=result) return aiohttp.web.json_response(status=200, data=result)
@@ -108,6 +108,6 @@ async def main():
if __name__ == "__main__": if __name__ == "__main__":
print(generate_toilet_banner("Edderkop v0.1")) print(generate_toilet_banner("studspider v0.1"))
print("Built for PLAY-WELL TEKNOLOGIES by contact@traps.moe\n\n") print("Built for PLAY-WELL TEKNOLOGIES by contact@traps.moe\n\n")
aiohttp.web.run_app(app, port=7432) aiohttp.web.run_app(app, port=7432)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

-2
View File
@@ -1,2 +0,0 @@
reflex==0.8.14.post1
-9
View File
@@ -1,9 +0,0 @@
import reflex as rx
config = rx.Config(
app_name="web",
plugins=[
rx.plugins.SitemapPlugin(),
rx.plugins.TailwindV4Plugin(),
]
)
View File
Whitespace-only changes.
-36
View File
@@ -1,36 +0,0 @@
"""Welcome to Reflex! This file outlines the steps to create a basic app."""
import reflex as rx
from rxconfig import config
class State(rx.State):
"""The app state."""
def index() -> rx.Component:
# Welcome Page (Index)
return rx.container(
rx.color_mode.button(position="top-right"),
rx.vstack(
rx.heading("Welcome to Reflex!", size="9"),
rx.text(
"Get started by editing ",
rx.code(f"{config.app_name}/{config.app_name}.py"),
size="5",
),
rx.link(
rx.button("Check out our docs!"),
href="https://reflex.dev/docs/getting-started/introduction/",
is_external=True,
),
spacing="5",
justify="center",
min_height="85vh",
),
)
app = rx.App()
app.add_page(index)
+9 -8
View File
@@ -11,12 +11,14 @@ import re
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
from pathlib import Path from pathlib import Path
print("Creating log directory if it doesn't exist...") print("Creating log directory if it doesn't exist...")
os.makedirs("./logs/", exist_ok=True) os.makedirs("./logs/", exist_ok=True)
import banner import banner
import get_sq_env import get_sq_env
from time import time from time import time
time = int(time()) time = int(time())
import asquare as sq import asquare as sq
@@ -31,15 +33,15 @@ from asyncio_throttle.throttler import Throttler
# set up logger # set up logger
print("Setting up logger...") print("Setting up logger...")
logger = logging.getLogger("edderkop") logger = logging.getLogger("studspider")
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler("./logs/edderkop.log", maxBytes=125000, backupCount=5) handler = RotatingFileHandler("./logs/studspider.log", maxBytes=125000, backupCount=5)
logger.addHandler(handler) logger.addHandler(handler)
lego = AsyncBricksetAPI(debug=True, logger=logger) lego = AsyncBricksetAPI(debug=True, logger=logger)
# sq = AsyncSquareClient(logger=logger) # sq = AsyncSquareClient(logger=logger)
# logging.basicConfig( # logging.basicConfig(
# filename="./logs/edderkop.log", encoding="utf-8", level=logging.DEBUG # filename="./logs/studspider.log", encoding="utf-8", level=logging.DEBUG
# ) # )
print("Setting up rate limiter...") print("Setting up rate limiter...")
print("Doing RE things...") print("Doing RE things...")
@@ -85,9 +87,7 @@ async def request_handler(request: web.Request) -> web.Response:
try: try:
# Verify request method # Verify request method
if request.method != "POST": if request.method != "POST":
logger.error( logger.error(f"{time}\tInvalid request method from %s at ", request.remote)
f"{time}\tInvalid request method from %s at ", request.remote
)
return web.Response(status=405, text="Method not allowed. Use POST.") return web.Response(status=405, text="Method not allowed. Use POST.")
# Get JSON data from request # Get JSON data from request
@@ -138,12 +138,13 @@ async def request_handler(request: web.Request) -> web.Response:
print(f"Request handler error: {str(e)}") print(f"Request handler error: {str(e)}")
return web.Response(status=500, text="Internal server error") return web.Response(status=500, text="Internal server error")
print("Starting web server...") print("Starting web server...")
os.system('cls' if os.name == 'nt' else 'clear') os.system("cls" if os.name == "nt" else "clear")
app = web.Application() app = web.Application()
app.router.add_post("/", request_handler) app.router.add_post("/", request_handler)
if __name__ == "__main__": if __name__ == "__main__":
print(banner.generate("Edderkop v0.1")) print(banner.generate("studspider v0.1"))
print("Built for PLAY-WELL TEKNOLOGIES by contact@traps.moe\n\n") print("Built for PLAY-WELL TEKNOLOGIES by contact@traps.moe\n\n")
web.run_app(app, host="localhost", port=7432) web.run_app(app, host="localhost", port=7432)
+3 -3
View File
@@ -1,12 +1,12 @@
import src.test_server import src.test_server
class edderkop: class Studspider:
def __init__(self): def __init__(self):
self.name = "Edderkop" self.name = "Studspider"
self.version = "0.0.1" self.version = "0.0.1"
self.description = """ self.description = """
Edderkop is an application designed to interact with the Brickset API and directly with Square. studspider is an application designed to interact with the Brickset API and directly with Square.
It allows users to search for items, manage collections, and perform various operations related to bricksets. It allows users to search for items, manage collections, and perform various operations related to bricksets.
""" """
Generated
+33 -33
View File
@@ -239,39 +239,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b2/b7/545d2c10c1fc15e48653c91efde329a790f2eecfbbf2bd16003b5db2bab0/dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9", size = 1892, upload-time = "2025-02-19T22:15:01.647Z" }, { url = "https://files.pythonhosted.org/packages/b2/b7/545d2c10c1fc15e48653c91efde329a790f2eecfbbf2bd16003b5db2bab0/dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9", size = 1892, upload-time = "2025-02-19T22:15:01.647Z" },
] ]
[[package]]
name = "edderkop"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "aiohttp" },
{ name = "aiosqlite" },
{ name = "apscheduler" },
{ name = "asyncio-throttle" },
{ name = "bs4" },
{ name = "dotenv" },
{ name = "pyinstaller" },
{ name = "pytest" },
{ name = "reflex" },
{ name = "requests" },
{ name = "squareup" },
]
[package.metadata]
requires-dist = [
{ name = "aiohttp", specifier = ">=3.12.13,<4.0.0" },
{ name = "aiosqlite", specifier = ">=0.21.0,<0.22.0" },
{ name = "apscheduler", specifier = ">=3.11.0,<4.0.0" },
{ name = "asyncio-throttle", specifier = ">=1.0.2,<2.0.0" },
{ name = "bs4", specifier = ">=0.0.2" },
{ name = "dotenv", specifier = ">=0.9.9,<0.10.0" },
{ name = "pyinstaller", specifier = ">=6.14.1,<7.0.0" },
{ name = "pytest", specifier = ">=8.4.2,<9.0.0" },
{ name = "reflex", specifier = ">=0.8.14.post1" },
{ name = "requests", specifier = ">=2.32.4,<3.0.0" },
{ name = "squareup", specifier = ">=43.0.0.20250618,<44.0.0.0" },
]
[[package]] [[package]]
name = "frozenlist" name = "frozenlist"
version = "1.7.0" version = "1.7.0"
@@ -971,6 +938,39 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/be/72/2db2f49247d0a18b4f1bb9a5a39a0162869acf235f3a96418363947b3d46/starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659", size = 73736, upload-time = "2025-09-13T08:41:03.869Z" }, { url = "https://files.pythonhosted.org/packages/be/72/2db2f49247d0a18b4f1bb9a5a39a0162869acf235f3a96418363947b3d46/starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659", size = 73736, upload-time = "2025-09-13T08:41:03.869Z" },
] ]
[[package]]
name = "studpider"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "aiohttp" },
{ name = "aiosqlite" },
{ name = "apscheduler" },
{ name = "asyncio-throttle" },
{ name = "bs4" },
{ name = "dotenv" },
{ name = "pyinstaller" },
{ name = "pytest" },
{ name = "reflex" },
{ name = "requests" },
{ name = "squareup" },
]
[package.metadata]
requires-dist = [
{ name = "aiohttp", specifier = ">=3.12.13,<4.0.0" },
{ name = "aiosqlite", specifier = ">=0.21.0,<0.22.0" },
{ name = "apscheduler", specifier = ">=3.11.0,<4.0.0" },
{ name = "asyncio-throttle", specifier = ">=1.0.2,<2.0.0" },
{ name = "bs4", specifier = ">=0.0.2" },
{ name = "dotenv", specifier = ">=0.9.9,<0.10.0" },
{ name = "pyinstaller", specifier = ">=6.14.1,<7.0.0" },
{ name = "pytest", specifier = ">=8.4.2,<9.0.0" },
{ name = "reflex", specifier = ">=0.8.14.post1" },
{ name = "requests", specifier = ">=2.32.4,<3.0.0" },
{ name = "squareup", specifier = ">=43.0.0.20250618,<44.0.0.0" },
]
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.15.0" version = "4.15.0"