### Initial Project Setup and Dependency Installation Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Setup Clone the repository, set up a Python virtual environment, activate it, and install all necessary project dependencies for testing. ```bash # 1. Clone the repository git clone https://github.com/crocodilestick/Calibre-Web-Automated.git cd Calibre-Web-Automated # 2. Create virtual environment python3 -m venv .venv # 3. Activate virtual environment source .venv/bin/activate # Linux/Mac # OR .venv\Scripts\activate # Windows # 4. Install dependencies pip install -r requirements.txt pip install pytest pytest-timeout pytest-flask pytest-mock faker testcontainers # 5. You're ready to test! ./run_tests.sh ``` -------------------------------- ### Example Migration Log Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Thumbnail-System-Migration This log shows the typical output during the thumbnail migration process on startup for existing installations. ```log INFO: Thumbnail migration: Found 158 old subdirectories, starting migration INFO: Thumbnail migration: Cleared 255 old database entries INFO: Thumbnail migration: Removed 255 old files and 158 subdirectories INFO: Thumbnail migration: Complete. Thumbnails will be regenerated automatically as needed. ``` -------------------------------- ### OpenLDAP Configuration Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/LDAP-Authentication Example configuration parameters for connecting to an OpenLDAP server. Ensure these match your LDAP server's setup. ```text LDAP Server: ldap://openldap.company.com:389 LDAP Encryption: None (or TLS for security) LDAP Base DN: ou=people,dc=company,dc=org LDAP User Object Filter: (&(objectClass=inetOrgPerson)(uid=%s)) LDAP Authentication: Simple Bind Auto-create users from LDAP: ✅ Enabled ``` -------------------------------- ### Manifest File Format Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Enhanced-Ingest-System Example of a manifest file used to provide advanced processing instructions for books. ```json { "action": "add_format", "book_id": 123, "original_filename": "my-book.epub" } ``` -------------------------------- ### Using Fixtures for Test Setup Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Guide-for-Contributors Example of a test function utilizing the 'temp_cwa_db' fixture for automatic temporary database setup and cleanup. ```python def test_with_database(temp_cwa_db): """The temp_cwa_db fixture is automatically available.""" # Test uses temporary database that's cleaned up automatically temp_cwa_db.insert_import_log(1, "Test Book", "EPUB", "/path") assert temp_cwa_db.get_total_imports() == 1 ``` -------------------------------- ### Install Pytest Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Installs the pytest testing framework. This is a minimal installation for troubleshooting 'pytest: command not found' errors. ```bash pip install pytest ``` -------------------------------- ### FreeIPA Configuration Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/LDAP-Authentication Example configuration parameters for connecting to a FreeIPA server. TLS encryption is recommended for security. ```text LDAP Server: ldap://ipa.company.com:389 LDAP Encryption: TLS (recommended) LDAP Base DN: cn=users,cn=accounts,dc=company,dc=com LDAP User Object Filter: (&(objectClass=person)(uid=%s)) LDAP Authentication: Simple Bind Auto-create users from LDAP: ✅ Enabled ``` -------------------------------- ### Install Docker and Check Version Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Building-Custom-Docker-Images Ensure Docker is installed and running on your system by checking its version. This is a prerequisite for building Docker images. ```bash # Check if Docker is installed docker --version ``` -------------------------------- ### SQL Key Fields Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Kobo-Integration-&-Sync Shows example SQL fields relevant to Kobo sync configuration and tracking, including user settings for shelf-only sync, shelf marking for sync, and active sync relationships. ```sql -- User configuration users.kobo_only_shelves_sync -- Enable shelf-only sync mode -- Shelf configuration shelf.kobo_sync -- Mark shelf for Kobo sync -- Sync tracking kobo_synced_books.user_id, book_id -- Active sync relationships ``` -------------------------------- ### Start Docker Container Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Guide-for-Contributors Initiate the Docker container for the calibre-web-automated project. ```bash # Start container docker compose up -d ``` -------------------------------- ### Install Pytest Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Running-Tests Installs pytest if the command is not found. Alternatively, install all development dependencies. ```bash pip install pytest ``` ```bash pip install -r requirements-dev.txt ``` -------------------------------- ### Check Docker Installation Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Verify that Docker is installed and accessible from your terminal. ```bash docker --version ``` -------------------------------- ### Quick Setup: Auto-Discovery Configuration Source: https://github.com/crocodilestick/calibre-web-automated/wiki/OAuth-Configuration Enter these details in CWA's OAuth settings for easy setup using a metadata URL. Test the connection before saving. ```text Metadata URL: [paste your metadata URL here] OAuth Client ID: [your client ID] OAuth Client Secret: [your client secret] ``` -------------------------------- ### Start Docker Daemon (Linux) Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Building-Custom-Docker-Images If Docker is not running, use this command to start the Docker daemon on Linux systems. Ensure you have the necessary permissions. ```bash # Start Docker daemon (Linux) sudo systemctl start docker ``` -------------------------------- ### Start Service with docker-compose.yml.dev Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Building-Custom-Docker-Images Use this command to start your Calibre-Web Automated service using the specified development docker-compose file, ensuring it runs with your custom image. ```bash docker compose -f docker-compose.yml.dev up -d ``` -------------------------------- ### Generate Test Fixtures Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/tests/README.md Downloads public domain ebooks and creates synthetic test files. This is a one-time setup step. ```bash cd tests/fixtures python download_gutenberg.py # Download public domain ebooks (~5MB) python generate_synthetic.py # Create synthetic test files cd ../.. ``` -------------------------------- ### Install Test Dependencies Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Overview Installs development dependencies for testing using pip. Ensure you have Python 3.10+ and a bash shell. ```bash pip install -r requirements-dev.txt ``` ```bash pip install pytest pytest-timeout pytest-flask pytest-mock faker testcontainers requests ``` -------------------------------- ### Start Calibre-Web Automated with Docker Compose Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/README.md Use this command to start the Calibre-Web Automated service in detached mode using a development Docker Compose file. Ensure `docker-compose.yml.dev` is correctly configured. ```bash $ docker compose -f docker-compose.yml.dev up -d ``` -------------------------------- ### OPDS Authentication Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/LDAP-Authentication Example of how to authenticate with OPDS feeds using LDAP credentials. Replace placeholders with your actual details. ```text URL: https://your-cwa.com/opds Username: [LDAP username] Password: [LDAP password] ``` -------------------------------- ### Extend with New Sync Protocol (Python) Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/cps/progress_syncing/README.md Example of how to create a new sync protocol by defining a Flask Blueprint and registering it with the application. It demonstrates using 'get_book_by_checksum' to identify books. ```python # protocols/new_protocol.py from flask import Blueprint, request from .kosync import get_book_by_checksum new_protocol = Blueprint('new_protocol', __name__) @new_protocol.route('/new_protocol/sync', methods=['PUT']) def sync(): checksum = request.json['document'] book_id, format, title, path, version = get_book_by_checksum(checksum) # Implement sync logic # Register in cps/main.py: from .progress_syncing.protocols.new_protocol import new_protocol app.register_blueprint(new_protocol) ``` -------------------------------- ### OPDS Catalog API - LDAP/Reverse-Proxy Auth Example Source: https://context7.com/crocodilestick/calibre-web-automated/llms.txt Demonstrates authentication using credentials for LDAP or reverse-proxy users. Requires HTTP Basic Auth. ```bash BASE="http://localhost:8083" curl -u "ldap-user:ldap-password" "$BASE/opds/new" ``` -------------------------------- ### Check Python Version Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Verify that Python 3.10 or higher is installed. Python 3.13 is recommended. ```bash python3 --version ``` -------------------------------- ### Example Test Function with Fixtures Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/tests/README.md Demonstrates how to use fixtures like `temp_cwa_db` and `sample_book_data` within a test function. These fixtures are automatically provided by `conftest.py`. ```python def test_something(temp_cwa_db, sample_book_data): # temp_cwa_db and sample_book_data are automatically available pass ``` -------------------------------- ### Verify Dependencies and Docker Access Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Building-Custom-Docker-Images Check if bash, git, and docker are installed and accessible. Ensure the Docker daemon is running and the user has the necessary permissions. ```bash bash --version git --version docker --version docker info ``` -------------------------------- ### Run Unit Tests (Manual) Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Execute unit tests from the command line. This suite takes approximately 2 minutes to run. ```bash pytest tests/unit/ -v ``` -------------------------------- ### Install Pytest Watch Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Installs the pytest-watch plugin, which automatically re-runs tests when source files change. ```bash pip install pytest-watch ``` -------------------------------- ### Run All Tests (Manual) Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Execute the entire test suite from the command line. This comprehensive run takes approximately 5-7 minutes. ```bash pytest tests/ -v ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Installs necessary packages for development and testing, including pytest, pytest-flask, pytest-timeout, pytest-mock, and faker. ```bash pip install -r requirements-dev.txt ``` -------------------------------- ### Production Build with Custom Options Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Building-Custom-Docker-Images Build a production-ready image with a clean version tag and a specified output directory. Use this for stable releases and deployments. ```bash ./build.sh -u myuser -v v3.1.5 -d ~/builds # Creates: myuser/calibre-web-automated:v3.1.5 # Version: v3.1.5 ``` -------------------------------- ### Download Sample Books with Python Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/tests/fixtures/README.md Execute this Python script to download public domain books in various formats for testing purposes. Ensure you are in the 'tests/fixtures' directory before running. ```bash cd tests/fixtures python download_gutenberg.py ``` -------------------------------- ### Quick Dev Build with Defaults Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Building-Custom-Docker-Images Use this command for a quick development build, accepting most defaults. The script will prompt for your Docker Hub username if it's not already configured. ```bash ./build.sh -l -v v3.2.0-test -r 1 ``` -------------------------------- ### Update Python Version with pyenv Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Setup If a specific Python version is required and not installed, use pyenv to install and set the local version. ```bash pyenv install 3.12.3 pyenv local 3.12.3 ``` -------------------------------- ### Create Unit Test File Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Guide-for-Contributors Use the 'touch' command to create a new Python file for your unit test, following the specified naming convention. ```bash # Unit test example touch tests/unit/test_my_feature.py ``` -------------------------------- ### Auto-Metadata Fetch Field Selection Example Source: https://context7.com/crocodilestick/calibre-web-automated/llms.txt Customize which metadata fields are updated by the auto-fetch system, shown with examples for academic and comic libraries. ```text # Academic library field selection example (preserve manual cataloging): ☑ Authors ☑ Publisher ☑ Identifiers ☑ Publication Date ☐ Title ☐ Description ☐ Tags ☐ Rating ☐ Cover # Comic collection example: ☑ Series ☑ Cover ☑ Tags ☑ Rating ☐ Title ☐ Authors ☐ Description ☐ Publisher ``` -------------------------------- ### API Authentication Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/LDAP-Authentication Example using curl to authenticate with API endpoints using LDAP credentials. The -u flag is used for basic authentication. ```bash curl -u "ldap-user:ldap-password" https://your-cwa.com/api/v1/books ``` -------------------------------- ### Run Integration Tests (Manual) Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Quick-Start Execute integration tests from the command line. This suite takes approximately 3-4 minutes to run. ```bash pytest tests/integration/ -v ``` -------------------------------- ### Unit and Integration Tests (Bash) Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/cps/progress_syncing/README.md Commands to run unit tests for the algorithm, storage, and database, as well as integration tests for the full sync workflow and the KOSync protocol. ```bash # Unit tests - Algorithm, storage, database pytest tests/unit/test_progress_syncing_*.py -v # Integration tests - Full sync workflow pytest tests/integration/test_progress_syncing_*.py -v pytest tests/integration/test_kosync_*.py -v ``` -------------------------------- ### Configure OAuth 2.0 / OIDC Authentication (Quick Setup) Source: https://context7.com/crocodilestick/calibre-web-automated/llms.txt Configure OAuth 2.0/OIDC authentication in the admin panel using the Metadata URL for auto-discovery. This is the recommended approach for integrating with compliant identity providers. ```text # Admin → Basic Configuration → OAuth Settings # Quick setup (auto-discovery, recommended): Metadata URL: https://auth.example.com/realms/myrealm/.well-known/openid-configuration Client ID: calibre-web-automated Client Secret: OAuth Scopes: openid profile email groups Username Field: preferred_username (or: sub, email, username) Email Field: email Admin Group: admins (JWT "groups" claim value → auto-grants admin) OAuth Redirect Host: https://cwa.example.com # Required behind reverse proxies # Provider-specific redirect URI to register in your OAuth provider: # Generic / Keycloak / Authentik: https://cwa.example.com/login/generic/authorized # GitHub: https://cwa.example.com/login/github/authorized # Google: https://cwa.example.com/login/google/authorized ``` -------------------------------- ### Initialize Charts and Warnings Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/cps/templates/cwa_user_activity.html Sets up event listeners and initial states when the DOM is loaded. Includes logic to display a warning if a 'show_warning' flag is set in the template. ```javascript document.addEventListener('DOMContentLoaded', function() { // Show warning if present {% if show_warning %} document.getElementById('date-warning').style.display = 'block'; {% endif %} initCharts(); }); ``` -------------------------------- ### Get Convert Library Status Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/cps/templates/cwa_convert_library.html Periodically fetches the status of the Convert Library service using a GET request. Updates the displayed status text and progress bar based on the response. Terminates polling if the process ends or is cancelled. ```javascript async function getStatus() { let get; try { const res = await fetch("{{ url_for('convert_library.get_status')}}"); get = await res.json(); } catch (e) { console.error("Error: ", e); } // Check if get.status is a non-empty string if (get.status && get.status.trim() !== "") { document.getElementById("innerStatus").innerHTML = get.status.replace(/\n/g, "
"); } if (get.progress) { const { current, total } = get.progress; if (total > 0) { const percentage = Math.round((current / total) * 100); const progressBar = document.getElementById("progress-bar"); progressBar.style.width = percentage + "%" ; progressBar.textContent = percentage + "%" ; } } if (get.status.includes("CONVERT LIBRARY PROCESS TERMINATED BY USER")){ // Add finished log document.getElementById("innerStatus").innerHTML; // Check if run was cancelled, make progress bar red if so const progressBar = document.getElementById("progress-bar"); progressBar.style.backgroundColor = "#D22B2B"; // Cadmium Red // End script clearTimeout(timeout); return false; } if (get.status.includes("CWA Convert Library Service - Run Ended:")){ // Add finished log document.getElementById("innerStatus").innerHTML; // Set the progress bar to 100% const percentage = 100; const progressBar = document.getElementById("progress-bar"); progressBar.style.width = percentage + "%" ; progressBar.textContent = percentage + "%" ; // End script clearTimeout(timeout); return false; } timeout = setTimeout(getStatus, 1000); } getStatus(); ``` -------------------------------- ### Run Full Test Suite Before Creating PR Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/tests/TEST_OPTIMIZATION.md Execute smoke and unit tests in parallel, followed by integration tests sequentially with shortened traceback output. ```bash pytest tests/smoke/ tests/unit/ -n auto pytest tests/integration/ -v --tb=short ``` -------------------------------- ### Get Book Cover Source: https://context7.com/crocodilestick/calibre-web-automated/llms.txt Retrieves the cover image for a specific book. An optional resolution can be specified. ```APIDOC ## Get book cover ### Description Retrieves the cover image for a specific book. An optional resolution can be specified. ### Method GET ### Endpoint /cover/[/] ### Parameters #### Path Parameters - **book_id** (integer) - Required - The ID of the book whose cover to retrieve. - **resolution** (string) - Optional - The desired resolution of the cover image. Options: 'og' (original), 'sm' (small thumbnail), or default (web-optimised). ### Request Example ```bash curl -u admin:admin123 -o cover.jpg "http://localhost:8083/cover/42" curl -u admin:admin123 -o cover_small.jpg "http://localhost:8083/cover/42/sm" ``` ``` -------------------------------- ### Add New Format to Existing Book (Manifest) Source: https://context7.com/crocodilestick/calibre-web-automated/llms.txt Creates a manifest file and copies a new book format for ingestion. This is typically handled by the web UI but can be scripted. ```bash cat > /opt/cwa/ingest/20250101_120000_000000_my-book.cwa.json <<'EOF' { "action": "add_format", "book_id": 123, "original_filename": "my-book.epub" } EOF ``` ```bash cp ~/Downloads/my-book.epub /opt/cwa/ingest/20250101_120000_000000_my-book.epub ``` -------------------------------- ### Helper Function: Database Access Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Docker-in-Docker-Mode A helper function to get a database path that works in both standard and Docker-in-Docker modes. ```python # Database access (works in both modes) from tests.conftest import get_db_path db_path = get_db_path(folder_fixture, "cwa.db") conn = sqlite3.connect(db_path) ``` -------------------------------- ### Docker Tests for Container Startup Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Implementation-Status Details the tests for container startup and health, covering aspects like accessibility, environment variables, and service status. ```text ✅ TestContainerHealth (9 tests) - test_container_starts_successfully - test_web_server_is_accessible - test_health_check_passes - test_environment_variables_loaded - test_port_binding_correct - test_volume_mounts_working - test_api_endpoints_respond - test_services_running - test_logs_show_startup ``` -------------------------------- ### Timeout Control for Tests Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Running-Tests Set a timeout for tests to prevent hanging. This example sets a 5-second timeout per test. ```bash pytest tests/ --timeout=5 ``` -------------------------------- ### Sample Book Fixtures for Testing Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Implementation-Status This structure outlines the required sample book files for various testing scenarios, including valid formats, corrupted files, edge cases, and metadata variations. Files marked with '✅ Created' are complete, while '❌ Needed' indicate missing fixtures. ```tree tests/fixtures/sample_books/ ├── valid/ │ ├── sample.epub ✅ Created │ ├── sample.mobi ❌ Needed │ ├── sample.azw3 ❌ Needed │ ├── sample.pdf ❌ Needed │ ├── sample.txt ✅ Created │ └── (25+ more formats) ├── corrupted/ │ ├── broken.epub ✅ Created │ ├── invalid.mobi ❌ Needed │ └── malformed.pdf ❌ Needed ├── edge_cases/ │ ├── huge.epub ❌ Needed (100MB+) │ ├── unicode_名前.epub ✅ Created │ └── no_metadata.epub ✅ Created └── metadata/ ├── complete.epub ✅ Created └── minimal.epub ✅ Created ``` -------------------------------- ### OAuth Provider Metadata URLs Source: https://github.com/crocodilestick/calibre-web-automated/wiki/OAuth-Configuration Examples of metadata URLs for common OAuth providers. Use these for auto-discovery configuration in CWA. ```text https://your-keycloak.com/realms/your-realm/.well-known/openid-configuration ``` ```text https://your-authentik.com/application/o/your-app/.well-known/openid-configuration ``` ```text https://accounts.google.com/.well-known/openid-configuration ``` ```text https://login.microsoftonline.com/your-tenant/.well-known/openid-configuration ``` -------------------------------- ### Get Duplicate Status Source: https://context7.com/crocodilestick/calibre-web-automated/llms.txt Retrieves the current status of the duplicate detection system, including any active scans or recent activity. ```APIDOC ## GET /duplicates/status ### Description Retrieves the current operational status of the smart duplicate detection engine. ### Method GET ### Endpoint /duplicates/status ### Response #### Success Response (200) - (Response body structure not specified, but would typically include information about active scans, cache status, etc.) ``` -------------------------------- ### Initialize and Render OPDS Order List Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/cps/templates/user_edit.html Sets up the OPDS order list by parsing raw order strings, building the order based on labels, and rendering the list items. It also handles the visibility toggles for OPDS entries. ```javascript document.addEventListener('DOMContentLoaded', function() { const opdsLabels = {{ opds_root_labels | tojson }}; const opdsOrderRaw = "{{ opds_root_order_string }}"; const opdsHiddenRaw = "{{ opds_hidden_entries_string }}"; const magicShelfLabels = {{ magic_shelf_order_labels | tojson }}; const magicShelfOrderRaw = "{{ magic_shelf_order_string }}"; const magicShelfOrderMode = "{{ magic_shelf_order_mode }}"; function parseOrder(raw) { if (!raw) return []; return raw.split(',').map(item => item.trim()).filter(Boolean); } function buildOrderList(labels, order) { const labelMap = new Map(labels.map(item => [item.key, item.label])); const seen = new Set(); const result = []; order.forEach(key => { if (labelMap.has(key) && !seen.has(key)) { result.push(key); seen.add(key); } }); labels.forEach(item => { if (!seen.has(item.key)) { result.push(item.key); seen.add(item.key); } }); return result; } function renderOpdsOrderList() { const container = document.getElementById('opds_root_order_list'); if (!container) return; const order = buildOrderList(opdsLabels, parseOrder(opdsOrderRaw)); container.innerHTML = ''; const hiddenSet = new Set(parseOrder(opdsHiddenRaw)); order.forEach(key => { const label = opdsLabels.find(item => item.key === key)?.label || key; const isHidden = hiddenSet.has(key); const li = document.createElement('li'); li.className = 'opds-order-item'; li.dataset.key = key; li.innerHTML = ` ${label} `; container.appendChild(li); }); setupOpdsDragDrop(); updateOpdsHiddenInput(); } function setupOpdsDragDrop() { let dragged = null; let isDragging = false; const items = document.querySelectorAll('.opds-order-item'); items.forEach(item => { item.addEventListener('mousedown', function(e) { isDragging = true; dragged = this; this.classList.add('dragging'); document.body.style.userSelect = 'none'; e.preventDefault(); }); }); document.addEventListener('mousemove', function(e) { if (!isDragging || !dragged) return; const container = document.getElementById('opds_root_order_list'); const afterElement = getOpdsAfterElement(container, e.clientY); if (afterElement == null) { container.appendChild(dragged); } else { container.insertBefore(dragged, afterElement); } }); document.addEventListener('mouseup', function() { if (!isDragging) return; isDragging = false; if (dragged) { dragged.classList.remove('dragging'); dragged = null; } document.body.style.userSelect = ''; updateOpdsHiddenInput(); }); } function getOpdsAfterElement(container, y) { const draggableElements = [...container.querySelectorAll('.opds-order-item:not(.dragging)')]; return draggableElements.reduce((closest, child) => { const box = child.getBoundingClientRect(); const offset = y - box.top - box.height / 2; if (offset < 0 && offset > closest.offset) { return { offset: offset, element: child }; } return closest; }, { offset: Number.NEGATIVE_INFINITY }).element; } function updateOpdsHiddenInput() { const container = document.getElementById('opds_root_order_list'); const hiddenInput = document.getElementById('opds_root_order'); const hiddenEntriesInput = document.getElementById('opds_hidden_entries'); if (!container || !hiddenInput) return; const items = container.querySelectorAll('.opds-order-item'); const order = Array.from(items).map(item => item.dataset.key); hiddenInput.value = order.join(','); if (!hiddenEntriesInput) return; const hidden = []; container.querySelectorAll('.opds-order-visible').forEach(checkbox => { if (!checkbox.checked) { hidden.push(checkbox.dataset.key); } }); hiddenEntriesInput.value = hidden.join(','); } function renderMagicShelfOrderList() { const container = document.getElementById('magic_shelf_order_list'); if (!container) return; const order = buildOrderList(magicShelfLabels, parseOrder(magicShelfOrderRaw)); container.innerHTML = ''; order.forEach(key => { const item = magicShelfLabels.find(entry => entry.key === key); const label = item?.label || key; const icon = item?.icon || '📚'; const li = document.createElement('li'); li.className = 'opds-order-item magic-shelf-order-item'; li.dataset.key = key; li.innerHTML = ` ${icon} ${label} `; container.appendChild(li); }); setupMagicShelfDragDrop(); updateMagicShelfHiddenInput(); updateMagicShelfOrderModeState(); } function setupMagicShelfDragDrop() { let dragged = null; let isDragging = false; const items = document.querySelectorAll('.magic-shelf-order-item'); items.forEach(item => { item.addEventListener('mousedown', function(e) { const orderMode = document.getElementById('magic_shelf_order_mode')?.value; if ``` -------------------------------- ### Optimize SQLite Database Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Stats-Activity-Dashboard Run this command to optimize the SQLite database file, which is recommended for installations with a large number of activity records. ```bash sqlite3 /config/cwa.db "VACUUM;" ``` -------------------------------- ### Run Single Smoke Test Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Guide-for-Contributors Executes a specific smoke test using pytest. This is useful for verifying installation and basic functionality. ```bash pytest tests/smoke/test_smoke.py::test_smoke_suite_itself -v ``` -------------------------------- ### Network Architecture Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Reverse-Proxy-Authentication Illustrates a secure network flow where traffic passes through an authenticated reverse proxy before reaching the internal application. ```text Internet → Reverse Proxy (Auth) → Internal Network → CWA ↑ ↑ (Public) (Private) ``` -------------------------------- ### Configure Discovery Source Chart Source: https://github.com/crocodilestick/calibre-web-automated/blob/main/cps/templates/cwa_user_activity.html Sets up a pie chart to display the distribution of discovery sources. Handles cases with no data by displaying a 'No discovery data yet' message. Uses a mapping for source labels and customizes chart appearance. ```javascript t() { const data = currentData.discoverySources || []; if (data.length === 0) { discoveryChart.setOption({ title: { text: 'No discovery data yet', left: 'center', top: 'center', textStyle: { color: '#999', fontSize: 14 } } }, true); return; } const sourceLabels = { 'search': 'Search', 'book_detail': 'Book Detail', 'series': 'Series Page', 'author': 'Author Page', 'browse': 'Browse', 'shelf': 'Shelf', 'category': 'Category', 'direct': 'Direct Link' }; const option = { tooltip: { trigger: 'item', backgroundColor: 'rgba(0,0,0,0.8)', textStyle: { color: '#fff' }, formatter: '{b}: {c} ({d}%)' }, legend: { orient: 'horizontal', bottom: '5%', textStyle: { color: '#fff' } }, series: [{ type: 'pie', radius: ['40%', '70%'], center: ['50%', '40%'], data: data.map(([source, count]) => ({ name: sourceLabels[source] || source, value: count })), emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(255, 152, 0, 0.5)' } }, itemStyle: { borderRadius: 8, borderColor: '#1a2332', borderWidth: 2 }, label: { color: '#fff', formatter: '{b}\n{d}%' } }] }; discoveryChart.setOption(option, true); } ``` -------------------------------- ### Create a Custom Pytest Fixture Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Testing-Guide-for-Contributors Define a custom pytest fixture in conftest.py that provides setup and cleanup logic for test data. ```python @pytest.fixture def my_custom_fixture(): """Provide custom test data.""" # Setup data = create_test_data() yield data # Cleanup (optional) cleanup_test_data(data) ``` -------------------------------- ### SQL Foreign Key Constraint Example Source: https://github.com/crocodilestick/calibre-web-automated/wiki/Kobo-Integration-&-Sync Illustrates the SQL syntax for adding ON DELETE CASCADE to foreign key constraints, which is necessary to resolve deletion errors when interacting with Calibre Desktop. ```sql -- Add ON DELETE CASCADE to foreign key constraints -- Example: FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ```