mirror of
https://github.com/Routstr/routstr-core.git
synced 2026-10-05 20:28:23 +00:00
Merge branch 'main' into x-cash-refac
This commit is contained in:
+6
-6
@@ -19,19 +19,19 @@ DEVS_DONATION_RATE = float(os.environ.get("DEVS_DONATION_RATE", 0.021)) # 2.1%
|
||||
NSEC = os.environ["NSEC"] # Nostr private key for the wallet
|
||||
CURRENCY = cast(CurrencyUnit, os.environ.get("CURRENCY", "sat"))
|
||||
|
||||
WALLET: Wallet | None = None
|
||||
wallet_instance: Wallet | None = None
|
||||
|
||||
|
||||
async def init_wallet() -> None:
|
||||
global WALLET
|
||||
WALLET = await Wallet.create(nsec=NSEC, mint_urls=[MINT], currency=CURRENCY)
|
||||
global wallet_instance
|
||||
wallet_instance = await Wallet.create(nsec=NSEC)
|
||||
|
||||
|
||||
def wallet() -> Wallet:
|
||||
global WALLET
|
||||
if WALLET is None:
|
||||
global wallet_instance
|
||||
if wallet_instance is None:
|
||||
raise ValueError("Wallet not initialized")
|
||||
return WALLET
|
||||
return wallet_instance
|
||||
|
||||
|
||||
async def delete_key_if_zero_balance(key: ApiKey, session: AsyncSession) -> None:
|
||||
|
||||
+17
-2
@@ -9,6 +9,21 @@ LOG_FILE="${LOG_FILE:-/home/ubuntu/proxy/update.log}"
|
||||
LOCK_FILE="${LOCK_FILE:-/tmp/proxy_update.lock}"
|
||||
MAX_LOG_LINES="${MAX_LOG_LINES:-10000}" # Maximum number of log lines to keep
|
||||
|
||||
# Detect which Docker Compose command is available
|
||||
detect_docker_compose_cmd() {
|
||||
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
|
||||
echo "docker compose"
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
echo "docker-compose"
|
||||
else
|
||||
log_message "ERROR: Neither 'docker compose' nor 'docker-compose' is available"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Set the Docker Compose command
|
||||
DOCKER_COMPOSE_CMD=$(detect_docker_compose_cmd)
|
||||
|
||||
# Function to log messages with timestamp
|
||||
log_message() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
|
||||
@@ -68,11 +83,11 @@ if [ "$LOCAL_HASH" != "$REMOTE_HASH" ]; then
|
||||
|
||||
# Stop current containers
|
||||
log_message "Stopping current containers..."
|
||||
sudo docker compose down 2>&1 | tee -a "$LOG_FILE"
|
||||
sudo $DOCKER_COMPOSE_CMD down 2>&1 | tee -a "$LOG_FILE"
|
||||
|
||||
# Build and start updated containers
|
||||
log_message "Building and starting updated containers..."
|
||||
if sudo docker compose up -d --build 2>&1 | tee -a "$LOG_FILE"; then
|
||||
if sudo $DOCKER_COMPOSE_CMD up -d --build 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log_message "Successfully updated and restarted containers"
|
||||
else
|
||||
log_message "ERROR: Failed to start containers"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
REPO_DIR=/home/user/proxy
|
||||
LOG_FILE=/home/user/proxy/update.log
|
||||
* * * * * /home/user/proxy/scripts/auto_update.sh >/dev/null 2>&1
|
||||
* * * * * /home/user/proxy/scripts/auto_update.sh >/dev/null 2>&1
|
||||
|
||||
OUTPUT_FILE=/home/user/proxy/models.json
|
||||
BASE_URL=https://openrouter.ai/api/v1
|
||||
0 * * * * python3 /home/user/proxy/scripts/models_meta.py >/dev/null 2>&1
|
||||
|
||||
Regular → Executable
+11
-3
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import TypedDict
|
||||
from urllib.request import urlopen
|
||||
|
||||
@@ -38,9 +41,13 @@ class Model(TypedDict):
|
||||
per_request_limits: dict | None
|
||||
|
||||
|
||||
OUTPUT_FILE = os.getenv("OUTPUT_FILE", "models.json")
|
||||
BASE_URL = os.getenv("BASE_URL", "https://openrouter.ai/api/v1")
|
||||
|
||||
|
||||
def fetch_openrouter_models() -> list[Model]:
|
||||
"""Fetches model information from OpenRouter API."""
|
||||
with urlopen("https://openrouter.ai/api/v1/models") as response:
|
||||
with urlopen(f"{BASE_URL}/models") as response:
|
||||
data = json.loads(response.read().decode("utf-8"))
|
||||
|
||||
models_data: list[Model] = []
|
||||
@@ -64,9 +71,10 @@ def main() -> None:
|
||||
models = fetch_openrouter_models()
|
||||
|
||||
# Print the first model data in a nicely indented JSON format
|
||||
print(json.dumps(models[0], indent=4))
|
||||
# print(json.dumps(models[0], indent=4))
|
||||
print(f"Writing {len(models)} models to {OUTPUT_FILE}")
|
||||
|
||||
with open("or-models.json", "w") as f:
|
||||
with open(OUTPUT_FILE, "w") as f:
|
||||
json.dump({"models": models}, f, indent=4)
|
||||
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from router.main import app, lifespan
|
||||
from tests.conftest import TEST_ENV
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_background_tasks_cancel_on_shutdown() -> None:
|
||||
pricing_started = asyncio.Event()
|
||||
pricing_cancelled = asyncio.Event()
|
||||
|
||||
async def fake_update() -> None:
|
||||
pricing_started.set()
|
||||
try:
|
||||
await asyncio.Event().wait()
|
||||
except asyncio.CancelledError:
|
||||
pricing_cancelled.set()
|
||||
raise
|
||||
|
||||
refund_started = asyncio.Event()
|
||||
refund_cancelled = asyncio.Event()
|
||||
|
||||
async def fake_refund() -> None:
|
||||
refund_started.set()
|
||||
try:
|
||||
await asyncio.Event().wait()
|
||||
except asyncio.CancelledError:
|
||||
refund_cancelled.set()
|
||||
raise
|
||||
|
||||
with patch.dict("os.environ", TEST_ENV, clear=True):
|
||||
mock_wallet = AsyncMock()
|
||||
mock_wallet.__aenter__ = AsyncMock(return_value=mock_wallet)
|
||||
mock_wallet.__aexit__ = AsyncMock(return_value=None)
|
||||
mock_state = MagicMock()
|
||||
mock_state.balance = 1000
|
||||
mock_wallet.fetch_wallet_state = AsyncMock(return_value=mock_state)
|
||||
mock_wallet.send_to_lnurl = AsyncMock(return_value=100)
|
||||
mock_wallet.redeem = AsyncMock(return_value=(1, "sat"))
|
||||
mock_wallet.send = AsyncMock(return_value="cashuAtoken123")
|
||||
|
||||
with (
|
||||
patch("router.cashu.Wallet.create", AsyncMock(return_value=mock_wallet)),
|
||||
patch("router.cashu.WALLET", mock_wallet),
|
||||
):
|
||||
with (
|
||||
patch("router.main.update_sats_pricing", new=fake_update),
|
||||
patch("router.main.check_for_refunds", new=fake_refund),
|
||||
):
|
||||
async with lifespan(app):
|
||||
await pricing_started.wait()
|
||||
await refund_started.wait()
|
||||
|
||||
assert pricing_cancelled.is_set()
|
||||
assert refund_cancelled.is_set()
|
||||
Reference in New Issue
Block a user