|
# retoor <retoor@molodetz.nl>
|
|
|
|
import time
|
|
from pathlib import Path
|
|
from dotenv import load_dotenv
|
|
from os import environ
|
|
|
|
load_dotenv()
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
STATIC_DIR = BASE_DIR / "devplacepy" / "static"
|
|
TEMPLATES_DIR = BASE_DIR / "devplacepy" / "templates"
|
|
|
|
DATA_DIR = Path(environ.get("DEVPLACE_DATA_DIR", str(BASE_DIR / "data")))
|
|
UPLOADS_DIR = DATA_DIR / "uploads"
|
|
ATTACHMENTS_DIR = UPLOADS_DIR / "attachments"
|
|
PROJECT_FILES_DIR = UPLOADS_DIR / "project_files"
|
|
CONTAINER_WORKSPACES_DIR = DATA_DIR / "container_workspaces"
|
|
ZIPS_DIR = DATA_DIR / "zips"
|
|
ZIP_STAGING_DIR = DATA_DIR / "zip_staging"
|
|
FORK_STAGING_DIR = DATA_DIR / "fork_staging"
|
|
BACKUPS_DIR = DATA_DIR / "backups"
|
|
BACKUP_STAGING_DIR = DATA_DIR / "backup_staging"
|
|
SEO_REPORTS_DIR = DATA_DIR / "seo_reports"
|
|
PLANNING_REPORTS_DIR = DATA_DIR / "planning_reports"
|
|
DBAPI_DIR = DATA_DIR / "dbapi"
|
|
DEEPSEARCH_DIR = DATA_DIR / "deepsearch"
|
|
DEEPSEARCH_CHROMA_DIR = DEEPSEARCH_DIR / "chroma"
|
|
ISSLOP_DIR = DATA_DIR / "isslop"
|
|
ISSLOP_WORKSPACES_DIR = ISSLOP_DIR / "workspaces"
|
|
ISSLOP_RUNS_DIR = ISSLOP_DIR / "runs"
|
|
ISSLOP_MEDIA_DIR = ISSLOP_DIR / "media"
|
|
KEYS_DIR = DATA_DIR / "keys"
|
|
BOT_DIR = DATA_DIR / "bot"
|
|
LOCKS_DIR = DATA_DIR / "locks"
|
|
|
|
DEVII_TASKS_DB = DATA_DIR / "devii_tasks.db"
|
|
DEVII_LESSONS_DB = DATA_DIR / "devii_lessons.db"
|
|
|
|
DATABASE_URL = environ.get(
|
|
"DEVPLACE_DATABASE_URL", f"sqlite:///{DATA_DIR / 'devplace.db'}"
|
|
)
|
|
SECRET_KEY = environ.get("SECRET_KEY", "devplace-secret-key-change-in-production")
|
|
SECONDS_PER_DAY = 86400
|
|
SESSION_MAX_AGE = SECONDS_PER_DAY * 7
|
|
SESSION_MAX_AGE_REMEMBER = SECONDS_PER_DAY * 30
|
|
PORT = 10500
|
|
SITE_URL = environ.get("DEVPLACE_SITE_URL", "").rstrip("/")
|
|
|
|
PRESENCE_TIMEOUT_SECONDS = int(environ.get("DEVPLACE_PRESENCE_TIMEOUT_SECONDS", "60"))
|
|
PRESENCE_WRITE_SECONDS = max(1, PRESENCE_TIMEOUT_SECONDS // 2)
|
|
PRESENCE_ONLINE_LIMIT = int(environ.get("DEVPLACE_PRESENCE_ONLINE_LIMIT", "30"))
|
|
PRESENCE_ONLINE_MARGIN_SECONDS = int(
|
|
environ.get("DEVPLACE_PRESENCE_ONLINE_MARGIN_SECONDS", "20")
|
|
)
|
|
|
|
XMLRPC_BIND = environ.get("DEVPLACE_XMLRPC_BIND", "127.0.0.1")
|
|
XMLRPC_PORT = int(environ.get("DEVPLACE_XMLRPC_PORT", "10550"))
|
|
|
|
STATIC_VERSION = environ.get("DEVPLACE_STATIC_VERSION") or str(int(time.time()))
|
|
|
|
TEMPLATE_AUTO_RELOAD = environ.get("DEVPLACE_TEMPLATE_AUTO_RELOAD", "1") != "0"
|
|
|
|
INTERNAL_BASE_URL = environ.get(
|
|
"DEVPLACE_INTERNAL_BASE_URL", f"http://localhost:{PORT}"
|
|
).rstrip("/")
|
|
INTERNAL_GATEWAY_URL = f"{INTERNAL_BASE_URL}/openai/v1/chat/completions"
|
|
INTERNAL_EMBED_URL = f"{INTERNAL_BASE_URL}/openai/v1/embeddings"
|
|
INTERNAL_MODEL = "molodetz"
|
|
INTERNAL_EMBED_MODEL = "molodetz~embed"
|
|
INTERNAL_IMAGE_MODEL = "molodetz-img-small"
|
|
|
|
AWARD_GIVE_COOLDOWN_HOURS_DEFAULT = 24
|
|
AWARD_RECEIVE_COOLDOWN_HOURS_DEFAULT = 24
|
|
AWARD_DISPLAY_HOURS_DEFAULT = 24
|
|
AWARD_DESCRIPTION_MAX = 125
|
|
AWARD_IMAGE_MODEL_DEFAULT = "molodetz-img-small"
|
|
AWARD_IMAGE_SIZE_DEFAULT = "512x512"
|
|
AWARD_GENERATION_TIMEOUT_SECONDS = 120.0
|
|
AWARD_IMAGE_PROMPT_DEFAULT = (
|
|
"Generate a single decorative developer award emblem/badge as a PNG with a fully "
|
|
"transparent background (alpha channel). No rectangular backdrop, no drop shadow "
|
|
"plate, no text labels rendered in the image. Center one stylized trophy/medal "
|
|
"icon that visually matches this message:"
|
|
)
|
|
DEFAULT_CORRECTION_PROMPT = "Leave literary as is, only do punctuation and casing"
|
|
DEFAULT_MODIFIER_PROMPT = (
|
|
"Execute what is behind `@ai` (the prompt) and replace that part including `@ai`"
|
|
)
|
|
|
|
SERVICE_LOCK_FILE = LOCKS_DIR / "devplace-services.lock"
|
|
INIT_LOCK_FILE = LOCKS_DIR / "devplace-init.lock"
|
|
|
|
CONTAINER_IMAGE = environ.get("DEVPLACE_CONTAINER_IMAGE", "ppy:latest")
|
|
CONTAINER_PROXY_HOST = environ.get("DEVPLACE_CONTAINER_PROXY_HOST", "").strip()
|
|
|
|
VAPID_PRIVATE_KEY_FILE = KEYS_DIR / "notification-private.pem"
|
|
VAPID_PRIVATE_KEY_PKCS8_FILE = KEYS_DIR / "notification-private.pkcs8.pem"
|
|
VAPID_PUBLIC_KEY_FILE = KEYS_DIR / "notification-public.pem"
|
|
VAPID_SUB = environ.get("DEVPLACE_VAPID_SUB", "mailto:retoor@molodetz.nl")
|
|
|
|
DATA_PATHS: dict[str, Path] = {
|
|
"data": DATA_DIR,
|
|
"uploads": UPLOADS_DIR,
|
|
"attachments": ATTACHMENTS_DIR,
|
|
"project_files": PROJECT_FILES_DIR,
|
|
"container_workspaces": CONTAINER_WORKSPACES_DIR,
|
|
"zips": ZIPS_DIR,
|
|
"zip_staging": ZIP_STAGING_DIR,
|
|
"fork_staging": FORK_STAGING_DIR,
|
|
"backups": BACKUPS_DIR,
|
|
"backup_staging": BACKUP_STAGING_DIR,
|
|
"seo_reports": SEO_REPORTS_DIR,
|
|
"planning_reports": PLANNING_REPORTS_DIR,
|
|
"dbapi": DBAPI_DIR,
|
|
"deepsearch": DEEPSEARCH_DIR,
|
|
"deepsearch_chroma": DEEPSEARCH_CHROMA_DIR,
|
|
"isslop": ISSLOP_DIR,
|
|
"isslop_workspaces": ISSLOP_WORKSPACES_DIR,
|
|
"isslop_runs": ISSLOP_RUNS_DIR,
|
|
"isslop_media": ISSLOP_MEDIA_DIR,
|
|
"keys": KEYS_DIR,
|
|
"bot": BOT_DIR,
|
|
"locks": LOCKS_DIR,
|
|
}
|
|
|
|
|
|
def ensure_data_dirs() -> None:
|
|
for path in DATA_PATHS.values():
|
|
path.mkdir(parents=True, exist_ok=True)
|