Add comprehensive documentation for Quizzical Beats
- Created a detailed database schema document outlining tables, relationships, and key fields. - Added OAuth integration documentation covering Spotify and Dropbox authentication processes. - Introduced a FAQ section addressing common user inquiries about the application. - Developed a user-friendly index page for easy navigation of the documentation. - Specified documentation dependencies in requirements.txt for building the documentation site. - Expanded user guide with sections on account management, creating rounds, exporting rounds, getting started, importing songs, and user interface navigation. - Updated mkdocs.yml for improved site structure and navigation.
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
# Backup and Restore
|
||||
|
||||
This guide explains how to back up and restore Quizzical Beats data, ensuring your music quiz system remains protected against data loss.
|
||||
|
||||
## Understanding Backup Components
|
||||
|
||||
A complete Quizzical Beats backup includes:
|
||||
|
||||
- **Database**: Contains all rounds, songs, user accounts, and system settings
|
||||
- **Media Files**: MP3 snippets, custom intro/outro sounds, and uploaded audio
|
||||
- **Configuration**: Environment variables and application settings
|
||||
- **Metadata**: Version information and backup manifest
|
||||
|
||||
## Manual Backup Process
|
||||
|
||||
Perform a manual backup through the admin interface:
|
||||
|
||||
1. Log in as an administrator
|
||||
2. Navigate to Admin > System > Backup Manager
|
||||
3. Click "Create New Backup" or use the "Quick Actions" button
|
||||
4. Options you can configure:
|
||||
- Custom backup name (optional)
|
||||
- Include MP3 files (enabled by default)
|
||||
- Include configuration files (enabled by default)
|
||||
5. The backup will be stored in the `/data/backups` directory
|
||||
6. Once completed, you can download the backup ZIP file
|
||||
|
||||
## Automated Backup Configuration
|
||||
|
||||
Set up scheduled automatic backups:
|
||||
|
||||
1. Go to Admin > System > Backup Manager
|
||||
2. Click "Schedule Backups"
|
||||
3. Configure:
|
||||
- Frequency (hourly, daily, weekly)
|
||||
- Time of execution (HH:MM format)
|
||||
- Retention policy (days to keep backups)
|
||||
4. Click "Save Schedule" to apply the settings
|
||||
|
||||
For Docker deployments, you can configure automated backups using the Docker labels or Ofelia scheduler:
|
||||
|
||||
1. Click "View Configuration Suggestion" in the scheduler form
|
||||
2. Choose the appropriate configuration option:
|
||||
- Docker Compose labels
|
||||
- Ofelia.ini configuration
|
||||
3. Apply the suggested configuration to your Docker setup
|
||||
4. Restart your containers to activate the schedule
|
||||
|
||||
## Backup Retention Policies
|
||||
|
||||
Configure how long backups are kept:
|
||||
|
||||
1. Navigate to Admin > System > Backup Manager
|
||||
2. Click "Configure Retention"
|
||||
3. Set the number of days to keep backups:
|
||||
- Enter a value between 1-365 days
|
||||
- Enter 0 to keep all backups indefinitely
|
||||
4. Options:
|
||||
- Save Policy: Updates the retention settings
|
||||
- Apply Now: Immediately deletes backups older than the specified period
|
||||
|
||||
## Backup Management
|
||||
|
||||
Manage your existing backups:
|
||||
|
||||
1. Go to Admin > System > Backup Manager > Existing Backups
|
||||
2. For each backup, you can:
|
||||
- Download: Save the backup file to your local system
|
||||
- Verify: Check the backup integrity
|
||||
- Restore: Revert your system to this backup state
|
||||
- Delete: Remove the backup file
|
||||
|
||||
## Restoring from Backup
|
||||
|
||||
Restore your system when needed:
|
||||
|
||||
1. Go to Admin > System > Backup Manager > Existing Backups
|
||||
2. You can either:
|
||||
- Select an existing backup from the list
|
||||
- Upload a backup file using the "Upload Backup" button
|
||||
3. Click the "Restore" icon next to the backup you wish to restore
|
||||
4. Confirm the restore operation
|
||||
5. The system will:
|
||||
- Create safety backups of your current state
|
||||
- Restore the database, MP3 files, and configuration
|
||||
- Preserve all file history
|
||||
|
||||
## Command-Line Backup
|
||||
|
||||
For scripting and automation, use the CLI commands:
|
||||
|
||||
```bash
|
||||
# Create a backup
|
||||
python run.py backup create --auto
|
||||
|
||||
# Apply retention policy
|
||||
python run.py backup retention --days 30
|
||||
```
|
||||
|
||||
## Backup Verification
|
||||
|
||||
Ensure your backups are valid:
|
||||
|
||||
1. Go to Admin > System > Backup Manager > Existing Backups
|
||||
2. Click the "Verify" icon next to the backup
|
||||
3. The system will check:
|
||||
- File integrity (ZIP structure)
|
||||
- Required files presence (database)
|
||||
- Version metadata
|
||||
4. A notification will appear with the verification results
|
||||
|
||||
## System Health
|
||||
|
||||
The Backup Manager also provides a system health overview:
|
||||
|
||||
1. Check the "System Health" section at the bottom of the page
|
||||
2. It displays the status of critical components:
|
||||
- Database connectivity
|
||||
- File storage access
|
||||
- Configuration status
|
||||
|
||||
## Troubleshooting Backup Issues
|
||||
|
||||
**Backup Failure**:
|
||||
- Check storage permissions for the `/data/backups` directory
|
||||
- Verify sufficient disk space
|
||||
- Ensure the database is not locked by another process
|
||||
|
||||
**Restore Failure**:
|
||||
- Ensure the backup format is compatible with your version
|
||||
- Check system logs for detailed error messages
|
||||
- Verify backup file integrity using the verification tool
|
||||
@@ -0,0 +1,255 @@
|
||||
# Configuration Guide
|
||||
|
||||
This guide explains how to configure Quizzical Beats for different environments and use cases.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Quizzical Beats uses environment variables for configuration. These can be set in the `.env` file or directly in your environment.
|
||||
|
||||
### Core Configuration
|
||||
|
||||
```bash
|
||||
# Debug settings
|
||||
DEBUG=True
|
||||
DEBUG2=False
|
||||
SECRET_KEY=your-secret-key-here-make-it-long-and-random
|
||||
```
|
||||
|
||||
### API Keys and Services
|
||||
|
||||
```bash
|
||||
# OpenAI API settings
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
OPENAI_URL=https://api.openai.com/v1
|
||||
OPENAI_MODEL=gpt-4o-mini
|
||||
OPENAI_SEARCH_MODEL=gpt-4o-mini-search-preview
|
||||
|
||||
# Translation and language services
|
||||
DEEPL_API_KEY=your-deepl-api-key
|
||||
MEANINGCLOUD_API_KEY=your-meaningcloud-api-key
|
||||
|
||||
# Audio services
|
||||
ELEVENLABS_API_KEY=your-elevenlabs-api-key
|
||||
ACRCLOUD_TOKEN=your-acrcloud-token
|
||||
|
||||
# Music APIs
|
||||
LASTFM_API_KEY=your-lastfm-api-key
|
||||
```
|
||||
|
||||
## Music Metadata APIs
|
||||
|
||||
Quizzical Beats uses multiple API services to gather comprehensive music metadata. Configuring these services enhances the quality and completeness of your music library.
|
||||
|
||||
### Last.fm
|
||||
|
||||
Last.fm provides genre information and tag data that's often missing from streaming services:
|
||||
|
||||
- **Configuration**: Set the `LASTFM_API_KEY` environment variable
|
||||
- **Usage**: Automatically enriches tracks with genre metadata
|
||||
- **Benefits**: Improves genre-based round generation
|
||||
- **Obtain API Key**: [Last.fm API](https://www.last.fm/api/account/create)
|
||||
|
||||
### Spotify
|
||||
|
||||
Spotify provides comprehensive track metadata and audio features analysis:
|
||||
|
||||
- **Configuration**: Set `SPOTIFY_CLIENT_ID` and `SPOTIFY_CLIENT_SECRET`
|
||||
- **Usage**: Primary source for song previews, artwork, and audio characteristics
|
||||
- **Benefits**: Enables audio feature analysis (tempo, danceability, energy, etc.)
|
||||
- **Obtain API Keys**: [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/)
|
||||
|
||||
### Deezer
|
||||
|
||||
Deezer serves as an alternative source for track metadata and previews:
|
||||
|
||||
- **Configuration**: Set `DEEZER_APP_ID` and `DEEZER_APP_SECRET`
|
||||
- **Usage**: Alternative source when Spotify data is unavailable
|
||||
- **Benefits**: Provides additional preview URLs and metadata
|
||||
- **Obtain API Keys**: [Deezer Developers](https://developers.deezer.com/myapps)
|
||||
|
||||
### ACRCloud
|
||||
|
||||
ACRCloud can be used for music recognition and metadata enrichment:
|
||||
|
||||
- **Configuration**: Set `ACRCLOUD_TOKEN`
|
||||
- **Usage**: Identify songs from audio samples
|
||||
- **Benefits**: Enhanced metadata lookups using audio fingerprinting
|
||||
- **Obtain API Keys**: [ACRCloud](https://www.acrcloud.com/)
|
||||
|
||||
### Metadata Enrichment Process
|
||||
|
||||
When a song is imported into Quizzical Beats:
|
||||
|
||||
1. The system first checks if the song has an ISRC (International Standard Recording Code)
|
||||
2. If an ISRC is available, it's used to find metadata across all configured services
|
||||
3. The system consolidates data from multiple sources to create a comprehensive record
|
||||
4. If an ISRC is unavailable, the system relies on the original source's data
|
||||
5. Genre information is converted to tags for improved searchability
|
||||
|
||||
For optimal metadata quality, we recommend configuring at least Spotify and Last.fm APIs.
|
||||
|
||||
### Database Configuration
|
||||
|
||||
```bash
|
||||
# SQLite (default)
|
||||
SQLALCHEMY_DATABASE_URI=sqlite:///data/song_data.db
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS=False
|
||||
|
||||
# For MySQL/MariaDB:
|
||||
# SQLALCHEMY_DATABASE_URI=mysql+pymysql://username:password@localhost/musicround
|
||||
|
||||
# For PostgreSQL:
|
||||
# SQLALCHEMY_DATABASE_URI=postgresql://username:password@localhost/musicround
|
||||
```
|
||||
|
||||
### OAuth Provider Configuration
|
||||
|
||||
```bash
|
||||
# Spotify API configuration
|
||||
SPOTIFY_CLIENT_ID=your-spotify-client-id
|
||||
SPOTIFY_CLIENT_SECRET=your-spotify-client-secret
|
||||
SPOTIFY_REDIRECT_URI=http://localhost:5000/auth/spotify/callback
|
||||
|
||||
# Deezer API configuration
|
||||
DEEZER_APP_ID=your-deezer-app-id
|
||||
DEEZER_APP_SECRET=your-deezer-app-secret
|
||||
DEEZER_REDIRECT_URI=http://localhost:5000/deezer-callback
|
||||
|
||||
# Google OAuth configuration
|
||||
GOOGLE_CLIENT_ID=your-google-client-id
|
||||
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||
|
||||
# Authentik OAuth configuration
|
||||
AUTHENTIK_CLIENT_ID=your-authentik-client-id
|
||||
AUTHENTIK_CLIENT_SECRET=your-authentik-client-secret
|
||||
AUTHENTIK_METADATA_URL=https://authentik.example.com/.well-known/openid-configuration
|
||||
|
||||
# Dropbox OAuth configuration
|
||||
DROPBOX_APP_KEY=your-dropbox-app-key
|
||||
DROPBOX_APP_SECRET=your-dropbox-app-secret
|
||||
DROPBOX_REDIRECT_URI=http://localhost:5000/users/dropbox/callback
|
||||
```
|
||||
|
||||
### Email Configuration
|
||||
|
||||
```bash
|
||||
# Email settings
|
||||
MAIL_HOST=smtp.example.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USE_TLS=True
|
||||
MAIL_USE_SSL=False
|
||||
MAIL_USERNAME=your-email-username
|
||||
MAIL_PASSWORD=your-email-password
|
||||
MAIL_SENDER=quizzical-beats@example.com
|
||||
MAIL_RECIPIENT=admin@example.com
|
||||
```
|
||||
|
||||
### Automation Settings
|
||||
|
||||
```bash
|
||||
# Used for automated tasks and API access
|
||||
AUTOMATION_TOKEN=your-secure-automation-token
|
||||
```
|
||||
|
||||
## Configuration File (.env)
|
||||
|
||||
Create a `.env` file in the root directory with your configuration variables. You can copy the provided `.env.demo` file as a starting point:
|
||||
|
||||
```bash
|
||||
cp .env.demo .env
|
||||
```
|
||||
|
||||
Then edit the `.env` file with your actual configuration values:
|
||||
|
||||
```bash
|
||||
# Example .env file (simplified)
|
||||
SECRET_KEY=your-secure-secret-key
|
||||
DEBUG=True
|
||||
SQLALCHEMY_DATABASE_URI=sqlite:///data/song_data.db
|
||||
SPOTIFY_CLIENT_ID=your-spotify-client-id
|
||||
SPOTIFY_CLIENT_SECRET=your-spotify-client-secret
|
||||
# Add other variables as needed
|
||||
```
|
||||
|
||||
## Configuration Priority
|
||||
|
||||
Quizzical Beats loads configuration in the following order of priority:
|
||||
|
||||
1. Environment variables set in the system
|
||||
2. Variables in the `.env` file
|
||||
3. Default values defined in the `config.py` file
|
||||
|
||||
## Docker Environment Variables
|
||||
|
||||
When using Docker, you can pass environment variables through the `docker-compose.yml` file:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
environment:
|
||||
- SECRET_KEY=your-secure-secret-key
|
||||
- SQLALCHEMY_DATABASE_URI=postgresql://postgres:password@db/musicround
|
||||
- SPOTIFY_CLIENT_ID=your-spotify-client-id
|
||||
- SPOTIFY_CLIENT_SECRET=your-spotify-client-secret
|
||||
# Add other variables as needed
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
```
|
||||
|
||||
## Required Configuration
|
||||
|
||||
The following variables are required for core functionality:
|
||||
|
||||
- `SECRET_KEY`: Used for securing sessions and CSRF tokens
|
||||
- `SQLALCHEMY_DATABASE_URI`: Database connection string
|
||||
|
||||
## Optional Configuration
|
||||
|
||||
These configurations enable additional features:
|
||||
|
||||
### Spotify Integration
|
||||
|
||||
Required for importing playlists and tracks from Spotify:
|
||||
- `SPOTIFY_CLIENT_ID`
|
||||
- `SPOTIFY_CLIENT_SECRET`
|
||||
- `SPOTIFY_REDIRECT_URI`
|
||||
|
||||
### Dropbox Integration
|
||||
|
||||
Required for exporting rounds to Dropbox:
|
||||
- `DROPBOX_APP_KEY`
|
||||
- `DROPBOX_APP_SECRET`
|
||||
- `DROPBOX_REDIRECT_URI`
|
||||
|
||||
### OAuth Authentication
|
||||
|
||||
Required for sign-in with external providers:
|
||||
- Google: `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`
|
||||
- Authentik: `AUTHENTIK_CLIENT_ID`, `AUTHENTIK_CLIENT_SECRET`, `AUTHENTIK_METADATA_URL`
|
||||
|
||||
## Applying Configuration Changes
|
||||
|
||||
After changing configuration:
|
||||
|
||||
1. For a standard installation, restart the application:
|
||||
```bash
|
||||
sudo systemctl restart quizzical-beats
|
||||
# Or if using Gunicorn directly:
|
||||
kill -HUP $(cat gunicorn.pid)
|
||||
```
|
||||
|
||||
2. For Docker installations:
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Verifying Configuration
|
||||
|
||||
To verify your configuration:
|
||||
|
||||
1. Check the application logs after startup
|
||||
2. Visit the Admin > System > Settings page in the web interface
|
||||
3. Check the system health on the Admin > System > Health Dashboard page
|
||||
@@ -0,0 +1,304 @@
|
||||
# Installation Guide
|
||||
|
||||
This guide explains how to install and set up Quizzical Beats in various environments.
|
||||
|
||||
## System Requirements
|
||||
|
||||
Before installation, ensure your system meets these requirements:
|
||||
|
||||
- **Operating System**: Linux (recommended), macOS, or Windows
|
||||
- **Python**: Version 3.8 or higher
|
||||
- **Database**: SQLite (included), PostgreSQL, or MySQL
|
||||
- **Storage**: Minimum 2GB free space for application and database
|
||||
- **Memory**: 2GB RAM minimum, 4GB recommended
|
||||
- **Optional**: Docker and Docker Compose for containerized deployment
|
||||
|
||||
## Docker Installation (Recommended)
|
||||
|
||||
The easiest way to deploy Quizzical Beats is using Docker:
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. Install [Docker](https://docs.docker.com/get-docker/)
|
||||
2. Install [Docker Compose](https://docs.docker.com/compose/install/)
|
||||
|
||||
### Deployment Steps
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/christianlouis/musicround.git
|
||||
cd musicround
|
||||
```
|
||||
|
||||
2. Configure environment variables:
|
||||
```bash
|
||||
cp .env.demo .env
|
||||
```
|
||||
Edit the `.env` file to set your configuration options, including API keys and database settings.
|
||||
|
||||
3. Start the application:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
4. Access the application at `http://localhost:5000`
|
||||
|
||||
### Docker Volume Configuration
|
||||
|
||||
The Docker setup creates several persistent volumes:
|
||||
|
||||
- **data**: Contains the SQLite database and uploaded files
|
||||
- **mp3**: Stores all generated and uploaded MP3 files
|
||||
- **backups**: Location for automated backups
|
||||
|
||||
You can configure these volumes in the `docker-compose.yml` file:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
- ./mp3:/app/mp3
|
||||
- ./backups:/app/backups
|
||||
```
|
||||
|
||||
## Manual Installation
|
||||
|
||||
For non-Docker environments:
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. Install Python 3.8+ and pip
|
||||
2. Set up a virtual environment (recommended):
|
||||
```bash
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
```
|
||||
|
||||
### Installation Steps
|
||||
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/christianlouis/musicround.git
|
||||
cd musicround
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. Configure environment variables:
|
||||
```bash
|
||||
cp .env.demo .env
|
||||
```
|
||||
Edit the `.env` file with your configuration settings.
|
||||
|
||||
4. Create necessary directories:
|
||||
```bash
|
||||
mkdir -p data/backups mp3
|
||||
```
|
||||
|
||||
5. Initialize the database:
|
||||
```bash
|
||||
python run_migration.py
|
||||
```
|
||||
|
||||
6. Start the application:
|
||||
```bash
|
||||
python run.py
|
||||
```
|
||||
|
||||
7. Access the application at `http://localhost:5000`
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For production environments, consider the following:
|
||||
|
||||
### Web Server Configuration
|
||||
|
||||
Use a production-ready web server:
|
||||
|
||||
1. Install Gunicorn:
|
||||
```bash
|
||||
pip install gunicorn
|
||||
```
|
||||
|
||||
2. Configure Gunicorn:
|
||||
```bash
|
||||
gunicorn -w 4 -b 127.0.0.1:8000 "musicround:create_app()"
|
||||
```
|
||||
|
||||
3. Set up Nginx as a reverse proxy:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /static {
|
||||
alias /path/to/musicround/static;
|
||||
expires 30d;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. Set up HTTPS using Certbot (Let's Encrypt):
|
||||
```bash
|
||||
sudo certbot --nginx -d your-domain.com
|
||||
```
|
||||
|
||||
### Database Configuration
|
||||
|
||||
For larger deployments, use PostgreSQL:
|
||||
|
||||
1. Install PostgreSQL and create a database:
|
||||
```bash
|
||||
sudo apt install postgresql
|
||||
sudo -u postgres createuser -P quizzicalbeats
|
||||
sudo -u postgres createdb -O quizzicalbeats musicround
|
||||
```
|
||||
|
||||
2. Update the database URI in your `.env` file:
|
||||
```
|
||||
SQLALCHEMY_DATABASE_URI=postgresql://quizzicalbeats:password@localhost/musicround
|
||||
```
|
||||
|
||||
### Security Configuration
|
||||
|
||||
1. Generate a strong secret key:
|
||||
```bash
|
||||
python -c "import secrets; print('SECRET_KEY=' + secrets.token_hex(32))"
|
||||
```
|
||||
Add this to your `.env` file.
|
||||
|
||||
2. Set debug mode to False in production:
|
||||
```
|
||||
DEBUG=False
|
||||
```
|
||||
|
||||
3. Configure proper file permissions:
|
||||
```bash
|
||||
sudo chown -R www-data:www-data data mp3 backups
|
||||
sudo chmod -R 750 data mp3 backups
|
||||
```
|
||||
|
||||
## Setting Up Third-Party Services
|
||||
|
||||
### Spotify Integration
|
||||
|
||||
1. Go to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/)
|
||||
2. Create a new application
|
||||
3. Add `http://your-domain.com/auth/spotify/callback` to the Redirect URIs
|
||||
4. Copy your Client ID and Client Secret to your `.env` file:
|
||||
```
|
||||
SPOTIFY_CLIENT_ID=your-client-id
|
||||
SPOTIFY_CLIENT_SECRET=your-client-secret
|
||||
SPOTIFY_REDIRECT_URI=http://your-domain.com/auth/spotify/callback
|
||||
```
|
||||
|
||||
### Dropbox Integration
|
||||
|
||||
1. Go to the [Dropbox App Console](https://www.dropbox.com/developers/apps)
|
||||
2. Create a new app with the following settings:
|
||||
- API: Dropbox API
|
||||
- Access type: Full Dropbox
|
||||
- Name: Quizzical Beats (or your preferred name)
|
||||
3. Add `http://your-domain.com/users/dropbox/callback` to the OAuth 2 Redirect URIs
|
||||
4. Copy your App Key and App Secret to your `.env` file:
|
||||
```
|
||||
DROPBOX_APP_KEY=your-app-key
|
||||
DROPBOX_APP_SECRET=your-app-secret
|
||||
DROPBOX_REDIRECT_URI=http://your-domain.com/users/dropbox/callback
|
||||
```
|
||||
5. Under Permissions, select:
|
||||
- files.content.read
|
||||
- files.content.write
|
||||
- sharing.write
|
||||
|
||||
### OpenAI Integration (for AI-powered features)
|
||||
|
||||
1. Go to [OpenAI API Keys](https://platform.openai.com/account/api-keys)
|
||||
2. Create a new secret key
|
||||
3. Add your API key to your `.env` file:
|
||||
```
|
||||
OPENAI_API_KEY=your-api-key
|
||||
```
|
||||
|
||||
### Email Configuration
|
||||
|
||||
1. Configure your SMTP settings in the `.env` file:
|
||||
```
|
||||
MAIL_HOST=smtp.example.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USE_TLS=True
|
||||
MAIL_USERNAME=your-username
|
||||
MAIL_PASSWORD=your-password
|
||||
MAIL_SENDER=quizzical-beats@example.com
|
||||
MAIL_RECIPIENT=admin@example.com
|
||||
```
|
||||
|
||||
## Troubleshooting Installation Issues
|
||||
|
||||
### Database Migration Errors
|
||||
|
||||
If you encounter errors during database migration:
|
||||
|
||||
1. Check for database connection issues:
|
||||
```bash
|
||||
python -c "from musicround import db; db.create_all()"
|
||||
```
|
||||
|
||||
2. Reset the migration if needed:
|
||||
```bash
|
||||
rm -f data/song_data.db
|
||||
python run_migration.py
|
||||
```
|
||||
|
||||
### File Permission Issues
|
||||
|
||||
If you encounter file permission errors:
|
||||
|
||||
1. Check ownership of data directories:
|
||||
```bash
|
||||
ls -la data mp3 backups
|
||||
```
|
||||
|
||||
2. Update permissions if needed:
|
||||
```bash
|
||||
sudo chown -R $(whoami) data mp3 backups
|
||||
```
|
||||
|
||||
### OAuth Configuration Errors
|
||||
|
||||
If OAuth authentication fails:
|
||||
|
||||
1. Verify that your callback URLs exactly match what's configured in the provider's developer console
|
||||
2. Check for typos in your client IDs and secrets
|
||||
3. Ensure the application is in "production" status for Dropbox
|
||||
4. Verify that all required scopes/permissions are enabled
|
||||
|
||||
### Server Not Starting
|
||||
|
||||
If the server fails to start:
|
||||
|
||||
1. Check the logs for errors:
|
||||
```bash
|
||||
tail -f logs/quizzical-beats.log
|
||||
```
|
||||
|
||||
2. Verify that all required dependencies are installed:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. Check if another process is using port 5000:
|
||||
```bash
|
||||
sudo lsof -i :5000
|
||||
```
|
||||
@@ -0,0 +1,141 @@
|
||||
# System Health Monitoring
|
||||
|
||||
This guide explains how to monitor, troubleshoot, and maintain the health of your Quizzical Beats installation.
|
||||
|
||||
## Health Dashboard
|
||||
|
||||
Quizzical Beats provides a built-in health dashboard that gives you a comprehensive overview of your system:
|
||||
|
||||
1. Log in as an administrator
|
||||
2. Navigate to Admin > System > Health Dashboard
|
||||
3. The dashboard displays:
|
||||
- Database information (status, song count, round count, user count)
|
||||
- Storage information (directory status, file counts, sizes)
|
||||
- External service status
|
||||
- Memory usage
|
||||
- Version information
|
||||
|
||||
### Health Status Cards
|
||||
|
||||
The top of the health dashboard features status cards that provide a quick overview of your system's health:
|
||||
|
||||
- **Database**: Connection status and database health
|
||||
- **Storage**: File storage status and access permissions
|
||||
- **API Services**: Status of external API connections
|
||||
- **Memory**: System memory availability and usage
|
||||
|
||||
Each card is color-coded to indicate status:
|
||||
- Green: Good/healthy
|
||||
- Yellow: Warning/potential issues
|
||||
- Red: Error/critical issues
|
||||
|
||||
## Database Monitoring
|
||||
|
||||
### Database Statistics
|
||||
|
||||
The database section of the health dashboard shows:
|
||||
|
||||
- Total number of songs in the database
|
||||
- Total number of rounds
|
||||
- Total number of users
|
||||
- Database file size
|
||||
- Last backup timestamp
|
||||
|
||||
This information helps you track database growth and ensure you're performing regular backups.
|
||||
|
||||
## Storage Monitoring
|
||||
|
||||
The storage section provides information about key directories:
|
||||
|
||||
- Directory name
|
||||
- Number of files in each directory
|
||||
- Total size of files
|
||||
- Write permission status
|
||||
|
||||
This helps you identify potential storage issues such as:
|
||||
- Lack of write permissions
|
||||
- Unexpected growth in file count or size
|
||||
- Directories approaching storage limits
|
||||
|
||||
## External Service Monitoring
|
||||
|
||||
The External Services section displays the status of integrated third-party services:
|
||||
|
||||
- Service name
|
||||
- Connection status (Available, Warning, Unavailable)
|
||||
- Status details or error messages
|
||||
|
||||
Services monitored may include:
|
||||
- Spotify API
|
||||
- Dropbox API
|
||||
- OpenAI API
|
||||
- Email service
|
||||
- Other integrated services based on your configuration
|
||||
|
||||
## Version Information
|
||||
|
||||
The Version Information section shows:
|
||||
|
||||
- Application version
|
||||
- Release name
|
||||
- Release date
|
||||
- Python version
|
||||
- Operating system platform
|
||||
- Flask version
|
||||
|
||||
This information is essential when troubleshooting issues or planning updates.
|
||||
|
||||
## Troubleshooting Common Issues
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
If the database status shows errors:
|
||||
|
||||
1. Check database credentials in your `.env` file
|
||||
2. Verify that the database file exists at the configured location
|
||||
3. Check file permissions on the database file
|
||||
4. Ensure there's enough disk space for database growth
|
||||
|
||||
### Storage Issues
|
||||
|
||||
If the Storage status shows problems:
|
||||
|
||||
1. Check directory permissions for the affected directories
|
||||
2. Verify that the application has write access to these directories
|
||||
3. Ensure sufficient disk space is available
|
||||
4. Check for file corruption or missing critical files
|
||||
|
||||
### External Service Connectivity
|
||||
|
||||
If service connections are failing:
|
||||
|
||||
1. Verify API keys and credentials in your `.env` file
|
||||
2. Check that redirect URIs are correctly configured
|
||||
3. Test external connectivity to the service endpoints
|
||||
4. Verify SSL certificates are valid for secure connections
|
||||
5. Check for API rate limiting or service outages
|
||||
|
||||
## CLI Health Checks
|
||||
|
||||
For command-line health checks, you can use:
|
||||
|
||||
```bash
|
||||
python run.py health check
|
||||
```
|
||||
|
||||
This command performs basic health checks and outputs the results to the console, which is useful for automated monitoring scripts.
|
||||
|
||||
## Best Practices for System Health
|
||||
|
||||
1. **Regular Monitoring**: Check the health dashboard at least weekly
|
||||
2. **Automated Alerts**: Set up external monitoring for critical services
|
||||
3. **Preventive Maintenance**: Address warning signs before they become critical
|
||||
4. **Regular Backups**: Configure automated backups and verify them regularly
|
||||
5. **Update Management**: Keep the application and dependencies up to date
|
||||
6. **Resource Planning**: Monitor growth trends to plan for future resource needs
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Backup and Restore](backup-restore.md) - For information on configuring backups
|
||||
- [Configuration Guide](configuration.md) - For details on configuring external services
|
||||
- [Installation Guide](installation.md) - For system requirements and setup
|
||||
@@ -0,0 +1,98 @@
|
||||
# Changelog
|
||||
|
||||
This document tracks all notable changes made to Quizzical Beats across different versions.
|
||||
|
||||
## v1.0.0 - May 10, 2025
|
||||
|
||||
### Milestone 9: "Documentation Dynamo"
|
||||
- Added comprehensive documentation system with MkDocs
|
||||
- Created user guides with detailed instructions
|
||||
- Added developer documentation with architecture overview
|
||||
- Implemented administrator documentation
|
||||
- Added FAQ section covering common questions
|
||||
- Created installation and configuration guides
|
||||
- Added OAuth integration documentation
|
||||
|
||||
## v0.9.0 - April 15, 2025
|
||||
|
||||
### Milestone 8: "Dropbox Dispatch"
|
||||
- Added Dropbox OAuth integration for user accounts
|
||||
- Implemented round export directly to Dropbox
|
||||
- Added user interface for Dropbox account management
|
||||
- Created export logs and status tracking
|
||||
- Added fallback handling for Dropbox token expiration
|
||||
- Implemented automatic token refresh for Dropbox API
|
||||
|
||||
## v0.8.0 - March 2, 2025
|
||||
|
||||
### Milestone 7: "Bulletproof Backups"
|
||||
- Implemented comprehensive backup system
|
||||
- Added backup scheduling with Ofelia integration
|
||||
- Created backup verification and integrity checks
|
||||
- Added restore functionality for system recovery
|
||||
- Implemented backup retention policies
|
||||
- Added system health dashboard
|
||||
- Created command-line backup tools
|
||||
|
||||
## v0.7.0 - February 10, 2025
|
||||
|
||||
### Milestone 6: "Advanced Features & Optimizations"
|
||||
- Implemented comprehensive logging system
|
||||
- Added system monitoring dashboard
|
||||
- Optimized database queries for better performance
|
||||
- Improved error handling and user feedback
|
||||
- Enhanced security with improved authentication flows
|
||||
|
||||
## v0.6.0 - January 25, 2025
|
||||
|
||||
### Milestone 5: "Additional OAuth Providers"
|
||||
- Added Google OAuth integration
|
||||
- Implemented Authentik OAuth support
|
||||
- Created unified authentication experience
|
||||
- Added profile linking between OAuth accounts
|
||||
- Enhanced security for third-party authentication
|
||||
|
||||
## v0.5.0 - January 8, 2025
|
||||
|
||||
### Milestone 4: "Enhanced User Experience"
|
||||
- Added support for user-specific intro/outro/replay MP3s
|
||||
- Updated email system to use logged-in user's email
|
||||
- Implemented user preferences and settings system
|
||||
- Improved UI/UX for round creation and management
|
||||
- Added customizable export settings
|
||||
|
||||
## v0.4.0 - December 15, 2024
|
||||
|
||||
### Milestone 3: "Spotify Integration with User Accounts"
|
||||
- Migrated Spotify token storage to user-specific model
|
||||
- Added Spotify OAuth login option
|
||||
- Created fallback mechanism for service account
|
||||
- Linked user playlists with their Spotify accounts
|
||||
- Enhanced Spotify data synchronization
|
||||
|
||||
## v0.3.0 - December 1, 2024
|
||||
|
||||
### Milestone 2: "Authentication Foundation"
|
||||
- Designed and implemented database schema for users and roles
|
||||
- Created basic authentication system with local username/password
|
||||
- Implemented user management interfaces
|
||||
- Added admin role functionality
|
||||
- Enhanced security with proper password handling and session management
|
||||
|
||||
## v0.2.0 - November 15, 2024
|
||||
|
||||
### Milestone 1: "Spotify Integration Fix"
|
||||
- Fixed Spotify playlist import functionality
|
||||
- Implemented proper pagination for playlist retrieval
|
||||
- Added better error handling for API rate limits
|
||||
- Refactored Spotify client code for maintainability
|
||||
- Enhanced logging for API requests and responses
|
||||
|
||||
## v0.1.0 - November 1, 2024
|
||||
|
||||
### Initial Release
|
||||
- Basic Flask application structure
|
||||
- Simple round creation functionality
|
||||
- Manual song entry capabilities
|
||||
- Basic export functionality
|
||||
- Minimal UI with core features
|
||||
@@ -0,0 +1,787 @@
|
||||
# API Reference
|
||||
|
||||
This document provides a comprehensive reference for the Quizzical Beats API endpoints.
|
||||
|
||||
## Authentication
|
||||
|
||||
All API endpoints require authentication unless specified otherwise.
|
||||
|
||||
### Authentication Methods
|
||||
|
||||
The API supports two authentication methods:
|
||||
|
||||
1. **Session Cookie**: For browser-based applications
|
||||
2. **API Key**: For programmatic access
|
||||
|
||||
#### API Key Authentication
|
||||
|
||||
To use API key authentication:
|
||||
|
||||
1. Generate an API key in your profile settings
|
||||
2. Include the key in the `X-API-Key` header with each request:
|
||||
```
|
||||
X-API-Key: your-api-key-here
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
API requests are rate-limited to prevent abuse:
|
||||
|
||||
- 100 requests per hour for standard users
|
||||
- 300 requests per hour for admin users
|
||||
|
||||
Rate limit headers are included in all responses:
|
||||
```
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 95
|
||||
X-RateLimit-Reset: 1620567890
|
||||
```
|
||||
|
||||
## Response Format
|
||||
|
||||
All API responses are in JSON format with a consistent structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success|error",
|
||||
"data": { ... },
|
||||
"message": "Optional message",
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 42,
|
||||
"pages": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
When an error occurs, the response will have status code 4xx or 5xx and include an error message:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"message": "Descriptive error message",
|
||||
"code": "ERROR_CODE"
|
||||
}
|
||||
```
|
||||
|
||||
Common error codes:
|
||||
- `UNAUTHORIZED`: Authentication failed
|
||||
- `FORBIDDEN`: Permission denied
|
||||
- `NOT_FOUND`: Resource not found
|
||||
- `VALIDATION_ERROR`: Invalid input data
|
||||
- `RATE_LIMITED`: Rate limit exceeded
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### User Endpoints
|
||||
|
||||
#### Get Current User
|
||||
|
||||
```
|
||||
GET /api/user
|
||||
```
|
||||
|
||||
Returns information about the currently authenticated user.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 123,
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"is_admin": false,
|
||||
"created_at": "2025-01-15T12:34:56Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Update User Profile
|
||||
|
||||
```
|
||||
PUT /api/user
|
||||
```
|
||||
|
||||
Update the current user's profile information.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"username": "new_username",
|
||||
"email": "new_email@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 123,
|
||||
"username": "new_username",
|
||||
"email": "new_email@example.com",
|
||||
"is_admin": false,
|
||||
"created_at": "2025-01-15T12:34:56Z"
|
||||
},
|
||||
"message": "Profile updated successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### Song Endpoints
|
||||
|
||||
#### List Songs
|
||||
|
||||
```
|
||||
GET /api/songs
|
||||
```
|
||||
|
||||
Returns a paginated list of songs in the user's library.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page`: Page number (default: 1)
|
||||
- `per_page`: Items per page (default: 20, max: 100)
|
||||
- `search`: Search term
|
||||
- `sort`: Sort field (title, artist, album, year)
|
||||
- `order`: Sort order (asc, desc)
|
||||
- `genre`: Filter by genre
|
||||
- `year`: Filter by year
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": [
|
||||
{
|
||||
"id": 456,
|
||||
"title": "Song Title",
|
||||
"artist": "Artist Name",
|
||||
"album": "Album Name",
|
||||
"year": 2010,
|
||||
"genre": "Rock",
|
||||
"preview_url": "https://example.com/preview.mp3",
|
||||
"spotify_id": "spotify:track:abcdef123456",
|
||||
"duration_ms": 240000
|
||||
},
|
||||
// More songs...
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 42,
|
||||
"pages": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Song
|
||||
|
||||
```
|
||||
GET /api/songs/{id}
|
||||
```
|
||||
|
||||
Returns detailed information about a specific song.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 456,
|
||||
"title": "Song Title",
|
||||
"artist": "Artist Name",
|
||||
"album": "Album Name",
|
||||
"year": 2010,
|
||||
"genre": "Rock",
|
||||
"preview_url": "https://example.com/preview.mp3",
|
||||
"spotify_id": "spotify:track:abcdef123456",
|
||||
"duration_ms": 240000,
|
||||
"added_by": 123,
|
||||
"created_at": "2025-02-10T15:30:45Z",
|
||||
"popularity": 75,
|
||||
"tags": [
|
||||
{
|
||||
"id": 789,
|
||||
"name": "Summer Hits",
|
||||
"color": "#ff5500"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Create Song
|
||||
|
||||
```
|
||||
POST /api/songs
|
||||
```
|
||||
|
||||
Add a new song to the user's library.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"title": "New Song",
|
||||
"artist": "New Artist",
|
||||
"album": "New Album",
|
||||
"year": 2025,
|
||||
"genre": "Pop",
|
||||
"spotify_id": "spotify:track:xyz789",
|
||||
"preview_url": "https://example.com/preview.mp3"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 457,
|
||||
"title": "New Song",
|
||||
"artist": "New Artist",
|
||||
"album": "New Album",
|
||||
"year": 2025,
|
||||
"genre": "Pop",
|
||||
"preview_url": "https://example.com/preview.mp3",
|
||||
"spotify_id": "spotify:track:xyz789",
|
||||
"added_by": 123,
|
||||
"created_at": "2025-05-11T09:12:34Z"
|
||||
},
|
||||
"message": "Song added successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Update Song
|
||||
|
||||
```
|
||||
PUT /api/songs/{id}
|
||||
```
|
||||
|
||||
Update an existing song.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"title": "Updated Title",
|
||||
"artist": "Updated Artist",
|
||||
"album": "Updated Album",
|
||||
"year": 2020,
|
||||
"genre": "Electronic"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 456,
|
||||
"title": "Updated Title",
|
||||
"artist": "Updated Artist",
|
||||
"album": "Updated Album",
|
||||
"year": 2020,
|
||||
"genre": "Electronic",
|
||||
"preview_url": "https://example.com/preview.mp3",
|
||||
"spotify_id": "spotify:track:abcdef123456"
|
||||
},
|
||||
"message": "Song updated successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Song
|
||||
|
||||
```
|
||||
DELETE /api/songs/{id}
|
||||
```
|
||||
|
||||
Remove a song from the user's library.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "Song deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### Round Endpoints
|
||||
|
||||
#### List Rounds
|
||||
|
||||
```
|
||||
GET /api/rounds
|
||||
```
|
||||
|
||||
Returns a paginated list of the user's quiz rounds.
|
||||
|
||||
**Query Parameters:**
|
||||
- `page`: Page number (default: 1)
|
||||
- `per_page`: Items per page (default: 20, max: 100)
|
||||
- `search`: Search term
|
||||
- `sort`: Sort field (name, created_at)
|
||||
- `order`: Sort order (asc, desc)
|
||||
- `tag`: Filter by tag ID
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": [
|
||||
{
|
||||
"id": 789,
|
||||
"name": "80s Rock Classics",
|
||||
"description": "Classic rock hits from the 1980s",
|
||||
"created_at": "2025-03-20T14:25:36Z",
|
||||
"song_count": 10,
|
||||
"round_type": "decade",
|
||||
"tags": [
|
||||
{
|
||||
"id": 123,
|
||||
"name": "80s",
|
||||
"color": "#3366ff"
|
||||
},
|
||||
{
|
||||
"id": 456,
|
||||
"name": "Rock",
|
||||
"color": "#cc0000"
|
||||
}
|
||||
]
|
||||
},
|
||||
// More rounds...
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 15,
|
||||
"pages": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Round
|
||||
|
||||
```
|
||||
GET /api/rounds/{id}
|
||||
```
|
||||
|
||||
Returns detailed information about a specific round, including its songs.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 789,
|
||||
"name": "80s Rock Classics",
|
||||
"description": "Classic rock hits from the 1980s",
|
||||
"created_at": "2025-03-20T14:25:36Z",
|
||||
"user_id": 123,
|
||||
"is_public": true,
|
||||
"round_type": "decade",
|
||||
"intro_file": "/mp3/intros/80s_intro.mp3",
|
||||
"outro_file": "/mp3/outros/rock_outro.mp3",
|
||||
"songs": [
|
||||
{
|
||||
"id": 101,
|
||||
"title": "Sweet Child O' Mine",
|
||||
"artist": "Guns N' Roses",
|
||||
"year": 1987,
|
||||
"position": 1,
|
||||
"question": "Name this iconic 80s rock song",
|
||||
"answer": "Sweet Child O' Mine by Guns N' Roses",
|
||||
"points": 10,
|
||||
"preview_url": "https://example.com/preview1.mp3"
|
||||
},
|
||||
// More songs...
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"id": 123,
|
||||
"name": "80s",
|
||||
"color": "#3366ff"
|
||||
},
|
||||
{
|
||||
"id": 456,
|
||||
"name": "Rock",
|
||||
"color": "#cc0000"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Create Round
|
||||
|
||||
```
|
||||
POST /api/rounds
|
||||
```
|
||||
|
||||
Create a new quiz round.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"name": "New Quiz Round",
|
||||
"description": "A fresh music quiz round",
|
||||
"round_type": "mixed",
|
||||
"is_public": true,
|
||||
"song_ids": [101, 102, 103, 104],
|
||||
"tag_ids": [123, 456]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 790,
|
||||
"name": "New Quiz Round",
|
||||
"description": "A fresh music quiz round",
|
||||
"created_at": "2025-05-11T10:15:20Z",
|
||||
"user_id": 123,
|
||||
"is_public": true,
|
||||
"round_type": "mixed",
|
||||
"song_count": 4
|
||||
},
|
||||
"message": "Round created successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Update Round
|
||||
|
||||
```
|
||||
PUT /api/rounds/{id}
|
||||
```
|
||||
|
||||
Update an existing round.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"name": "Updated Round Name",
|
||||
"description": "Updated description",
|
||||
"is_public": false,
|
||||
"song_ids": [101, 102, 105, 106],
|
||||
"tag_ids": [123, 789]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"id": 789,
|
||||
"name": "Updated Round Name",
|
||||
"description": "Updated description",
|
||||
"is_public": false,
|
||||
"song_count": 4
|
||||
},
|
||||
"message": "Round updated successfully"
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Round
|
||||
|
||||
```
|
||||
DELETE /api/rounds/{id}
|
||||
```
|
||||
|
||||
Delete a quiz round.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"message": "Round deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### Export Endpoints
|
||||
|
||||
#### Export Round to Dropbox
|
||||
|
||||
```
|
||||
POST /rounds/{round_id}/export-to-dropbox
|
||||
```
|
||||
|
||||
Export a round to the user's connected Dropbox account.
|
||||
|
||||
**Request Body Parameters:**
|
||||
```
|
||||
include_mp3s: boolean (default: true) - Whether to include MP3 files in the export
|
||||
include_pdf: boolean (default: true) - Whether to include PDF in the export
|
||||
custom_folder: string (optional) - Additional subfolder path within the user's configured export path
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Round exported to Dropbox successfully",
|
||||
"shared_links": {
|
||||
"text": "https://www.dropbox.com/s/abc123/round_123_metadata.json?dl=0",
|
||||
"pdf": "https://www.dropbox.com/s/def456/round_123.pdf?dl=0",
|
||||
"mp3": "https://www.dropbox.com/s/ghi789/round_123.mp3?dl=0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response:**
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "Error exporting to Dropbox: <error details>",
|
||||
"redirect": "URL for MP3 generation if needed"
|
||||
}
|
||||
```
|
||||
|
||||
#### List Dropbox Folders
|
||||
|
||||
```
|
||||
GET /api/dropbox/folders
|
||||
```
|
||||
|
||||
List folders from the user's Dropbox account.
|
||||
|
||||
**Query Parameters:**
|
||||
```
|
||||
path: string - The path to list folders from (default: root)
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"folders": [
|
||||
{
|
||||
"name": "Folder Name",
|
||||
"path": "/Folder Name",
|
||||
"is_dir": true
|
||||
},
|
||||
{
|
||||
"name": "Documents",
|
||||
"path": "/Documents",
|
||||
"is_dir": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Create Dropbox Folder
|
||||
|
||||
```
|
||||
POST /api/dropbox/create-folder
|
||||
```
|
||||
|
||||
Create a new folder in the user's Dropbox account.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"parent_path": "/path/to/parent",
|
||||
"folder_name": "New Folder"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Folder created successfully",
|
||||
"folder": {
|
||||
"name": "New Folder",
|
||||
"path": "/path/to/parent/New Folder",
|
||||
"is_dir": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Dropbox OAuth Endpoints
|
||||
|
||||
#### Connect Dropbox Account
|
||||
|
||||
```
|
||||
GET /users/dropbox/connect
|
||||
```
|
||||
|
||||
Initiates the OAuth flow for connecting a Dropbox account.
|
||||
|
||||
**Response:**
|
||||
Redirects to Dropbox OAuth authorization page
|
||||
|
||||
#### Dropbox OAuth Callback
|
||||
|
||||
```
|
||||
GET /users/dropbox/callback
|
||||
```
|
||||
|
||||
Handles the OAuth callback from Dropbox.
|
||||
|
||||
**Query Parameters:**
|
||||
```
|
||||
code: string - The authorization code from Dropbox
|
||||
error: string - Error message if authorization failed
|
||||
```
|
||||
|
||||
**Response:**
|
||||
Redirects back to user profile page with a success or error message
|
||||
|
||||
#### Disconnect Dropbox Account
|
||||
|
||||
```
|
||||
POST /users/dropbox/disconnect
|
||||
```
|
||||
|
||||
Disconnects the user's Dropbox account.
|
||||
|
||||
**Response:**
|
||||
Redirects back to user profile page with a success message
|
||||
|
||||
### Spotify Integration Endpoints
|
||||
|
||||
#### Get User Playlists
|
||||
|
||||
```
|
||||
GET /api/spotify/playlists
|
||||
```
|
||||
|
||||
Get the current user's Spotify playlists.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": [
|
||||
{
|
||||
"id": "spotify:playlist:abcdef123456",
|
||||
"name": "My Awesome Playlist",
|
||||
"owner": "spotify_user123",
|
||||
"track_count": 42,
|
||||
"image_url": "https://example.com/playlist_cover.jpg"
|
||||
},
|
||||
// More playlists...
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 35,
|
||||
"pages": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Import Playlist
|
||||
|
||||
```
|
||||
POST /api/spotify/import/playlist
|
||||
```
|
||||
|
||||
Import songs from a Spotify playlist.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"playlist_id": "spotify:playlist:abcdef123456",
|
||||
"limit": 20
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"import_id": "imp_789012",
|
||||
"playlist_name": "My Awesome Playlist",
|
||||
"status": "processing",
|
||||
"songs_found": 42,
|
||||
"songs_to_import": 20,
|
||||
"estimated_completion": "45 seconds"
|
||||
},
|
||||
"message": "Import started"
|
||||
}
|
||||
```
|
||||
|
||||
### Health Check Endpoint
|
||||
|
||||
```
|
||||
GET /api/health
|
||||
```
|
||||
|
||||
Get system health information (admin only).
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"version": "1.0.0",
|
||||
"uptime": "5d 12h 37m",
|
||||
"database": {
|
||||
"status": "connected",
|
||||
"size": "42MB",
|
||||
"migrations": "up-to-date"
|
||||
},
|
||||
"storage": {
|
||||
"available": "1.2GB",
|
||||
"used": "345MB"
|
||||
},
|
||||
"services": {
|
||||
"spotify": "connected",
|
||||
"dropbox": "connected",
|
||||
"email": "connected"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Webhook Notifications
|
||||
|
||||
Quizzical Beats can send webhook notifications for certain events.
|
||||
|
||||
### Configuring Webhooks
|
||||
|
||||
Webhooks are configured in the admin settings:
|
||||
|
||||
1. Go to Admin > System > Webhooks
|
||||
2. Add a new webhook URL
|
||||
3. Select which events to receive notifications for
|
||||
|
||||
### Webhook Events
|
||||
|
||||
- `round.created`: A new round was created
|
||||
- `round.exported`: A round was exported
|
||||
- `import.completed`: A Spotify import was completed
|
||||
- `backup.completed`: A system backup was completed
|
||||
|
||||
### Webhook Payload
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "round.exported",
|
||||
"timestamp": "2025-05-11T10:30:45Z",
|
||||
"data": {
|
||||
"round_id": 789,
|
||||
"round_name": "80s Rock Classics",
|
||||
"user_id": 123,
|
||||
"username": "john_doe",
|
||||
"export_format": "zip",
|
||||
"destination": "dropbox"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Versioning
|
||||
|
||||
The current API version is v1. The version is specified in the URL path:
|
||||
|
||||
```
|
||||
/api/v1/resource
|
||||
```
|
||||
|
||||
For backward compatibility, requests to `/api/resource` will be directed to the latest stable API version.
|
||||
@@ -0,0 +1,285 @@
|
||||
# Architecture Overview
|
||||
|
||||
This document provides a comprehensive overview of the Quizzical Beats architecture, designed to help developers understand the system structure and components.
|
||||
|
||||
## Application Structure
|
||||
|
||||
Quizzical Beats follows a modular Flask application structure:
|
||||
|
||||
```
|
||||
musicround/
|
||||
├── __init__.py # Application factory
|
||||
├── config.py # Configuration management
|
||||
├── models.py # Database models
|
||||
├── version.py # Version information
|
||||
├── errors.py # Error handling
|
||||
├── deezer_client.py # Deezer API integration
|
||||
├── helpers/ # Utility modules
|
||||
│ ├── __init__.py
|
||||
│ ├── auth_helpers.py # Authentication utilities
|
||||
│ ├── backup_helper.py # Backup management
|
||||
│ ├── dropbox_helper.py # Dropbox integration
|
||||
│ ├── email_helper.py # Email functionality
|
||||
│ ├── import_helper.py # Song import utilities
|
||||
│ ├── metadata.py # Song metadata processing
|
||||
│ ├── spotify_direct.py # Spotify API client
|
||||
│ └── utils.py # General utilities
|
||||
├── mp3/ # Audio file storage
|
||||
├── routes/ # Route definitions
|
||||
│ ├── __init__.py
|
||||
│ ├── api.py # API endpoints
|
||||
│ ├── auth.py # Authentication routes
|
||||
│ ├── core.py # Core application routes
|
||||
│ ├── db_admin.py # Database administration
|
||||
│ ├── deezer_routes.py # Deezer integration
|
||||
│ ├── generate.py # Content generation
|
||||
│ ├── import.py # Generic import functionality
|
||||
│ ├── import_routes.py # Import interface routes
|
||||
│ ├── import_songs.py # Song import functionality
|
||||
│ ├── process.py # Audio processing
|
||||
│ ├── rounds.py # Quiz round management
|
||||
│ └── users.py # User account management
|
||||
├── static/ # Static files (CSS, JS, images)
|
||||
└── templates/ # Jinja2 HTML templates
|
||||
├── admin/ # Admin interface templates
|
||||
├── auth/ # Authentication templates
|
||||
└── ... (other template categories)
|
||||
```
|
||||
|
||||
## Key Components
|
||||
|
||||
### Application Factory
|
||||
|
||||
The application is initialized using a factory pattern in `__init__.py`. This allows for flexible configuration and testing:
|
||||
|
||||
```python
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
|
||||
# Load configuration
|
||||
app.config.from_object(Config)
|
||||
|
||||
# Initialize extensions
|
||||
db.init_app(app)
|
||||
login_manager.init_app(app)
|
||||
|
||||
# Register blueprints
|
||||
from musicround.routes import core, auth, rounds, users, import_songs, import_routes, generate, process, api, deezer_routes, db_admin
|
||||
|
||||
app.register_blueprint(core.bp)
|
||||
app.register_blueprint(auth.bp)
|
||||
app.register_blueprint(rounds.bp)
|
||||
app.register_blueprint(users.bp)
|
||||
app.register_blueprint(import_songs.bp)
|
||||
app.register_blueprint(import_routes.bp)
|
||||
app.register_blueprint(generate.bp)
|
||||
app.register_blueprint(process.bp)
|
||||
app.register_blueprint(api.bp)
|
||||
app.register_blueprint(deezer_routes.bp)
|
||||
app.register_blueprint(db_admin.bp)
|
||||
|
||||
return app
|
||||
```
|
||||
|
||||
### Configuration Management
|
||||
|
||||
Configuration is handled in `config.py` using environment variables loaded from a `.env` file:
|
||||
|
||||
```python
|
||||
class Config:
|
||||
# Core configuration
|
||||
DEBUG = os.getenv("DEBUG", "True") == "True"
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', 'dev-key-please-change')
|
||||
|
||||
# API keys for various services
|
||||
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
||||
DEEPL_API_KEY = os.getenv("DEEPL_API_KEY")
|
||||
MEANINGCLOUD_API_KEY = os.getenv("MEANINGCLOUD_API_KEY")
|
||||
LASTFM_API_KEY = os.getenv("LASTFM_API_KEY")
|
||||
|
||||
# Database configuration
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///data/song_data.db')
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
|
||||
# OAuth provider configurations
|
||||
SPOTIFY_CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
|
||||
SPOTIFY_CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET")
|
||||
DROPBOX_APP_KEY = os.getenv("DROPBOX_APP_KEY")
|
||||
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
|
||||
# ... other configuration
|
||||
```
|
||||
|
||||
### Database Models
|
||||
|
||||
The data model is defined in `models.py` using SQLAlchemy ORM:
|
||||
|
||||
```python
|
||||
class User(db.Model, UserMixin):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(80), unique=True, nullable=False)
|
||||
email = db.Column(db.String(120), unique=True, nullable=True)
|
||||
password_hash = db.Column(db.String(128))
|
||||
is_admin = db.Column(db.Boolean, default=False)
|
||||
rounds = db.relationship('Round', backref='author', lazy=True)
|
||||
# OAuth tokens and preferences
|
||||
|
||||
class Song(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
title = db.Column(db.String(200), nullable=False)
|
||||
artist = db.Column(db.String(200), nullable=False)
|
||||
spotify_id = db.Column(db.String(50), nullable=True)
|
||||
preview_url = db.Column(db.String(255), nullable=True)
|
||||
year = db.Column(db.Integer, nullable=True)
|
||||
# Audio features and metadata
|
||||
|
||||
class Round(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
title = db.Column(db.String(200), nullable=False)
|
||||
description = db.Column(db.Text, nullable=True)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
||||
songs = db.relationship('RoundSong', backref='round', lazy=True, cascade="all, delete-orphan")
|
||||
# Round configuration and settings
|
||||
```
|
||||
|
||||
### Authentication System
|
||||
|
||||
The authentication system supports:
|
||||
|
||||
1. **Local Authentication**: Username/password authentication
|
||||
2. **OAuth Providers**:
|
||||
- Spotify
|
||||
- Google
|
||||
- Authentik (OpenID Connect)
|
||||
3. **Role-Based Access Control**: Admin vs. regular users
|
||||
|
||||
OAuth integration is handled through dedicated helper functions in `auth_helpers.py`:
|
||||
|
||||
```python
|
||||
def get_spotify_oauth():
|
||||
# Configure OAuth for Spotify
|
||||
|
||||
def get_google_oauth():
|
||||
# Configure OAuth for Google
|
||||
|
||||
def get_authentik_oauth():
|
||||
# Configure OAuth for Authentik
|
||||
```
|
||||
|
||||
### External Integrations
|
||||
|
||||
#### Spotify Integration
|
||||
|
||||
The `spotify_direct.py` module provides:
|
||||
- Authentication with Spotify API
|
||||
- Playlist import functionality
|
||||
- Track search and metadata retrieval
|
||||
- Audio feature access
|
||||
|
||||
#### Dropbox Integration
|
||||
|
||||
The `dropbox_helper.py` module enables:
|
||||
- OAuth authentication with Dropbox
|
||||
- File export to Dropbox
|
||||
- Folder management in Dropbox
|
||||
- Shared link generation
|
||||
|
||||
#### Deezer Integration
|
||||
|
||||
The `deezer_client.py` and related routes provide:
|
||||
- Authentication with Deezer API
|
||||
- Playlist import
|
||||
- Track search and preview access
|
||||
|
||||
#### OpenAI Integration
|
||||
|
||||
AI-powered features use the OpenAI API for:
|
||||
- Round generation suggestions
|
||||
- Lyric analysis
|
||||
- Song categorization
|
||||
|
||||
### Backup System
|
||||
|
||||
The backup system in `backup_helper.py` provides:
|
||||
|
||||
```python
|
||||
def create_backup(include_mp3=True, include_config=True, backup_name=None):
|
||||
# Create ZIP archive with database and optional files
|
||||
|
||||
def restore_from_backup(backup_file, force=False):
|
||||
# Restore system from backup archive
|
||||
|
||||
def list_backups():
|
||||
# List available backups with metadata
|
||||
|
||||
def verify_backup(backup_path):
|
||||
# Check backup integrity
|
||||
```
|
||||
|
||||
Features include:
|
||||
- Database dumps using SQLite backup API
|
||||
- MP3 file inclusion in backups
|
||||
- Configuration file backup
|
||||
- Scheduled backups
|
||||
- Retention policy management
|
||||
|
||||
## Request Flow
|
||||
|
||||
1. Request arrives at the Flask application
|
||||
2. Blueprint routes direct to the appropriate view function
|
||||
3. Authentication middleware checks for required permissions
|
||||
4. View function processes the request:
|
||||
- Database queries via SQLAlchemy models
|
||||
- External API calls where needed
|
||||
- Business logic processing
|
||||
5. Response is rendered using Jinja2 templates
|
||||
6. Rendered HTML is returned to the client
|
||||
|
||||
### Example Routes
|
||||
|
||||
```python
|
||||
@bp.route('/rounds/<int:round_id>')
|
||||
@login_required
|
||||
def view_round(round_id):
|
||||
round = Round.query.get_or_404(round_id)
|
||||
# Check permissions
|
||||
# Process data
|
||||
return render_template('rounds/view.html', round=round)
|
||||
|
||||
@bp.route('/rounds/<int:round_id>/export-to-dropbox', methods=['POST'])
|
||||
@login_required
|
||||
def export_to_dropbox(round_id):
|
||||
round = Round.query.get_or_404(round_id)
|
||||
# Check permissions
|
||||
# Export to Dropbox
|
||||
return jsonify({'success': True, 'message': 'Export successful'})
|
||||
```
|
||||
|
||||
## System Health Monitoring
|
||||
|
||||
The health monitoring system provides dashboards for:
|
||||
|
||||
1. **Database Health**: Connection status, table counts, size
|
||||
2. **Storage Health**: Directory status, file counts, permissions
|
||||
3. **External Service Status**: API connectivity checks
|
||||
4. **Version Information**: Application version, dependencies
|
||||
|
||||
## Extension Points
|
||||
|
||||
To extend Quizzical Beats, consider these integration points:
|
||||
|
||||
1. **New OAuth Providers**: Add provider configuration in `auth_helpers.py`
|
||||
2. **Additional Export Formats**: Implement in the rounds routes
|
||||
3. **New Music Data Sources**: Create a new client module similar to `spotify_direct.py` or `deezer_client.py`
|
||||
4. **Custom Audio Processing**: Extend the functionality in the `process.py` routes
|
||||
5. **AI Features**: Enhance OpenAI integration for additional content generation
|
||||
|
||||
## Technology Stack
|
||||
|
||||
- **Backend**: Python 3.8+, Flask 2.x
|
||||
- **Database**: SQLAlchemy 1.4+ with SQLite/PostgreSQL/MySQL
|
||||
- **Frontend**: TailwindCSS, Alpine.js, vanilla JavaScript
|
||||
- **Authentication**: Flask-Login, OAuth integrations
|
||||
- **APIs**: Spotify, Deezer, Dropbox, OpenAI, DeepL
|
||||
- **Media Processing**: FFmpeg, MP3 manipulation libraries
|
||||
- **Testing**: Pytest for unit and integration tests
|
||||
@@ -0,0 +1,195 @@
|
||||
# Contributing to Quizzical Beats
|
||||
|
||||
This guide provides information for developers who want to contribute to the Quizzical Beats project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Development Environment Setup
|
||||
|
||||
1. Fork the repository on GitHub
|
||||
2. Clone your fork locally:
|
||||
```bash
|
||||
git clone https://github.com/YOUR-USERNAME/musicround.git
|
||||
cd musicround
|
||||
```
|
||||
|
||||
3. Set up a virtual environment:
|
||||
```bash
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
```
|
||||
|
||||
4. Install development dependencies:
|
||||
```bash
|
||||
pip install -r requirements-dev.txt
|
||||
```
|
||||
|
||||
5. Set up pre-commit hooks:
|
||||
```bash
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
6. Configure your environment variables for development:
|
||||
```bash
|
||||
cp .env.example .env.dev
|
||||
# Edit .env.dev with your development settings
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Branching Strategy
|
||||
|
||||
We use a simplified Git flow approach:
|
||||
|
||||
- `main`: Production-ready code
|
||||
- `develop`: Main development branch
|
||||
- Feature branches: Created from `develop` for new features
|
||||
- Bugfix branches: Created from `develop` for bug fixes
|
||||
- Hotfix branches: Created from `main` for critical fixes
|
||||
|
||||
Naming conventions:
|
||||
- Feature branches: `feature/short-description`
|
||||
- Bug fix branches: `bugfix/issue-number-description`
|
||||
- Hotfix branches: `hotfix/issue-number-description`
|
||||
|
||||
### Making Changes
|
||||
|
||||
1. Create a new branch from `develop`:
|
||||
```bash
|
||||
git checkout develop
|
||||
git pull origin develop
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
2. Make your changes, following the coding standards
|
||||
|
||||
3. Run tests to ensure your changes don't break existing functionality:
|
||||
```bash
|
||||
pytest
|
||||
```
|
||||
|
||||
4. Commit your changes with a descriptive message:
|
||||
```bash
|
||||
git commit -am "Add feature: short description
|
||||
|
||||
More detailed explanation of the changes if needed.
|
||||
Fixes #123"
|
||||
```
|
||||
|
||||
5. Push your branch to your fork:
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
6. Create a pull request from your branch to the `develop` branch of the main repository
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### Python Style Guide
|
||||
|
||||
We follow PEP 8 with some modifications:
|
||||
|
||||
- Line length: 100 characters maximum
|
||||
- Use 4 spaces for indentation (no tabs)
|
||||
- Use docstrings for all classes and functions
|
||||
- Follow Google's Python Style Guide for docstrings
|
||||
|
||||
### Flask-Specific Guidelines
|
||||
|
||||
- Organize routes by functionality in blueprints
|
||||
- Keep view functions small and focused
|
||||
- Use decorators for common patterns
|
||||
- Prefer class-based views for complex endpoints
|
||||
|
||||
### Testing Guidelines
|
||||
|
||||
- Write tests for all new features
|
||||
- Maintain or improve test coverage
|
||||
- Structure tests in a similar way to the code they test
|
||||
- Use fixtures for common setup
|
||||
- Mock external services in tests
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Ensure your code passes all tests and linting checks
|
||||
2. Update documentation if your changes affect it
|
||||
3. Add your changes to the CHANGELOG.md under "Unreleased"
|
||||
4. Request a review from at least one maintainer
|
||||
5. Address any feedback from the reviewer
|
||||
6. Once approved, a maintainer will merge your PR
|
||||
|
||||
## Database Migrations
|
||||
|
||||
When making changes to the database schema:
|
||||
|
||||
1. Create a new migration script in the `migrations/` directory
|
||||
2. Name it descriptively (e.g., `add_user_preferences.py`)
|
||||
3. Implement both upgrade and downgrade paths
|
||||
4. Test the migration in both directions
|
||||
5. Document the changes in the database schema documentation
|
||||
|
||||
Example migration script:
|
||||
|
||||
```python
|
||||
# migrations/add_user_preferences.py
|
||||
|
||||
def upgrade(db):
|
||||
db.execute("""
|
||||
ALTER TABLE user
|
||||
ADD COLUMN preferences JSON NULL
|
||||
""")
|
||||
|
||||
def downgrade(db):
|
||||
db.execute("""
|
||||
ALTER TABLE user
|
||||
DROP COLUMN preferences
|
||||
""")
|
||||
```
|
||||
|
||||
## Documentation Guidelines
|
||||
|
||||
When contributing to the documentation:
|
||||
|
||||
1. Use Markdown for all documentation files
|
||||
2. Keep language clear and concise
|
||||
3. Include code examples where appropriate
|
||||
4. Follow the existing documentation structure
|
||||
5. Update the documentation when implementing new features
|
||||
|
||||
## Release Process
|
||||
|
||||
Our release process follows these steps:
|
||||
|
||||
1. Features and bugfixes are merged into `develop`
|
||||
2. When ready for release, we:
|
||||
- Create a release branch `release/X.Y.Z`
|
||||
- Update version number in `version.py`
|
||||
- Finalize CHANGELOG.md
|
||||
- Run final tests
|
||||
3. The release branch is merged into `main`
|
||||
4. A tag is created for the release
|
||||
5. `main` is merged back into `develop`
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you need help or have questions:
|
||||
|
||||
- Check the existing documentation
|
||||
- Look at similar features or patterns in the codebase
|
||||
- Reach out on the project issues page
|
||||
- Contact the maintainers directly
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
|
||||
|
||||
### Our Standards
|
||||
|
||||
- Be respectful and inclusive
|
||||
- Accept constructive criticism gracefully
|
||||
- Focus on what's best for the community
|
||||
- Show empathy towards other community members
|
||||
|
||||
## License
|
||||
|
||||
By contributing to Quizzical Beats, you agree that your contributions will be licensed under the project's MIT License.
|
||||
@@ -0,0 +1,289 @@
|
||||
# Database Schema
|
||||
|
||||
This document provides an overview of the Quizzical Beats database schema, including tables, relationships, and key fields.
|
||||
|
||||
## Entity Relationship Diagram
|
||||
|
||||
The following diagram illustrates the relationships between the main entities in Quizzical Beats:
|
||||
|
||||
```
|
||||
+---------------+ +---------------+ +---------------+
|
||||
| User | | Round | | Song |
|
||||
+---------------+ +---------------+ +---------------+
|
||||
| id |<----->| id | | id |
|
||||
| username | | name | | title |
|
||||
| email | | round_type | | artist |
|
||||
| password_hash | | songs |-------| spotify_id |
|
||||
| is_admin | | round_criteria| | deezer_id |
|
||||
| roles |----+ | created_at | | isrc |
|
||||
| auth_provider | | | updated_at | | preview_url |
|
||||
| oauth_tokens | | | mp3_generated | | cover_url |
|
||||
+---------------+ | | pdf_generated | | tags |----+
|
||||
^ | +---------------+ | audio_features| |
|
||||
| | +---------------+ |
|
||||
| | ^ |
|
||||
| v | |
|
||||
+---------------+ +---------------+ +---------------+ |
|
||||
| UserPreferences| | Role | | RoundExport | |
|
||||
+---------------+ +---------------+ +---------------+ |
|
||||
| id | | id | | id | |
|
||||
| user_id | | name | | round_id | |
|
||||
| default_tts | | description | | user_id | |
|
||||
| enable_intro | +---------------+ | export_type | |
|
||||
| theme | | timestamp | |
|
||||
+---------------+ | destination | |
|
||||
+---------------+ |
|
||||
|
|
||||
+---------------+ +---------------+ |
|
||||
| SystemSetting | | Tag |<--------+
|
||||
+---------------+ +---------------+
|
||||
| id | | id |
|
||||
| key | | name |
|
||||
| value | | created_at |
|
||||
+---------------+ +---------------+
|
||||
```
|
||||
|
||||
## Tables
|
||||
|
||||
### User
|
||||
|
||||
The `User` table stores user account information and authentication details.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-----------------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| username | String(80) | User's display name |
|
||||
| email | String(120) | User's email address |
|
||||
| password_hash | String(255) | Hashed password (nullable for OAuth-only users) |
|
||||
| first_name | String(50) | User's first name |
|
||||
| last_name | String(50) | User's last name |
|
||||
| active | Boolean | Account active status |
|
||||
| is_admin | Boolean | Administrator privileges flag |
|
||||
| created_at | DateTime | Account creation timestamp |
|
||||
| last_login | DateTime | Last login timestamp |
|
||||
| reset_token | String(100) | Password reset token |
|
||||
| reset_token_expiry | DateTime | Token expiration time |
|
||||
| auth_provider | String(20) | Authentication provider (local, google, etc.) |
|
||||
| oauth_id | String(100) | Spotify user ID |
|
||||
| spotify_token | Text | Spotify access token |
|
||||
| spotify_refresh_token | Text | Spotify refresh token |
|
||||
| spotify_token_expiry | DateTime | Spotify token expiration |
|
||||
| google_id | String(100) | Google user ID |
|
||||
| google_token | Text | Google access token |
|
||||
| google_refresh_token | Text | Google refresh token |
|
||||
| authentik_id | String(100) | Authentik user ID |
|
||||
| authentik_token | Text | Authentik access token |
|
||||
| authentik_refresh_token | Text | Authentik refresh token |
|
||||
| dropbox_id | String(100) | Dropbox user ID |
|
||||
| dropbox_token | Text | Dropbox access token |
|
||||
| dropbox_refresh_token | Text | Dropbox refresh token |
|
||||
| dropbox_token_expiry | DateTime | Dropbox token expiration |
|
||||
| dropbox_export_path | String(255) | User's preferred Dropbox export folder |
|
||||
| intro_mp3 | String(255) | Custom intro MP3 path |
|
||||
| outro_mp3 | String(255) | Custom outro MP3 path |
|
||||
| replay_mp3 | String(255) | Custom replay MP3 path |
|
||||
|
||||
### UserPreferences
|
||||
|
||||
The `UserPreferences` table stores user-specific settings.
|
||||
|
||||
| Column | Type | Description |
|
||||
|----------------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| user_id | Integer | Foreign key to User |
|
||||
| default_tts_service | String(32) | Default text-to-speech service (polly, etc.) |
|
||||
| enable_intro | Boolean | Whether to enable intro sound |
|
||||
| theme | String(16) | UI theme preference (light, dark) |
|
||||
|
||||
### Role
|
||||
|
||||
The `Role` table defines user roles for permission management.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| name | String(50) | Role name |
|
||||
| description | String(255) | Role description |
|
||||
|
||||
### user_roles
|
||||
|
||||
The `user_roles` table is an association table linking users to roles.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-------------|--------------|--------------------------------------------------|
|
||||
| user_id | Integer | Foreign key to User |
|
||||
| role_id | Integer | Foreign key to Role |
|
||||
|
||||
### Song
|
||||
|
||||
The `Song` table stores detailed information about music tracks from various sources.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-----------------------|--------------|-------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| spotify_id | String(100) | Spotify track ID |
|
||||
| deezer_id | Integer | Deezer track ID |
|
||||
| isrc | String(20) | International Standard Recording Code |
|
||||
| title | String(200) | Song title |
|
||||
| artist | String(200) | Artist name |
|
||||
| album_name | String(200) | Album name |
|
||||
| genre | String(100) | Music genre |
|
||||
| year | Integer | Release year |
|
||||
| preview_url | String(500) | Primary audio preview URL |
|
||||
| cover_url | String(500) | Primary album cover URL |
|
||||
| spotify_preview_url | String(500) | Spotify-specific preview URL |
|
||||
| deezer_preview_url | String(500) | Deezer-specific preview URL |
|
||||
| apple_preview_url | String(500) | Apple Music preview URL |
|
||||
| youtube_preview_url | String(500) | YouTube preview URL |
|
||||
| spotify_cover_url | String(500) | Spotify cover image URL |
|
||||
| deezer_cover_url | String(500) | Deezer cover image URL |
|
||||
| apple_cover_url | String(500) | Apple Music cover image URL |
|
||||
| popularity | Integer | Popularity score (0-100) |
|
||||
| used_count | Integer | Number of times used in rounds |
|
||||
| source | String(20) | Data source (spotify, deezer, acrcloud) |
|
||||
| import_date | DateTime | When the song was imported |
|
||||
| added_at | DateTime | When the song was added |
|
||||
| last_used | DateTime | When the song was last used |
|
||||
| metadata_sources | String(500) | Comma-separated list of metadata sources |
|
||||
| acousticness | Float | Spotify audio feature - acousticness (0.0-1.0) |
|
||||
| danceability | Float | Spotify audio feature - danceability (0.0-1.0) |
|
||||
| energy | Float | Spotify audio feature - energy (0.0-1.0) |
|
||||
| instrumentalness | Float | Spotify audio feature - instrumentalness |
|
||||
| key | Integer | Spotify audio feature - musical key |
|
||||
| liveness | Float | Spotify audio feature - liveness (0.0-1.0) |
|
||||
| loudness | Float | Spotify audio feature - loudness (dB) |
|
||||
| mode | Integer | Spotify audio feature - modality (major/minor) |
|
||||
| speechiness | Float | Spotify audio feature - speechiness (0.0-1.0) |
|
||||
| tempo | Float | Spotify audio feature - tempo (BPM) |
|
||||
| time_signature | Integer | Spotify audio feature - time signature |
|
||||
| valence | Float | Spotify audio feature - valence (0.0-1.0) |
|
||||
| duration_ms | Integer | Track duration in milliseconds |
|
||||
| analysis_url | String(500) | URL to full audio analysis |
|
||||
| additional_data | Text | Additional data as JSON |
|
||||
|
||||
### Tag
|
||||
|
||||
The `Tag` table stores tags for categorizing songs.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| name | String(50) | Tag name |
|
||||
| created_at | DateTime | Creation timestamp |
|
||||
|
||||
### SongTag
|
||||
|
||||
The `SongTag` table links songs to tags.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-------------|--------------|--------------------------------------------------|
|
||||
| song_id | Integer | Foreign key to Song |
|
||||
| tag_id | Integer | Foreign key to Tag |
|
||||
| created_at | DateTime | When the tag was applied |
|
||||
|
||||
### Round
|
||||
|
||||
The `Round` table stores music quiz rounds.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-----------------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| name | String(200) | Round name |
|
||||
| round_type | String(50) | Type of round (genre, decade, etc.) |
|
||||
| round_criteria_used | String(500) | Criteria used to generate the round |
|
||||
| songs | Text | JSON string of song IDs in order |
|
||||
| genre | String(100) | Genre of the round (if applicable) |
|
||||
| decade | String(10) | Decade of the round (if applicable) |
|
||||
| tag | String(50) | Tag of the round (if applicable) |
|
||||
| created_at | DateTime | Creation timestamp |
|
||||
| updated_at | DateTime | Last update timestamp |
|
||||
| mp3_generated | Boolean | Flag indicating if MP3 has been generated |
|
||||
| pdf_generated | Boolean | Flag indicating if PDF has been generated |
|
||||
| last_generated_at | DateTime | When files were last generated |
|
||||
|
||||
### RoundExport
|
||||
|
||||
The `RoundExport` table tracks exports of rounds to various destinations.
|
||||
|
||||
| Column | Type | Description |
|
||||
|---------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| round_id | Integer | Foreign key to Round |
|
||||
| user_id | Integer | Foreign key to User |
|
||||
| export_type | String(20) | Export type (dropbox, email, etc.) |
|
||||
| timestamp | DateTime | Export timestamp |
|
||||
| destination | String(500) | Destination (path, email, etc.) |
|
||||
| include_mp3s | Boolean | Whether MP3s were included |
|
||||
| status | String(20) | Export status (success, failed) |
|
||||
| error_message | Text | Error message if export failed |
|
||||
|
||||
### SystemSetting
|
||||
|
||||
The `SystemSetting` table stores application-wide settings.
|
||||
|
||||
| Column | Type | Description |
|
||||
|-------------|--------------|--------------------------------------------------|
|
||||
| id | Integer | Primary key |
|
||||
| key | String(64) | Setting key |
|
||||
| value | Text | Setting value |
|
||||
|
||||
## Key Relationships
|
||||
|
||||
### User Relationships
|
||||
|
||||
- **User → UserPreferences**: One-to-one. A user has one set of preferences.
|
||||
- **User ↔ Roles**: Many-to-many through user_roles. A user can have multiple roles, and a role can be assigned to multiple users.
|
||||
- **User → RoundExports**: One-to-many. A user can create multiple exports.
|
||||
|
||||
### Song Relationships
|
||||
|
||||
- **Song ↔ Tags**: Many-to-many through SongTag. A song can have multiple tags, and a tag can be applied to multiple songs.
|
||||
- **Song → Rounds**: Many-to-many (implicit). Songs are referenced in the Round.songs field as a JSON string of IDs.
|
||||
|
||||
### Round Relationships
|
||||
|
||||
- **Round → RoundExports**: One-to-many. A round can have multiple exports.
|
||||
- **Round → Songs**: Many-to-many (implicit). A round contains multiple songs referenced by ID.
|
||||
|
||||
## Data Model Features
|
||||
|
||||
### OAuth Integration
|
||||
|
||||
The User model integrates OAuth provider information directly:
|
||||
- Support for Spotify, Google, Authentik and Dropbox OAuth providers
|
||||
- Token storage and refresh token functionality
|
||||
- Provider-specific user IDs
|
||||
|
||||
### Audio Features
|
||||
|
||||
The Song model includes detailed audio features from Spotify:
|
||||
- Acoustic characteristics (acousticness, instrumentalness)
|
||||
- Rhythmic characteristics (tempo, time_signature)
|
||||
- Mood characteristics (valence, energy, danceability)
|
||||
- Technical characteristics (loudness, key, mode)
|
||||
|
||||
### Multi-Source Integration
|
||||
|
||||
Songs can be imported from multiple sources:
|
||||
- Spotify API
|
||||
- Deezer API
|
||||
- ACRCloud identification service
|
||||
- Each song stores source-specific IDs and URLs
|
||||
|
||||
### Tagging System
|
||||
|
||||
The tagging system allows flexible organization:
|
||||
- Songs can be tagged for easier categorization
|
||||
- Tags provide a way to group songs by custom criteria
|
||||
|
||||
## Data Migrations
|
||||
|
||||
The database schema evolves over time through migrations. Migration scripts are stored in the `migrations/` directory:
|
||||
|
||||
- `add_preview_urls.py`: Added Song.preview_url field
|
||||
- `add_song_fields.py`: Added additional metadata fields to Song
|
||||
- `add_spotify_audio_features.py`: Added audio analysis data
|
||||
- `add_oauth_providers.py`: Extended OAuth provider support
|
||||
- `add_tag_system.py`: Added tagging functionality
|
||||
- `add_dropbox_oauth.py`: Added Dropbox OAuth support
|
||||
- `add_dropbox_export_path.py`: Added export path tracking
|
||||
@@ -0,0 +1,167 @@
|
||||
# OAuth Integration
|
||||
|
||||
This document details how Quizzical Beats integrates with OAuth providers, including Spotify and Dropbox.
|
||||
|
||||
## Overview
|
||||
|
||||
Quizzical Beats uses OAuth 2.0 to authenticate with third-party services. The current OAuth implementation provides:
|
||||
|
||||
- API access to third-party services (Spotify API, Dropbox files)
|
||||
- Token storage and refresh mechanisms
|
||||
- Fallback strategies when tokens expire
|
||||
|
||||
## OAuth Provider Configuration
|
||||
|
||||
### Spotify OAuth
|
||||
|
||||
Spotify OAuth is used for API access:
|
||||
|
||||
```python
|
||||
SPOTIFY_CLIENT_ID = os.environ.get('SPOTIFY_CLIENT_ID')
|
||||
SPOTIFY_CLIENT_SECRET = os.environ.get('SPOTIFY_CLIENT_SECRET')
|
||||
SPOTIFY_REDIRECT_URI = os.environ.get('SPOTIFY_REDIRECT_URI', 'http://localhost:5000/auth/spotify/callback')
|
||||
```
|
||||
|
||||
### Dropbox OAuth
|
||||
|
||||
Dropbox OAuth enables file export functionality:
|
||||
|
||||
```python
|
||||
DROPBOX_APP_KEY = os.environ.get('DROPBOX_APP_KEY')
|
||||
DROPBOX_APP_SECRET = os.environ.get('DROPBOX_APP_SECRET')
|
||||
DROPBOX_REDIRECT_URI = os.environ.get('DROPBOX_REDIRECT_URI', 'http://localhost:5000/users/dropbox/callback')
|
||||
```
|
||||
|
||||
## Dropbox Integration Implementation
|
||||
|
||||
The Dropbox OAuth integration is implemented directly in the User model:
|
||||
|
||||
```python
|
||||
class User(db.Model):
|
||||
# Other user fields...
|
||||
|
||||
# Dropbox OAuth fields
|
||||
dropbox_id = db.Column(db.String(100), nullable=True)
|
||||
dropbox_token = db.Column(db.Text(), nullable=True)
|
||||
dropbox_refresh_token = db.Column(db.Text(), nullable=True)
|
||||
dropbox_token_expiry = db.Column(db.DateTime(), nullable=True)
|
||||
dropbox_export_path = db.Column(db.String(255), nullable=True)
|
||||
```
|
||||
|
||||
### Dropbox Authentication Flow
|
||||
|
||||
1. User initiates Dropbox connection from their profile page
|
||||
2. Application redirects to Dropbox's authorization page
|
||||
3. User grants permission to the application
|
||||
4. Dropbox redirects back to our callback URL with an authorization code
|
||||
5. Application exchanges the code for access and refresh tokens
|
||||
6. Tokens and basic user info are stored in the user's record
|
||||
|
||||
Example of the callback handler:
|
||||
|
||||
```python
|
||||
@users_bp.route('/dropbox/callback')
|
||||
@login_required
|
||||
def dropbox_callback():
|
||||
# Handle errors
|
||||
if 'error' in request.args:
|
||||
flash(f'Dropbox authorization failed: {error}', 'error')
|
||||
return redirect(url_for('users.profile'))
|
||||
|
||||
# Exchange authorization code for tokens
|
||||
code = request.args.get('code')
|
||||
token_info = exchange_code_for_token(code)
|
||||
|
||||
# Store tokens in the user model
|
||||
current_user.dropbox_token = token_info.get('access_token')
|
||||
current_user.dropbox_refresh_token = token_info.get('refresh_token')
|
||||
|
||||
# Store expiration time
|
||||
expires_in = token_info.get('expires_in', 14400) # Default to 4 hours
|
||||
current_user.dropbox_token_expiry = datetime.now() + timedelta(seconds=expires_in)
|
||||
|
||||
# Get and store account info
|
||||
account_info = get_dropbox_account_info(current_user.dropbox_token)
|
||||
if account_info:
|
||||
current_user.dropbox_id = account_info.get('account_id')
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return redirect(url_for('users.profile'))
|
||||
```
|
||||
|
||||
## Token Management
|
||||
|
||||
### Token Refresh
|
||||
|
||||
Tokens are refreshed when they expire. The Dropbox implementation uses:
|
||||
|
||||
```python
|
||||
def get_current_user_dropbox_token():
|
||||
"""Get a valid Dropbox access token for the current user, refreshing if needed"""
|
||||
if not current_user or not current_user.is_authenticated:
|
||||
return None
|
||||
|
||||
# Check if token exists and is valid
|
||||
if (current_user.dropbox_token and
|
||||
current_user.dropbox_token_expiry and
|
||||
current_user.dropbox_token_expiry > datetime.now() + timedelta(minutes=5)):
|
||||
return current_user.dropbox_token
|
||||
|
||||
# Token is missing or about to expire - try to refresh
|
||||
if current_user.dropbox_refresh_token:
|
||||
# Refresh the token
|
||||
token_info = refresh_dropbox_token(current_user.dropbox_refresh_token)
|
||||
|
||||
if token_info and 'access_token' in token_info:
|
||||
# Update token in database
|
||||
current_user.dropbox_token = token_info['access_token']
|
||||
expires_in = token_info.get('expires_in', 14400)
|
||||
current_user.dropbox_token_expiry = datetime.now() + timedelta(seconds=expires_in)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return current_user.dropbox_token
|
||||
|
||||
return None
|
||||
```
|
||||
|
||||
### Token Revocation
|
||||
|
||||
Users can disconnect their Dropbox accounts:
|
||||
|
||||
```python
|
||||
@users_bp.route('/dropbox/disconnect', methods=['POST'])
|
||||
@login_required
|
||||
def dropbox_disconnect():
|
||||
"""Disconnect user's Dropbox account"""
|
||||
# Revoke token if present
|
||||
if current_user.dropbox_token:
|
||||
try:
|
||||
revoke_token(current_user.dropbox_token)
|
||||
except Exception as e:
|
||||
# Log the error but continue
|
||||
pass
|
||||
|
||||
# Clear Dropbox credentials
|
||||
current_user.dropbox_token = None
|
||||
current_user.dropbox_refresh_token = None
|
||||
current_user.dropbox_token_expiry = None
|
||||
current_user.dropbox_id = None
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return redirect(url_for('users.profile'))
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
When working with OAuth:
|
||||
|
||||
- Always use HTTPS in production
|
||||
- Store tokens securely
|
||||
- Implement proper token refresh
|
||||
- Handle token revocation when users disconnect accounts
|
||||
- Request minimal scope access
|
||||
- Validate all OAuth-related inputs
|
||||
- Use the official provider documentation for the most up-to-date OAuth implementation details
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
## General Questions
|
||||
|
||||
### What is Quizzical Beats?
|
||||
Quizzical Beats is a web application designed to help quiz hosts create music quiz rounds. It integrates with Spotify to access a vast music library and provides tools for round generation, song management, and export options.
|
||||
|
||||
### Is Quizzical Beats free to use?
|
||||
Quizzical Beats is free for personal use. Depending on your deployment, your administrator may have established specific licensing terms for your organization.
|
||||
|
||||
### Which browsers are supported?
|
||||
Quizzical Beats works with all modern browsers including Chrome, Firefox, Safari, and Edge. For the best experience, we recommend keeping your browser updated to the latest version.
|
||||
|
||||
## Account Management
|
||||
|
||||
### How do I create an account?
|
||||
You can create an account by visiting the login page and clicking "Register." You can sign up with an email and password or use OAuth providers like Spotify, Google, or Authentik (if enabled by your administrator).
|
||||
|
||||
### Can I change my password?
|
||||
Yes, you can change your password by going to Profile > Security > Change Password.
|
||||
|
||||
### I forgot my password. How do I reset it?
|
||||
On the login page, click the "Forgot Password" link and follow the instructions sent to your email.
|
||||
|
||||
### How do I connect my Spotify account?
|
||||
Go to Profile > Connected Accounts and click "Connect" next to Spotify. You'll be redirected to Spotify to authorize the connection.
|
||||
|
||||
### Why should I connect my Dropbox account?
|
||||
Connecting your Dropbox account allows you to export quiz rounds directly to your Dropbox, making it easy to access them from any device or share them with others.
|
||||
|
||||
## Song Management
|
||||
|
||||
### How many songs can I import at once?
|
||||
You can import up to 100 songs at once when importing from a Spotify playlist. For CSV imports, there's a limit of 500 songs per file.
|
||||
|
||||
### Why are some of my songs missing preview URLs?
|
||||
Spotify doesn't provide preview URLs for all tracks. If a song doesn't have a preview URL, you'll need to add your own audio snippet or find an alternative version of the song.
|
||||
|
||||
### How can I edit song metadata?
|
||||
Select the song from your library and click "Edit." You can then modify its metadata including title, artist, album, and year.
|
||||
|
||||
### Can I add my own songs not found on Spotify?
|
||||
Yes, you can manually add songs to your library by going to Songs > Add New Song and filling in the details. You can also upload your own MP3 snippet.
|
||||
|
||||
## Round Creation
|
||||
|
||||
### How many rounds can I create?
|
||||
There's no fixed limit on the number of rounds you can create, though performance may decrease with very large numbers of rounds (1000+).
|
||||
|
||||
### What's the ideal number of songs in a round?
|
||||
Most quiz hosts find 8-10 songs per round works well, providing enough variety without making the round too long.
|
||||
|
||||
### Can I reuse songs across multiple rounds?
|
||||
Yes, you can add the same song to multiple rounds. The song library keeps track of all your songs, allowing you to reuse them as needed.
|
||||
|
||||
### How do I create a themed round?
|
||||
Use the filter options when creating a round to focus on specific genres, decades, or artists. You can also create a custom round by manually selecting songs that fit your theme.
|
||||
|
||||
## Exporting
|
||||
|
||||
### What export formats are available?
|
||||
Quizzical Beats supports exporting rounds as PDF (questions and answers), MP3 (audio files), ZIP (combined package), and CSV (raw data).
|
||||
|
||||
### How do I export directly to Dropbox?
|
||||
Connect your Dropbox account, then when exporting a round, select "Export to Dropbox" as the destination. You can then choose which folder to export to.
|
||||
|
||||
### Can I customize the exported PDFs?
|
||||
Yes, you can customize the PDF header, footer, and overall layout in Settings > Export Preferences.
|
||||
|
||||
### Why is my export taking a long time?
|
||||
Exports with many rounds or large audio files may take longer. MP3 generation and packaging can be resource-intensive.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Spotify connection isn't working
|
||||
Try disconnecting and reconnecting your Spotify account. If the issue persists, ensure that your Spotify account is active and that you've granted all the required permissions.
|
||||
|
||||
### The application seems slow
|
||||
Performance depends on several factors including your device, internet connection, and the size of your song library. Try clearing your browser cache or using a different browser.
|
||||
|
||||
### Audio playback issues
|
||||
If you're experiencing audio playback issues, check your device volume, try a different browser, or ensure that you have a stable internet connection.
|
||||
|
||||
### I found a bug. How do I report it?
|
||||
Contact your system administrator or send an email to support@kaufdeinquiz.com with details about the bug and steps to reproduce it.
|
||||
|
||||
## Administration
|
||||
|
||||
### How do I back up my data?
|
||||
Administrators can create backups through the Admin > System > Backup interface. Backups can be scheduled or created manually.
|
||||
|
||||
### How do I restore from a backup?
|
||||
Go to Admin > System > Restore, select the backup file, and follow the instructions to restore your data.
|
||||
|
||||
### Can I run Quizzical Beats offline?
|
||||
Quizzical Beats requires internet access to connect to Spotify and other services. However, once songs are imported, you can use some features offline.
|
||||
|
||||
### How do I update Quizzical Beats?
|
||||
Administrators can update the application by pulling the latest version from the repository and restarting the application. For Docker installations, update the container image.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Welcome to Quizzical Beats Documentation
|
||||
|
||||
{ align=center }
|
||||
|
||||
## Music Quiz Round Generator
|
||||
|
||||
**Quizzical Beats** is a comprehensive web application for creating engaging music quiz rounds. Leveraging APIs from services like Spotify and Last.fm, it allows quiz hosts to generate rounds based on specific genres, decades, or completely random criteria, making your music quizzes dynamic and entertaining.
|
||||
|
||||
## Features
|
||||
|
||||
- **Spotify Integration**: Import songs and playlists directly from Spotify
|
||||
- **Dynamic Round Creation**: Generate rounds based on genres, decades, or tags
|
||||
- **Export Options**: Download as PDFs or playable MP3s
|
||||
- **Dropbox Integration**: Export rounds directly to your Dropbox
|
||||
- **User Accounts**: Personal settings, custom audio intros/outros
|
||||
- **Multiple Authentication Methods**: Local, Google, and Authentik OAuth
|
||||
- **System Backup & Restore**: Comprehensive backup solution with scheduling
|
||||
- **Admin Dashboard**: Monitor system health and manage users
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
This documentation is organized into several sections:
|
||||
|
||||
- **[User Guide](user-guide/getting-started.md)**: Learn how to use Quizzical Beats
|
||||
- **[Admin Guide](admin-guide/installation.md)**: Installation and maintenance information
|
||||
- **[Developer Guide](developer-guide/architecture.md)**: Technical documentation for developers
|
||||
- **[FAQ](faq.md)**: Frequently asked questions
|
||||
- **[Changelog](changelog.md)**: Version history and feature additions
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started with Quizzical Beats, visit the [Getting Started](user-guide/getting-started.md) guide.
|
||||
|
||||
## Support
|
||||
|
||||
If you need help using Quizzical Beats, please check the [FAQ](faq.md) first. If your question isn't answered there, contact support at [support@kaufdeinquiz.com](mailto:support@kaufdeinquiz.com).
|
||||
+13
-11
@@ -1,6 +1,6 @@
|
||||
# OAuth Integration Callback URLs
|
||||
|
||||
This document provides information about the OAuth callback URLs used in Quizzical Beats for various authentication providers.
|
||||
This document provides the callback URLs needed when configuring OAuth integration with various providers for Quizzical Beats.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -30,18 +30,20 @@ When configuring Authentik:
|
||||
|
||||
### Spotify API
|
||||
|
||||
**Callback URL:** `https://your-domain.com/users/spotify-callback`
|
||||
**Local Development:** `http://localhost:5000/users/spotify-callback`
|
||||
**Callback URL:** `https://your-domain.com/auth/spotify/callback`
|
||||
**Local Development:** `http://localhost:5000/auth/spotify/callback`
|
||||
|
||||
When configuring Spotify in the Spotify Developer Dashboard:
|
||||
1. Go to your app's settings
|
||||
2. Add the above URLs to the "Redirect URIs" section
|
||||
3. Save the changes
|
||||
1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/)
|
||||
2. Create or select your app
|
||||
3. Click "Edit Settings"
|
||||
4. Add the above URLs to the "Redirect URIs" section
|
||||
5. Save your changes
|
||||
|
||||
### Dropbox API
|
||||
|
||||
**Callback URL:** `https://your-domain.com/users/dropbox-callback`
|
||||
**Local Development:** `http://localhost:5000/users/dropbox-callback`
|
||||
**Callback URL:** `https://your-domain.com/users/dropbox/callback`
|
||||
**Local Development:** `http://localhost:5000/users/dropbox/callback`
|
||||
|
||||
When configuring Dropbox in the Dropbox Developer Console:
|
||||
1. Go to your app's settings in the [Dropbox App Console](https://www.dropbox.com/developers/apps)
|
||||
@@ -50,9 +52,9 @@ When configuring Dropbox in the Dropbox Developer Console:
|
||||
- `files.content.read`
|
||||
- `files.content.write`
|
||||
- `sharing.write`
|
||||
- `account_info.read`
|
||||
- `offline_access` (for refresh tokens)
|
||||
4. Set the app status to "Production" if it's still in development mode
|
||||
5. In the "Permissions" tab, ensure all required scopes are selected
|
||||
|
||||
## Environment Variables
|
||||
|
||||
@@ -66,10 +68,10 @@ GOOGLE_REDIRECT_URI=http://localhost:5000/users/login/google/callback
|
||||
AUTHENTIK_REDIRECT_URI=http://localhost:5000/users/login/authentik/callback
|
||||
|
||||
# For Spotify API
|
||||
SPOTIFY_REDIRECT_URI=http://localhost:5000/users/spotify-callback
|
||||
SPOTIFY_REDIRECT_URI=http://localhost:5000/auth/spotify/callback
|
||||
|
||||
# For Dropbox API
|
||||
# DROPBOX_REDIRECT_URI=http://localhost:5000/users/dropbox-callback
|
||||
# DROPBOX_REDIRECT_URI=http://localhost:5000/users/dropbox/callback
|
||||
# Note: The Dropbox URL is automatically generated using Flask's url_for function
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Documentation dependencies
|
||||
mkdocs>=1.4.0
|
||||
mkdocs-material>=9.0.0
|
||||
mkdocstrings>=0.21.0
|
||||
mkdocstrings-python>=1.0.0
|
||||
pymdown-extensions>=9.0
|
||||
Pygments>=2.14.0
|
||||
@@ -0,0 +1,111 @@
|
||||
# Account Management
|
||||
|
||||
This guide explains how to manage your Quizzical Beats account, including profile settings, integrations, and authentication options.
|
||||
|
||||
## Profile Settings
|
||||
|
||||
Manage your personal information and preferences:
|
||||
|
||||
1. Click your username in the top-right corner
|
||||
2. Select "Profile" from the dropdown menu
|
||||
3. Here you can:
|
||||
- Update your username
|
||||
- Change your email address
|
||||
- Edit your first and last name
|
||||
- Modify your password
|
||||
- Update your Dropbox export path
|
||||
|
||||
## Authentication Methods
|
||||
|
||||
Quizzical Beats supports multiple authentication methods:
|
||||
|
||||
### Local Username/Password
|
||||
|
||||
1. Go to Profile > Change Password
|
||||
2. You can:
|
||||
- Update your current password
|
||||
- View your last login time
|
||||
|
||||
### OAuth Providers
|
||||
|
||||
Connect and use third-party authentication:
|
||||
|
||||
1. Navigate to your Profile page
|
||||
2. Here you can connect/disconnect:
|
||||
- Spotify account
|
||||
- Google account (if enabled by your administrator)
|
||||
- Dropbox account (for file exports)
|
||||
- Authentik (if enabled by your administrator)
|
||||
|
||||
## Email-Based Account Identification
|
||||
|
||||
Quizzical Beats uses your email address as the primary identifier for your account, which provides several benefits:
|
||||
|
||||
### Single Account Across Login Methods
|
||||
|
||||
- If you login with username/password and later use Google or Authentik with the same email address, **you'll be automatically logged into the same account**
|
||||
- There's no need to manually link accounts - the system recognizes you based on your email
|
||||
- Your profile data, saved rounds, and settings remain consistent regardless of how you login
|
||||
|
||||
For example:
|
||||
1. You register with username "musicfan" and email "you@example.com"
|
||||
2. Later, you click "Sign in with Google" using the same email "you@example.com"
|
||||
3. The system will recognize and log you into your existing "musicfan" account
|
||||
4. All your data, settings, and history will be preserved
|
||||
|
||||
### Switching Between Login Methods
|
||||
|
||||
You can freely alternate between:
|
||||
- Username/password login
|
||||
- Google authentication (if enabled)
|
||||
- Authentik authentication (if enabled)
|
||||
|
||||
As long as all methods use the same email address, you'll always access the same account.
|
||||
|
||||
### Benefits
|
||||
|
||||
- **Simplified Experience**: No need to remember which login method you used previously
|
||||
- **Data Consistency**: Your preferences and data remain unified across login methods
|
||||
- **Flexible Authentication**: Choose the most convenient login method for your current situation
|
||||
|
||||
## Managing OAuth Connections
|
||||
|
||||
For each connected service:
|
||||
|
||||
1. View connection status and details
|
||||
2. Disconnect services when needed
|
||||
3. Re-authorize when tokens expire
|
||||
4. See token expiration information
|
||||
|
||||
## Custom Audio Files
|
||||
|
||||
Upload and manage your custom audio files:
|
||||
|
||||
1. Navigate to Profile > Audio Settings
|
||||
2. Here you can:
|
||||
- Upload custom intro music
|
||||
- Upload custom outro music
|
||||
- Upload custom replay sound
|
||||
- Generate audio using text-to-speech
|
||||
|
||||
## Account Security
|
||||
|
||||
Keep your account secure:
|
||||
|
||||
1. Use a strong, unique password
|
||||
2. Log out from shared computers
|
||||
3. Check your last login time
|
||||
4. Review connected applications regularly
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Can't Log In**:
|
||||
1. Try the "Forgot Password" option
|
||||
2. Check that you're using the correct OAuth provider
|
||||
3. Clear browser cookies and cache
|
||||
4. Contact your administrator if problems persist
|
||||
|
||||
**OAuth Connection Issues**:
|
||||
1. Disconnect and reconnect the service
|
||||
2. Ensure you're granting all required permissions
|
||||
3. Check that your third-party account is active and in good standing
|
||||
@@ -0,0 +1,75 @@
|
||||
# Creating Rounds
|
||||
|
||||
This guide explains how to create, configure, and manage music quiz rounds in Quizzical Beats.
|
||||
|
||||
## Understanding Round Types
|
||||
|
||||
Quizzical Beats offers several types of quiz rounds:
|
||||
|
||||
- **Random Selection**: Creates a diverse round with randomly selected songs
|
||||
- **By Decade**: Songs from a specific decade that has been used the least in your quizzes
|
||||
- **By Genre**: Songs from a specific genre that has been used the least in your quizzes
|
||||
- **By Tag**: Songs that share a specific tag from your collection
|
||||
|
||||
## Creating a Basic Round
|
||||
|
||||
To create a new quiz round:
|
||||
|
||||
1. From the Dashboard or Rounds page, click "Create New Round" or "Build Round"
|
||||
2. Enter an optional name for your round
|
||||
3. Select the round type by choosing one of the available cards:
|
||||
- Random Selection
|
||||
- By Decade
|
||||
- By Genre
|
||||
- By Tag (select a specific tag from the dropdown)
|
||||
4. Click the corresponding "Generate" button for your chosen round type
|
||||
5. Review the generated round with its selected songs
|
||||
6. Optionally modify the round name
|
||||
7. Click "Save This Quiz" to save your round
|
||||
|
||||
## Reviewing Generated Rounds
|
||||
|
||||
When a round is generated, you'll see:
|
||||
|
||||
1. A preview of all songs in the round
|
||||
2. Information about each song (title, artist, year, genre)
|
||||
3. Audio previews you can play to check each song
|
||||
4. Options to save the round or generate a different one
|
||||
|
||||
## Managing Saved Rounds
|
||||
|
||||
After saving a round, you can manage it from the round detail page:
|
||||
|
||||
1. Edit the round name by clicking the edit icon next to the title
|
||||
2. Add or remove songs
|
||||
3. Reorder songs by dragging and dropping them
|
||||
4. Save your changes using the "Save Changes" button
|
||||
|
||||
## Song Management
|
||||
|
||||
To modify the songs in your round:
|
||||
|
||||
1. On the round detail page, you can:
|
||||
- Remove songs by clicking the trash icon
|
||||
- Add new songs by clicking the "Add Song" button
|
||||
- Search for specific songs in the song library
|
||||
- Reorder songs using drag and drop
|
||||
2. After making changes, click "Save Changes" to update the round
|
||||
|
||||
## Export Options
|
||||
|
||||
Create different formats of your round:
|
||||
|
||||
1. **Generate MP3**: Creates an audio file with all songs, intro/outro, and announcements
|
||||
2. **Generate PDF**: Creates a printable document with the round information
|
||||
3. **Export to Dropbox**: Saves your round files to your connected Dropbox account
|
||||
4. **Send Email**: Sends the round details via email
|
||||
|
||||
## Deleting Rounds
|
||||
|
||||
To delete a round:
|
||||
|
||||
1. Navigate to the round detail page
|
||||
2. Click the "Delete Quiz" button
|
||||
3. Confirm deletion in the confirmation dialog
|
||||
4. The round and its associated files will be permanently removed
|
||||
@@ -0,0 +1,72 @@
|
||||
# Exporting Rounds
|
||||
|
||||
This guide explains the available methods for exporting your music quiz rounds from Quizzical Beats.
|
||||
|
||||
## Available Export Options
|
||||
|
||||
Quizzical Beats currently supports the following export options:
|
||||
|
||||
- **PDF**: Round document with questions, answers, and song information
|
||||
- **MP3**: Audio file with all songs concatenated for playback during your quiz
|
||||
- **JSON**: Metadata about the round and songs (exported automatically with Dropbox exports)
|
||||
|
||||
## Local Export
|
||||
|
||||
To export a round to your local device:
|
||||
|
||||
1. Navigate to the Rounds page
|
||||
2. Select the round you want to view
|
||||
3. Click the "Download MP3" or "Download PDF" button to save the respective file
|
||||
|
||||
## Dropbox Export
|
||||
|
||||
Quizzical Beats integrates with Dropbox to easily store your rounds in the cloud:
|
||||
|
||||
### Connecting to Dropbox
|
||||
|
||||
1. Go to your Profile page
|
||||
2. Find the "Connected Services" section
|
||||
3. Click "Connect Dropbox"
|
||||
4. Follow the authorization prompts from Dropbox
|
||||
5. Once connected, your Dropbox status will show as "Connected"
|
||||
|
||||
### Setting Your Dropbox Export Path
|
||||
|
||||
1. Go to your Profile page > Edit Profile
|
||||
2. Find the "Dropbox Export Path" field
|
||||
3. Enter your preferred folder path or use the default "/QuizzicalBeats"
|
||||
4. If your account is connected, you can click "Browse" to select a folder
|
||||
5. Save your changes
|
||||
|
||||
### Exporting Rounds to Dropbox
|
||||
|
||||
1. Navigate to the Rounds page
|
||||
2. Select the round you want to export
|
||||
3. Click "Export to Dropbox" button in the export options section
|
||||
4. In the export modal, choose whether to include MP3 files
|
||||
5. Click "Export Round" to send the files to your configured Dropbox folder
|
||||
|
||||
The system will create a folder structure in your Dropbox with the following format:
|
||||
```
|
||||
/[Your Export Path]/Round_[ID]_[Round Name]/
|
||||
├── round_[ID].mp3 (if MP3 option was selected)
|
||||
├── round_[ID].pdf
|
||||
└── Metadata/
|
||||
└── round_[ID]_metadata.json
|
||||
```
|
||||
|
||||
After the export completes successfully, you will see shared links to access each exported file directly.
|
||||
|
||||
## Troubleshooting Exports
|
||||
|
||||
### Failed Dropbox Export
|
||||
1. Check your Dropbox connection status in your Profile
|
||||
2. If your token has expired, reconnect your Dropbox account
|
||||
3. If the export fails because MP3 generation is required, click the provided link to generate the MP3 first
|
||||
4. Verify you have sufficient Dropbox storage space
|
||||
5. Check for any error messages displayed during the export process
|
||||
|
||||
### MP3 Export Issues
|
||||
1. Ensure all songs in the round have valid preview URLs
|
||||
2. Try regenerating the round MP3 by clicking the "Generate MP3" button on the round page
|
||||
3. If some songs lack preview URLs, you may need to edit those songs to add valid URLs
|
||||
@@ -0,0 +1,62 @@
|
||||
# Getting Started with Quizzical Beats
|
||||
|
||||
Welcome to Quizzical Beats, your ultimate music quiz round generator! This guide will help you get started with the application and create your first music quiz round.
|
||||
|
||||
## Creating Your Account
|
||||
|
||||
1. Navigate to the Quizzical Beats login page
|
||||
2. Click on "Register" to create a new account
|
||||
3. You can register using:
|
||||
- Email and password
|
||||
- Google account
|
||||
- Spotify account
|
||||
- Authentik (if enabled by your administrator)
|
||||
|
||||
## Setting Up Spotify Integration
|
||||
|
||||
To access Spotify's vast music library:
|
||||
|
||||
1. Go to your account settings
|
||||
2. Click on "Connect to Spotify"
|
||||
3. Follow the authorization prompts
|
||||
4. Once connected, you'll be able to import songs and playlists directly from Spotify
|
||||
|
||||
## Understanding Music Metadata
|
||||
|
||||
Quizzical Beats uses multiple music services to provide rich metadata for your songs:
|
||||
|
||||
1. **Spotify**: Provides song previews, album artwork, release dates, and audio features
|
||||
2. **Deezer**: Alternative source for song previews and metadata
|
||||
3. **Last.fm**: Enhances songs with genre information and music tags
|
||||
4. **ISRC Matching**: When available, uses standardized recording codes to match songs across services
|
||||
|
||||
This multi-source approach ensures your music library has comprehensive information for creating diverse quiz rounds based on genres, decades, and other musical characteristics.
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
After registering and logging in:
|
||||
|
||||
1. Visit your profile settings to customize your experience
|
||||
2. Upload custom intro/outro/replay sounds if desired
|
||||
3. Configure your email preferences for notifications
|
||||
|
||||
## Creating Your First Round
|
||||
|
||||
Once you're set up, you can create your first quiz round:
|
||||
|
||||
1. Click on "Create New Round" from the dashboard
|
||||
2. Choose a round type (random, by genre, by decade, etc.)
|
||||
3. Set the number of songs/questions
|
||||
4. Click "Generate Round"
|
||||
|
||||
## Exporting Your Round
|
||||
|
||||
After creating a round, you can export it in various formats:
|
||||
|
||||
1. PDF document with questions and answers
|
||||
2. MP3 files for playback
|
||||
3. Directly to Dropbox (if connected)
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you've created your first round, explore the [User Interface](user-interface.md) guide to learn about all the features available in Quizzical Beats.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Importing Songs
|
||||
|
||||
This guide explains the various methods for importing songs into Quizzical Beats to build your music quiz library.
|
||||
|
||||
## Music Service Integrations
|
||||
|
||||
Quizzical Beats supports importing songs from popular streaming services:
|
||||
|
||||
### Spotify Integration
|
||||
|
||||
#### Connecting Your Spotify Account
|
||||
|
||||
1. For full functionality, you'll need to connect your Spotify account
|
||||
2. Login to Quizzical Beats and authorize the Spotify connection
|
||||
3. Once connected, you can access and import songs from Spotify
|
||||
|
||||
#### Importing from Spotify
|
||||
|
||||
There are several ways to import songs from Spotify:
|
||||
|
||||
1. **Import Official Playlists**:
|
||||
- Navigate to Import > Official Playlists
|
||||
- Browse playlists from official Spotify accounts
|
||||
- Filter by keywords if needed
|
||||
- Click "Import" on the playlist you want to add
|
||||
|
||||
2. **Import Your Playlists**:
|
||||
- Navigate to Import > From Playlist
|
||||
- Enter a Spotify playlist URL or ID
|
||||
- Click "Import Playlist"
|
||||
- The songs will be added to your library
|
||||
|
||||
3. **Import Individual Albums or Tracks**:
|
||||
- Navigate to Import > Album or Import > Song
|
||||
- Enter the Spotify URL or ID of the album/track
|
||||
- Click "Import" to add the songs to your library
|
||||
|
||||
### Deezer Integration
|
||||
|
||||
Quizzical Beats also supports importing songs from Deezer:
|
||||
|
||||
1. **Import Deezer Playlists**:
|
||||
- Navigate to Import > From Playlist
|
||||
- Select "Deezer" as the platform
|
||||
- Enter a Deezer playlist URL or ID
|
||||
- Click "Import Playlist"
|
||||
|
||||
2. **Import Deezer Albums or Tracks**:
|
||||
- Navigate to Import > From Deezer
|
||||
- Choose to import an album or track
|
||||
- Enter the Deezer URL or ID
|
||||
- Click "Import" to add to your library
|
||||
|
||||
## Creating Rounds from Imported Songs
|
||||
|
||||
You can create rounds directly from imported playlists:
|
||||
|
||||
1. Navigate to Import > From Playlist
|
||||
2. Enter the playlist URL and select the platform (Spotify or Deezer)
|
||||
3. Optionally provide a name for your round
|
||||
4. Click "Import Playlist"
|
||||
5. Review the generated round
|
||||
6. Click "Save This Quiz" to create the round
|
||||
|
||||
## Viewing Imported Songs
|
||||
|
||||
After importing songs:
|
||||
|
||||
1. Go to the Songs page to see your newly imported music
|
||||
2. The songs will be displayed with available metadata including:
|
||||
- Title and artist
|
||||
- Album and year
|
||||
- Genre (when available)
|
||||
- Preview URLs
|
||||
|
||||
## Troubleshooting Import Issues
|
||||
|
||||
**Missing Audio Previews**: Some tracks may not have preview URLs available. In this case:
|
||||
- Try importing from a different source (Spotify vs. Deezer)
|
||||
- Look for an alternative version of the song
|
||||
- Some songs may not have preview URLs available from any source
|
||||
|
||||
**Duplicate Songs**: The system will automatically detect duplicates based on:
|
||||
- Spotify/Deezer IDs
|
||||
- ISRC codes when available
|
||||
|
||||
**Limited Imports**: For performance reasons, when creating rounds from playlists:
|
||||
- Only a limited number of songs (typically 8-10) will be included in a round
|
||||
- All songs are saved to your library for future use
|
||||
@@ -0,0 +1,64 @@
|
||||
# User Interface Guide
|
||||
|
||||
This guide provides an overview of the Quizzical Beats user interface to help you navigate the application efficiently.
|
||||
|
||||
## Dashboard
|
||||
|
||||
The dashboard is your main hub in Quizzical Beats, providing quick access to:
|
||||
|
||||
- **Recent Rounds**: Your most recently created quiz rounds
|
||||
- **Quick Actions**: Buttons for common tasks (Create New Round, Import Songs)
|
||||
- **System Status**: Information about your Spotify connection, Dropbox status, etc.
|
||||
|
||||
## Main Navigation
|
||||
|
||||
The main navigation menu is located at the top of the screen and includes:
|
||||
|
||||
- **Dashboard**: Return to the main dashboard
|
||||
- **Rounds**: View and manage all your quiz rounds
|
||||
- **Songs**: Browse and manage your song library
|
||||
- **Import**: Access options for importing songs from Spotify and other sources
|
||||
- **Export**: Options for exporting your quiz rounds
|
||||
- **Profile**: Access your user profile and settings
|
||||
|
||||
## Rounds Page
|
||||
|
||||
The Rounds page displays all your created quiz rounds with:
|
||||
|
||||
- **Search & Filter**: Find rounds by name, date, or type
|
||||
- **Round Cards**: Preview of each round with options to edit, play, or export
|
||||
|
||||
## Song Library
|
||||
|
||||
The Song Library provides a comprehensive view of all songs in your database:
|
||||
|
||||
- **Search**: Find songs by title, artist, album, or year
|
||||
- **Filter Panel**: Filter songs by genre, decade, tags, and more
|
||||
- **Preview**: Play song snippets directly in the browser
|
||||
|
||||
## Round Creator
|
||||
|
||||
When creating or editing a round:
|
||||
|
||||
- **Round Properties**: Set name and round criteria
|
||||
- **Song Selection**: Add songs manually or use the auto-generator
|
||||
- **Arrangement**: Reorder songs in your round
|
||||
- **Preview**: Test your round with the built-in player
|
||||
|
||||
## Settings Area
|
||||
|
||||
The account settings area allows you to:
|
||||
|
||||
- **Profile**: Update your user information
|
||||
- **Password**: Change your password
|
||||
- **OAuth Connections**: Manage connections to Spotify, Dropbox, and other services
|
||||
- **Audio Settings**: Configure custom intro, outro, and replay sounds
|
||||
|
||||
## Admin Settings
|
||||
|
||||
For administrators, additional settings include:
|
||||
|
||||
- **System Settings**: Configure global application settings
|
||||
- **User Management**: Manage user accounts
|
||||
- **System Health**: Monitor application status
|
||||
- **Backup & Restore**: Manage database backups
|
||||
Reference in New Issue
Block a user