chelsea fecafc15ee fixed file permission error causing reboot loop
d
2025-10-12 23:40:33,603 - apscheduler.scheduler - INFO - Scheduler started
2025-10-12 23:40:33,605 - polling_service - INFO - Polling scheduler started
2025-10-12 23:40:33,605 - apscheduler.scheduler - INFO - Added job "Check and poll sources" to job store "default"
2025-10-12 23:40:33,606 - polling_service - INFO - Poll checker job scheduled
2025-10-12 23:40:33,610 - filter_pipeline.config - INFO - Loaded filter config from filter_config.json
2025-10-12 23:40:33,610 - filter_pipeline.config - INFO - Loaded 5 filtersets from filtersets.json
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/usr/local/lib/python3.12/site-packages/flask/__main__.py", line 3, in <module>
    main()
  File "/usr/local/lib/python3.12/site-packages/flask/cli.py", line 1131, in main
    cli.main()
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1383, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1850, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1246, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 814, in invoke
    return callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/decorators.py", line 93, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 814, in invoke
    return callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/flask/cli.py", line 979, in run_command
    raise e from None
  File "/usr/local/lib/python3.12/site-packages/flask/cli.py", line 963, in run_command
    app: WSGIApplication = info.load_app()  # pyright: ignore
                           ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/flask/cli.py", line 349, in load_app
    app = locate_app(import_name, name)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/flask/cli.py", line 245, in locate_app
    __import__(module_name)
  File "/app/app.py", line 91, in <module>
✓ Database tables created
    filter_engine = FilterEngine.get_instance()
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/filter_pipeline/engine.py", line 55, in get_instance
    cls._instance = cls()
                    ^^^^^
  File "/app/filter_pipeline/engine.py", line 43, in __init__
    self.cache = FilterCache(self.config.get_cache_dir())
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/filter_pipeline/cache.py", line 28, in __init__
    self.cache_dir.mkdir(parents=True, exist_ok=True)
  File "/usr/local/lib/python3.12/pathlib.py", line 1311, in mkdir
    os.mkdir(self, mode)
PermissionError: [Errno 13] Permission denied: 'data/filter_cach
2025-10-12 23:43:42 +00:00
2025-10-11 17:38:19 -05:00

BalanceBoard

A Reddit-style content aggregator that collects posts from multiple platforms (Reddit, Hacker News, RSS feeds) and presents them in a unified, customizable feed.

Features

  • Multi-Platform Support: Collect content from Reddit, Hacker News, and RSS feeds
  • Automated Polling: Background service polls sources at configurable intervals
  • User Authentication: Local accounts with bcrypt password hashing and Auth0 OAuth support
  • Anonymous Browsing: Browse public feed without creating an account
  • Password Reset: Secure token-based password reset mechanism
  • Customizable Feeds: Filter and customize content based on your preferences
  • Admin Panel: Manage polling sources, view logs, and configure the system
  • Modern UI: Card-based interface with clean, responsive design

Quick Start

Prerequisites

  • Python 3.12+
  • PostgreSQL database
  • Docker (for containerized deployment)

Local Development

  1. Clone the repository

    git clone https://git.scorpi.us/chelsea/balanceboard.git
    cd balanceboard
    
  2. Set up environment

    python3 -m venv venv
    source venv/bin/activate
    pip install -r requirements.txt
    
  3. Configure environment variables

    cp .env.example .env
    # Edit .env with your database credentials and settings
    
  4. Initialize the database

    python3 -c "from app import app, db; app.app_context().push(); db.create_all()"
    
  5. Run migrations (if needed)

    python3 migrate_password_reset.py
    
  6. Start the application

    python3 app.py
    
  7. Access the application

    • Open browser to http://localhost:5000
    • Create an account or browse anonymously

Docker Deployment

  1. Build the image

    docker build -t git.scorpi.us/chelsea/balanceboard:latest .
    
  2. Push to registry

    docker push git.scorpi.us/chelsea/balanceboard:latest
    
  3. Deploy with docker-compose

    docker-compose up -d
    

See DEPLOYMENT.md for detailed deployment instructions.

Configuration

Platform Sources

Configure available platforms and communities in platform_config.json:

