48 Commits
Author SHA1 Message Date
C F d25e5aac60 fix type error 2025-12-17 14:56:57 -08:00
C F c88695f1e7 fix sq path so test works 2025-12-17 14:56:46 -08:00
C F 8413a89a47 test works and tests port 2025-12-17 14:56:34 -08:00
C F 6bb11a206b docker it up 2025-12-17 14:56:21 -08:00
C 4e94468315 Merge branch 'uv' 2025-10-26 15:54:44 -07:00
C ae55f36a0a ignore github 2025-10-26 15:51:58 -07:00
C e6937617a1 add initial web hook handling 2025-10-26 15:51:39 -07:00
C 1824c9fe59 add arguments for host and port!!! yay!! 2025-10-26 15:49:11 -07:00
C 0bc06358e8 BIG rename 2025-10-26 15:49:11 -07:00
C 77db374418 wtf is going on with these imports man 2025-10-26 15:48:57 -07:00
C e9d2bef2ae rename sql -> sqlite 2025-10-26 15:48:56 -07:00
C f514a577c8 all the reflex web junk lole 2025-10-26 15:48:56 -07:00
C 3e03fd7e8c add reflex for web stuff! 2025-10-26 15:48:56 -07:00
C 0fc3ad49ea global throttle things 2025-10-26 15:48:43 -07:00
C 0e3117e408 time stuff 2025-10-26 15:48:43 -07:00
ph0sgene 88dcb8a475 Update README.md 2025-10-26 15:48:42 -07:00
ph0sgene 7bbb46398e Update README.md 2025-10-26 15:48:42 -07:00
ph0sgene 2fc7e773e0 Update README.md 2025-10-26 15:48:42 -07:00
ph0sgene 784517e886 Update README.md 2025-10-26 15:48:42 -07:00
C ca99cd3853 fancy new readme 2025-10-26 15:48:34 -07:00
C a62b936920 spooder 2025-10-26 15:48:18 -07:00
C 4e808c3be9 mk test in test because test 2025-10-26 15:48:17 -07:00
C 80250035e5 modulize it >:( stupid wsl 2025-10-26 15:48:17 -07:00
C fb908e00b7 misc fixes 2025-10-26 15:48:17 -07:00
C 9804b6d673 fix up db fetch and insert 2025-10-26 15:48:17 -07:00
C 4dfe50db93 remove previous stuff from asquare and put it in glue 2025-10-26 15:48:17 -07:00
C 1c43e5ba06 make middleware module (glue) 2025-10-26 15:48:17 -07:00
C a85e06a19b global throttler implementation 2025-10-26 15:48:17 -07:00
C 12f03e8bc9 add initial review testing for sql 2025-10-26 15:47:59 -07:00
C 912ad15c28 rate limit 2025-10-26 15:47:59 -07:00
C 3b8a01160d move throttler example. we dont need it in src 2025-10-26 15:47:59 -07:00
C 0f60a31ef8 this is the schedule manager not the db 2025-10-26 15:47:58 -07:00
C f0e1d79e92 big sexy sqlite db 2025-10-26 15:47:58 -07:00
C 9a106d366b add rate limit handling to synch version :( 2025-10-26 15:47:58 -07:00
C ae459d2171 bs4 for testing 2025-10-26 15:47:58 -07:00
C bef441db88 i guess this should be versioned 2025-10-26 15:47:58 -07:00
C 72bac66682 add stuff todo for fixing database 2025-10-26 15:47:48 -07:00
C 60b687305e uv refresh 2025-10-26 15:47:48 -07:00
C 43e19b200d add verbosity to startup 2025-10-26 15:47:47 -07:00
C 7f5210ab57 testing subclassed asquare 2025-10-26 15:47:47 -07:00
C 3683a6ffc1 handle no numbers in set name 2025-10-26 15:47:47 -07:00
C aa2dc74ff7 added rotating logs! epicsauce 2025-10-26 15:47:20 -07:00
C 9b5d04183d added optional logging to brickset 2025-10-26 15:47:19 -07:00
ph0sgene 83769ce7db rm 314t 2025-10-26 15:47:11 -07:00
C 46dda6166a refactor: Migrate build system to Hatch and integrate UV 2025-10-26 15:47:11 -07:00
ph0sgene d9e64cf212 update ignore before rebase 2025-10-26 22:44:35 +00:00
ph0sgene 0c41ac2f84 Update README.md 2025-10-17 09:30:31 +00:00
ph0sgene 7cd8fe6541 Update README.md 2025-10-17 09:29:40 +00:00
6 changed files with 147 additions and 5 deletions

No files matched your search

+1
View File
@@ -34,3 +34,4 @@ studspider.db-journal
assets/external/ assets/external/
__pycache__/ __pycache__/
win/ win/
.github/
+21
View File
@@ -0,0 +1,21 @@
FROM python:3.13-alpine
# Install uv
RUN pip install uv
# Set working directory
WORKDIR /app
# Copy project files
COPY pyproject.toml ./
COPY README.md ./
# Install dependencies using uv without venv
RUN uv pip compile pyproject.toml -o requirements.txt && \
uv pip install --system -r requirements.txt
# Copy the rest of the application
COPY . .
# Default command
CMD ["python", "tests/test.py"]
+1 -1
View File
@@ -48,7 +48,7 @@ def get_set(set_number: int) -> dict:
} }
# add PW 10% b4 tax # add PW 10% b4 tax
our_set.update( our_set.update(
{"set_adjustredprice": our_set + ((10 / 100) * our_set["set_retailprice"])} {"set_adjustredprice": our_set["set_retailprice"] + ((10 / 100) * our_set["set_retailprice"])}
) )
our_set["pw_name"] = ( our_set["pw_name"] = (
f"{our_set['set_num']} - {our_set["set_theme"].upper()} {our_set['set_name']}" f"{our_set['set_num']} - {our_set["set_theme"].upper()} {our_set['set_name']}"
+1 -1
View File
@@ -1,6 +1,6 @@
import json import json
import get_sq_env from . import get_sq_env
SQUARE_TOKEN = get_sq_env.SQUARE_TOKEN SQUARE_TOKEN = get_sq_env.SQUARE_TOKEN
LEGO_CAT_ID = get_sq_env.LEGO_CAT_ID LEGO_CAT_ID = get_sq_env.LEGO_CAT_ID
+97 -2
View File
@@ -1,3 +1,4 @@
import argparse
import asyncio import asyncio
import json import json
from aiohttp import web from aiohttp import web
@@ -7,6 +8,7 @@ import uuid
import dotenv import dotenv
import os import os
import re import re
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
@@ -82,6 +84,47 @@ def valid_uuid(val):
return False return False
async def hook_handler(request: web.Request) -> web.Response:
"""Handle incoming JSON webhook POSTs on /hook endpoint"""
try:
# Verify request method
if request.method != "POST":
logger.error(
f"{time}\tInvalid request method to /hook from %s", request.remote
)
return web.Response(status=405, text="Method not allowed. Use POST.")
# Get JSON data from request
try:
data = await request.json()
except json.JSONDecodeError:
logger.error("Invalid JSON to /hook from %s", request.remote)
return web.Response(status=400, text="Invalid JSON in request body")
# Log the received webhook
print(f"[@DEBUG] Webhook received at {time} from {request.remote}")
logger.info(
f"{time}\tWebhook received from {request.remote}: {json.dumps(data)}"
)
# Process the webhook data here
# TODO: Add your webhook processing logic
response_data = {
"status": "success",
"message": "Webhook received",
"timestamp": time,
"data_received": data,
}
return web.json_response(response_data)
except Exception as e:
logger.error(f"Webhook handler error: {str(e)}")
print(f"Webhook handler error: {str(e)}")
return web.Response(status=500, text="Internal server error")
async def request_handler(request: web.Request) -> web.Response: async def request_handler(request: web.Request) -> web.Response:
"""Handle incoming POST requests with command processing""" """Handle incoming POST requests with command processing"""
try: try:
@@ -142,9 +185,61 @@ async def request_handler(request: web.Request) -> web.Response:
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("/api", request_handler)
app.router.add_post("/hook", hook_handler)
parser = argparse.ArgumentParser(description="studspider")
parser.add_argument(
"--host",
type=str,
default="localhost",
help="IP address to listen on. default: localhost",
)
parser.add_argument(
"--port", type=int, default=7432, help="Port to listen on. default: 7432"
)
parser.add_argument(
"--hook-port",
type=int,
default=8080,
help="Optional separate port for webhook endpoint. default: 8080",
)
args = parser.parse_args()
if __name__ == "__main__": if __name__ == "__main__":
print(banner.generate("studspider 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)
# If hook-port is specified, run a separate server for webhooks
if args.hook_port:
print(f"Starting main server on {args.host}:{args.port}")
print(f"Starting webhook server on {args.host}:{args.hook_port}")
# Create separate app for webhook
hook_app = web.Application()
hook_app.router.add_post("/hook", hook_handler)
# Run both servers concurrently
async def run_servers():
runner1 = web.AppRunner(app)
await runner1.setup()
site1 = web.TCPSite(runner1, args.host, args.port)
runner2 = web.AppRunner(hook_app)
await runner2.setup()
site2 = web.TCPSite(runner2, args.host, args.hook_port)
await site1.start()
await site2.start()
print(f"Main server running on http://{args.host}:{args.port}")
print(f"Webhook server running on http://{args.host}:{args.hook_port}/hook")
# Keep running
await asyncio.Event().wait()
asyncio.run(run_servers())
else:
print(f"Server running on {args.host}:{args.port}")
print(f"Webhook endpoint: http://{args.host}:{args.port}/hook")
web.run_app(app, host=args.host, port=args.port)
+26 -1
View File
@@ -1,6 +1,31 @@
import sys
from pathlib import Path
from pprint import pprint
sys.path.insert(0, str(Path(__file__).parent.parent))
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
import src.libsquare as sq import src.libsquare as sq
import src.bricksetapi as lego import src.bricksetapi as lego
print("=" * 80)
result = sock.connect_ex(('127.0.0.1', 7432))
if result == 0:
print("PORT 7432 IS IN USE")
else:
print("PORT 7432 IS AVAILABLE")
sock.close()
print("=" * 80)
print("SQUARE OBJECT FOR SET 71417:")
print("=" * 80)
oursq = sq.get_itm("71417") oursq = sq.get_itm("71417")
pprint(oursq, width=120, depth=None)
print("\n" + "=" * 80)
print("LEGO SET INFORMATION FOR SET 71417:")
print("=" * 80)
ourlego = lego.get_set(71417) ourlego = lego.get_set(71417)
print(f"{oursq}\n\n{ourlego}\n\n") print("=" * 80)
pprint(ourlego, width=120, depth=None)