- Bluesky post collector with mention tracking - PostgreSQL database for storage - OpenAI-based toxicity analysis - Web UI for viewing and analyzing posts - Docker compose setup for deployment 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
67 lines
1.8 KiB
Python
67 lines
1.8 KiB
Python
"""Flask application factory for the Bluesky Collector web UI."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from flask import Flask
|
|
|
|
from . import db as webdb
|
|
from .helpers import (
|
|
bsky_post_url,
|
|
encode_uri,
|
|
format_dt,
|
|
format_number,
|
|
time_ago,
|
|
truncate,
|
|
)
|
|
|
|
|
|
def create_app() -> Flask:
|
|
app = Flask(
|
|
__name__,
|
|
template_folder="templates",
|
|
)
|
|
|
|
app.secret_key = os.environ.get("SECRET_KEY", "bluesky-collector-dev-key")
|
|
|
|
app.config["DATABASE_URL"] = os.environ.get(
|
|
"DATABASE_URL",
|
|
"postgresql://bluesky:changeme@db:5432/bluesky",
|
|
)
|
|
|
|
# Initialize database pool
|
|
webdb.init_pool(app.config["DATABASE_URL"])
|
|
|
|
# Register Jinja2 globals/filters
|
|
app.jinja_env.filters["format_dt"] = format_dt
|
|
app.jinja_env.filters["time_ago"] = time_ago
|
|
app.jinja_env.filters["truncate_text"] = truncate
|
|
app.jinja_env.filters["format_number"] = format_number
|
|
app.jinja_env.globals["encode_uri"] = encode_uri
|
|
app.jinja_env.globals["bsky_post_url"] = bsky_post_url
|
|
|
|
# Register blueprints
|
|
from .routes.dashboard import bp as dashboard_bp
|
|
from .routes.accounts import bp as accounts_bp
|
|
from .routes.statuses import bp as statuses_bp
|
|
from .routes.mentions import bp as mentions_bp
|
|
from .routes.export import bp as export_bp
|
|
from .routes.analysis import bp as analysis_bp
|
|
|
|
app.register_blueprint(dashboard_bp)
|
|
app.register_blueprint(accounts_bp)
|
|
app.register_blueprint(statuses_bp)
|
|
app.register_blueprint(mentions_bp)
|
|
app.register_blueprint(export_bp)
|
|
app.register_blueprint(analysis_bp)
|
|
|
|
# Teardown
|
|
@app.teardown_appcontext
|
|
def close_db(exc):
|
|
pass # Pool is long-lived, closed at shutdown
|
|
|
|
import atexit
|
|
atexit.register(webdb.close_pool)
|
|
|
|
return app
|