{
  "reddit": {
    "name": "Reddit",
    "communities": [
      {
        "id": "programming",
        "name": "r/programming",
        "description": "Computer programming"
      }
    ]
  }
}

Polling Configuration

Admins can configure polling sources via the Admin Panel:

  • Platform: reddit, hackernews, or rss
  • Source ID: Subreddit name, or RSS feed URL
  • Poll Interval: How often to check for new content (in minutes)
  • Max Posts: Maximum posts to collect per poll
  • Fetch Comments: Whether to collect comments
  • Priority: low, medium, or high

Environment Variables

Key environment variables (see .env.example):

  • DATABASE_URL: PostgreSQL connection string
  • SECRET_KEY: Flask secret key for sessions
  • AUTH0_DOMAIN: Auth0 domain (if using OAuth)
  • AUTH0_CLIENT_ID: Auth0 client ID
  • AUTH0_CLIENT_SECRET: Auth0 client secret

Architecture

Components

  • Flask Web Server (app.py): Main application server
  • Polling Service (polling_service.py): Background scheduler for data collection
  • Data Collection (data_collection.py, data_collection_lib.py): Platform-specific data fetchers
  • Database Models (models.py): SQLAlchemy ORM models
  • User Service (user_service.py): User authentication and management

Database Schema

  • users: User accounts with authentication
  • poll_sources: Configured polling sources
  • poll_logs: History of polling activities
  • user_sessions: Active user sessions

Data Flow

  1. Polling service checks enabled sources at configured intervals
  2. Data collection fetchers retrieve posts from platforms
  3. Posts are normalized to a common schema and stored in data/posts/
  4. Web interface displays posts from the feed
  5. Users can filter, customize, and interact with content

API Endpoints

Public Routes

  • GET /: Main feed (anonymous or authenticated)
  • GET /login: Login page
  • POST /login: Authenticate user
  • GET /register: Registration page
  • POST /register: Create new account
  • GET /password-reset-request: Request password reset
  • POST /password-reset-request: Send reset link
  • GET /password-reset/<token>: Reset password form
  • POST /password-reset/<token>: Update password

Authenticated Routes

  • GET /settings: User settings
  • GET /logout: Log out

Admin Routes

  • GET /admin: Admin panel
  • GET /admin/polling: Manage polling sources
  • POST /admin/polling/add: Add new source
  • POST /admin/polling/update: Update source settings
  • POST /admin/polling/poll: Manually trigger poll

Development

Project Structure

balanceboard/
├── app.py                      # Main Flask application
├── polling_service.py          # Background polling service
├── data_collection.py          # Data collection orchestration
├── data_collection_lib.py      # Platform-specific fetchers
├── models.py                   # Database models
├── user_service.py             # User management
├── database.py                 # Database setup
├── platform_config.json        # Platform configurations
├── filtersets.json             # Content filter definitions
├── templates/                  # Jinja2 templates
├── static/                     # Static assets (CSS, JS)
├── themes/                     # UI themes
├── data/                       # Data storage
│   ├── posts/                  # Collected posts
│   ├── comments/               # Collected comments
│   └── moderation/             # Moderation data
├── requirements.txt            # Python dependencies
├── Dockerfile                  # Docker image definition
├── docker-compose.yml          # Docker composition
├── README.md                   # This file
└── DEPLOYMENT.md               # Deployment instructions

Adding a New Platform

  1. Add platform config to platform_config.json
  2. Implement fetcher in data_collection_lib.py:
    • fetchers.getPlatformData()
    • converters.platform_to_schema()
    • builders.build_platform_url()
  3. Update routing in getData() function
  4. Test data collection
  5. Add to available sources in admin panel

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Test thoroughly
  5. Submit a pull request

See DEPLOYMENT.md for commit and issue management guidelines.

License

This is a personal project by Chelsea. All rights reserved.

Support

For issues and feature requests, please use the issue tracker at: https://git.scorpi.us/chelsea/balanceboard/issues

Description
BalanceBoard - ADHD-friendly content aggregator
Readme 1.5 MiB
Languages
Python 52.3%
HTML 42.3%
CSS 3.9%
JavaScript 1.2%
Dockerfile 0.3%