### Example: Setting Autocaliweb Installation Directory
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Use this example to set a custom installation directory for Autocaliweb's core application files during a manual installation.
```bash
export ACW_INSTALL_DIR="/usr/local/autocaliweb"
```
--------------------------------
### Example: Setting Ingest Directory
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Use this example to specify the directory where new books will be placed for processing by the manual installation script.
```bash
export INGEST_DIR="/mnt/storage/NewBooks"
```
--------------------------------
### Example: Setting Autocaliweb Configuration Directory
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Use this example to specify a custom directory for Autocaliweb's configuration files, databases, and logs during a manual installation.
```bash
export ACW_CONFIG_DIR="/etc/autocaliweb"
```
--------------------------------
### Example: Setting Autocaliweb User
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Use this example to define the user account under which Autocaliweb services will run and own files during a manual installation.
```bash
export ACW_USER="autocali"
```
--------------------------------
### Run Autocaliweb Installation Script
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Manual-Installation
Navigate to the cloned directory and execute the manual installation script. This script handles dependency installation, environment setup, and service configuration.
```bash
cd /app/autocaliweb
chmod +x scripts/manual_install_acw.sh
./scripts/manual_install_acw.sh
```
--------------------------------
### Example: Setting Calibre Library Directory
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
This example shows how to set the root directory for your Calibre library, where books and metadata are stored. It can be used for manual installs or via command-line.
```bash
export LIBRARY_DIR="/mnt/books/MyCalibreLibrary"
```
--------------------------------
### Configuration Priority: Command-line Argument Example
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Illustrates the highest priority configuration source: command-line arguments. This example shows overriding the installation directory directly when running the script.
```bash
manual_install_acw.sh --install-dir "/home/youruser/apps/autocaliweb"
```
--------------------------------
### Example: Setting Autocaliweb Group
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Use this example to set the primary group for Autocaliweb services and file ownership during a manual installation.
```bash
export ACW_GROUP="acwusers"
```
--------------------------------
### Configuration Priority: Environment Variable Example
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
Demonstrates how setting an environment variable like ACW_INSTALL_DIR before running the manual install script will override the script's default installation directory.
```bash
export ACW_INSTALL_DIR="/usr/local/autocaliweb"; manual_install_acw.sh
```
--------------------------------
### Execute Manual Installation Script
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Make the downloaded script executable and run it as root to perform the manual installation of Autocaliweb. Follow the on-screen prompts.
```bash
sudo chmod +x ./manual_install_acw.sh && sudo ./manual_install_acw.sh
```
--------------------------------
### Manually Start Autocaliweb
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Manual-Installation
Manually start Autocaliweb by executing its start script. This method is an alternative to using systemd.
```bash
/app/autocaliweb/start_autocaliweb.sh
```
--------------------------------
### Download Manual Installation Script
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Download the manual installation script for Autocaliweb. It is recommended to check the script's content before execution.
```bash
curl -Lo ./manual_install_acw.sh https://github.com/gelbphoenix/autocaliweb/raw/refs/heads/main/scripts/manual_install_acw.sh
```
--------------------------------
### Autocaliweb Manual Installation Environment Variables
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Configuration
These variables are for manual installations to customize installation paths, directories, and user/group ownership. They take precedence over script defaults.
```bash
ACW_INSTALL_DIR=
ACW_CONFIG_DIR=
ACW_USER=
ACW_GROUP=
INGEST_DIR=
```
--------------------------------
### Install Autocaliweb via Proxmox VE Helper-Script (Gitea)
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
This command installs Autocaliweb on Proxmox VE using the community-maintained Helper-Scripts. Use this link if the GitHub source is unavailable or as directed.
```bash
bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/ct/autocaliweb.sh)"
```
--------------------------------
### Install Autocaliweb via Proxmox VE Helper-Script (GitHub)
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
This command installs Autocaliweb on Proxmox VE using the community-maintained Helper-Scripts. It fetches the script directly from GitHub.
```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/autocaliweb.sh)"
```
--------------------------------
### Start Autocaliweb with Docker Compose
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Navigate to the directory containing your docker-compose.yml file and run this command to start Autocaliweb in detached mode.
```bash
docker compose up -d
```
--------------------------------
### Start Autocaliweb Service using Systemd
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Manual-Installation
Start and check the status of the Autocaliweb service using systemctl. This is the recommended method for managing the application's lifecycle.
```bash
sudo systemctl start autocaliweb
sudo systemctl status autocaliweb
```
--------------------------------
### Install JavaScript Dev Dependencies
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Installs the necessary development dependencies for JavaScript linting and other tools. Run this command in the project's root directory.
```bash
npm install
```
--------------------------------
### JavaScript for Library Refresh
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/layout.html
Handles asynchronous fetching and display of library refresh status messages. Includes functions to start, stop, and update the refresh status.
```javascript
let checkMessagesInterval = null; // Store interval ID
function refreshLibrary() {
fetch("/acw-library-refresh", { method: "POST", headers: { "Content-Type": "application/json" } })
.then(response => response.json())
.then(data => {
updateLibraryRefreshMessage(data.message); // Show immediate confirmation
startCheckingMessages(); // Start checking for messages
})
.catch(error => console.error("Error:", error));
}
function checkLibraryMessages() {
fetch("/acw-library-refresh/messages")
.then(response => response.json())
.then(data => {
if (data.messages.length > 0) {
updateLibraryRefreshMessage(data.messages.join("
")); // Show messages
stopCheckingMessages(); // Stop checking once we get a message
}
})
.catch(error => console.error("Error fetching messages:", error));
}
function startCheckingMessages() {
if (!checkMessagesInterval) { // Prevent multiple intervals
checkMessagesInterval = setInterval(checkLibraryMessages, 500);
}
}
function stopCheckingMessages() {
if (checkMessagesInterval) {
clearInterval(checkMessagesInterval);
checkMessagesInterval = null;
}
}
function updateLibraryRefreshMessage(message) {
const messageDiv = document.getElementById("message_library_refresh");
const messagePara = document.getElementById("library_refresh_message")
if (messageDiv) {
messagePara.innerHTML = message; // Set the message inside the div
messageDiv.style.display = "inline-flex"; // Make sure it's visible
}
}
function dismissLibraryRefreshMessage() {
const messageDiv = document.getElementById("message_library_refresh");
const messagePara = document.getElementById("library_refresh_message")
if (messageDiv) {
messagePara.innerHTML = ""; // Set the message inside the div
messageDiv.style.display = "none"; // Make sure it's visible
}
}
```
--------------------------------
### Uninstall Autocaliweb
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Manual-Installation
Navigate to the installation directory and execute the uninstallation script to remove Autocaliweb. Ensure you have the necessary permissions.
```bash
cd /app/autocaliweb
chmod +x scripts/Uninstall_acw.sh
./scripts/Uninstall_acw.sh
```
--------------------------------
### Autocaliweb OIDC Provider Settings
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Single-Sign-On-and-OpenID-Connect
Configuration parameters within Autocaliweb to establish the connection with the VoidAuth OIDC provider. Ensure these match the VoidAuth client setup.
```text
generic OAuth Client Id: your-client-id
generic OAuth Client Secret: your-client-secret
generic OAuth scope: openid profile email
generic OAuth Metadata URL: Copy from OIDC Info in VoidAuth (Well-Known Endpoint)
generic OAuth Username mapper: preferred_username
generic OAuth Email mapper: email
generic OAuth Login Button: VoidAuth
```
--------------------------------
### SoundManager Setup for HTML5 Audio
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/listenmp3.html
Configures SoundManager to use HTML5 Audio, disabling Flash fallback. This snippet is essential for enabling audio playback in modern browsers.
```javascript
soundManager.setup({
useHTML5Audio: true,
preferFlash: false,
url: "/path/to/swf-files/",
onready: function () {
var mySound = soundManager.createSound({
// id: 'aSound',
// url: "{{ url_for('web.serve_book', book_id=mp3file,book_format=audioformat)}}"
});
mySound.play();
},
ontimeout: function () {
// Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?
},
});
```
--------------------------------
### Initialize Custom Theme UI and Pickr
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Sets up the custom theme UI, including the color swatch and potentially a color picker (Pickr). It retrieves saved theme colors and applies them, also determining text color contrast.
```javascript
(function () { var swatch = document.getElementById("customThemeSwatch"); var saved = window.themes && window.themes.customTheme && window.themes.customTheme.bgColor ? window.themes.customTheme.bgColor : "#ffffff"; if (swatch) swatch.style.background = saved; function _hexToRgb(hex) { hex = hex.replace("#", ""); if (hex.length === 3) { hex = hex .split("") .map(function (h) { return h + h; }) .join(""); } var bigint = parseInt(hex, 16); return { r: (bigint >> 16) & 255, g: (bigint >> 8) & 255, b: bigint & 255, }; } // Better contrast decision using WCAG relative luminance and contrast ratio // Returns true if black text is the better choice (i.e. background is light) function _isLight(hex) { try { var rgb = _hexToRgb(hex); // convert 0-255 to 0-1 var srgb = { r: rgb.r / 255, g: rgb.g / 255, b: rgb.b / 255 }; function lin(c) { return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); } var R = lin(srgb.r), G = lin(srgb.g), B = lin(srgb.b); var L = 0.2126 * R + 0.7152 * G + 0.0722 * B; // relative luminance // contrast ratios against black (L=0) and white (L=1) var contrastWithBlack = (L + 0.05) / (0.0 + 0.05); var contrastWithWhite = (1.0 + 0.05) / (L + 0.05); // pick the text color that gives higher contrast.
```
--------------------------------
### Initialize Color Picker and Theme
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Initializes the Pickr color picker component if available, allowing users to select a custom theme color. It applies the selected color immediately and also responds to the save action.
```javascript
function ensurePickrAndInit() {
if (window.Pickr) {
try {
var pickr = Pickr.create({
el: "#customThemeSwatch",
theme: "classic",
default: saved,
components: {
preview: true,
opacity: false,
hue: true,
interaction: {
hex: true,
input: true,
save: true,
},
},
});
// Immediate apply when color changes in the picker
pickr.on("change", function (color, instance) {
try {
var hex = color.toHEXA().toString();
if (swatch) swatch.style.background = hex;
applyCustomColor(hex);
} catch (e) {}
});
// Also respond to save (some pickr configs use save)
pickr.on("save", function (color, instance) {
try {
var hex = color.toHEXA().toString();
if (swatch) swatch.style.background = hex;
applyCustomColor(hex);
pickr.hide();
} catch (e) {}
});
// Clicking swatch opens pickr
if (swatch) swatch.addEventListener("click", function () {
pickr.show();
});
} catch (e) {
console.error("Pickr init failed", e);
}
return;
}
// wait a bit
setTimeout(ensurePickrAndInit, 150);
}
ensurePickrAndInit();
})();
```
--------------------------------
### Autocaliweb Docker Compose Configuration
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
This is a sample Docker Compose file for setting up Autocaliweb. Ensure you configure Timezone and volume binds according to your environment.
```yaml
services:
autocaliweb:
image: gelbphoenix/autocaliweb:latest
container_name: autocaliweb
restart: unless-stopped
ports:
- "8083:8083"
environment:
- TZ=Etc/UTC # Change to your specific timezone (e.g. Europe/Berlin, America/Denver)
- PUID=1000
- PGID=1000
volumes:
- /path/to/config:/config
- /path/to/book/ingest:/acw-book-ingest
- /path/to/library:/calibre-library
stop_signal: SIGINT
stop_grace_period: 15s
```
--------------------------------
### Download Docker Compose Template
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Use this command to download the Docker Compose template file. Save it to your desired data directory for Autocaliweb.
```bash
curl -Lo ./docker-compose.yml https://raw.githubusercontent.com/gelbphoenix/autocaliweb/main/docker-compose.yml
```
--------------------------------
### Comic Reader Initialization Script
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/readcbr.html
Initializes the Comic Reader application, setting up bookmarking functionality based on user authentication and stored bookmark data. It fetches the book content from the server.
```javascript
window.calibre = {
bookmarkUrl: "{{ url_for('web.set_bookmark', book_id=comicfile, book_format=extension.upper()) }}",
bookmark: "{{ bookmark.bookmark_key if bookmark != None }}",
useBookmarks: "{{ current_user.is_authenticated | tojson }}",
};
document.onreadystatechange = function () {
if (document.readyState == "complete") {
if (calibre.useBookmarks) {
currentImage = eval(calibre.bookmark);
if (typeof currentImage !== "number") {
currentImage = 0;
}
}
init( "{{ url_for('web.serve_book', book_id=comicfile, book_format=extension) }}" );
}
};
```
--------------------------------
### Configure Authelia Client for Autocaliweb
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Single-Sign-On-and-OpenID-Connect
Add this client configuration to your Authelia `configuration.yaml` to enable Autocaliweb as an OIDC client. Ensure the redirect URI matches your Autocaliweb domain.
```yaml
identity_providers:
oidc:
# ...
clients:
- id: autocaliweb
description: Autocaliweb
secret:
public: false
authorization_policy: one_factor # if you want to require 2FA, set this to `two_factor`
redirect_uris:
- "https:///login/generic/authorized"
scopes:
- openid
- profile
- email
userinfo_signed_response_alg: none
```
--------------------------------
### Calibre Web Application Configuration
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/listenmp3.html
Sets up global JavaScript variables for the Calibre web application, including paths to static assets, book URLs, and bookmarking configurations. This is used to interface with the backend for managing book data and user progress.
```javascript
window.calibre = {
filePath: "{{ url_for('static', filename='js/libs/') }}",
cssPath: "{{ url_for('static', filename='css/') }}",
bookUrl: "{{ url_for('static', filename=mp3file) }}/",
bookmarkUrl: "{{ url_for('web.set_bookmark', book_id=mp3file, book_format=audioformat.upper()) }}",
bookmark: "{{ bookmark.bookmark_key if bookmark != None }}",
useBookmarks: "{{ current_user.is_authenticated | tojson }}",
};
```
--------------------------------
### VoidAuth OIDC Client Configuration
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Single-Sign-On-and-OpenID-Connect
Configuration details for setting up a new OIDC client within the VoidAuth portal. These values are required for the Autocaliweb integration.
```text
Client ID: your-client-id
Auth Method: Client Secret Basic
Client Secret: your-client-secret
Redirect URLs: https://autocaliweb.example.com/login/generic/authorized
```
--------------------------------
### Kobo API Endpoint Configuration
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/generate_kobo_auth_url.html
Add this line to the .kobo/Kobo/Kobo eReader.conf file to set the API endpoint for Kobo eReader authentication. Ensure the auth_token is correctly generated.
```html
{% extends "fragment.html" %} {% block body %} {% if not warning %} {{\_('Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):')}}
api_endpoint={{url_for("kobo.TopLevelEndpoint", auth_token=auth_token, _external=True)}} {% else %} {{warning}} {% endif %} {% endblock %}
```
--------------------------------
### Jinja Macro for Book Cover Image
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/image.html
Generates a Markdown image link for a book cover. It sets the image title and alt text, constructs a srcset attribute, and creates a URL for the book's cover image, including a cache-busting parameter based on the last modification time.
```html
{% macro book_cover(book, alt=None) -%}
{%- set image_title = book.title if book.title else book.name -%}
{%- set image_alt = alt if alt else image_title -%}
{% set srcset = book|get_cover_srcset %}
 }})
{%- endmacro %}
```
--------------------------------
### Configure Libre Workspace OIDC Provider in Autocaliweb
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Single-Sign-On-and-OpenID-Connect
Use these settings to configure Autocaliweb to use Libre Workspace as an OIDC provider. Ensure you replace placeholders with your actual client ID, secret, and portal domain.
```text
generic OAuth Client Id:
generic OAuth Client Secret:
generic OAuth scope: openid profile email admin
generic OAuth Metadata URL: https:///.well-known/openid-configuration
Use Manual URLs: []
generic OAuth Username mapper: preferred_username
generic OAuth Email mapper: email
generic OAuth Login Button: (Libre Workspace or your own custom name)
```
--------------------------------
### Apply Theme Settings
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Applies background and title bar colors from a theme object based on the provided ID. Falls back to default white for title bar color if not specified.
```javascript
document.getElementById("main").style.backgroundColor = themes[id]["bgColor"]; document.getElementById("titlebar").style.color = themes[id]["title-color"] || "#fff"; document.getElementById("progress").style.color = themes[id]["title-color"] || "#fff";
```
--------------------------------
### Epub Reader Theme Selection Logic
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Handles the logic for selecting and applying themes in the Epub Reader. It updates the UI to show the selected theme and applies the theme to the reader's iframe.
```javascript
function selectTheme(id) { let tickSpans = document .getElementById("themes") .querySelectorAll("span"); // Remove tick mark from all theme buttons tickSpans.forEach(function (tickSpan) { try { tickSpan.textContent = ""; } catch (e) {} }); // Add tick mark to the button corresponding to the currently selected theme var el = document.getElementById(id); if (el) { var sp = el.querySelector("span"); if (sp) sp.textContent = "✓"; } else { var spById = document.getElementById(id + "Selected") || document.getElementById("customSelected"); if (spById) spById.textContent = "✓"; } // Saving theme to local storage localStorage.setItem("calibre.reader.theme", id); // If selecting custom theme, ensure epubjs theme is registered with chosen bg color if (id === "customTheme") { var customColor = window.themes.customTheme.bgColor || "#ffffff"; try { if (reader && reader.rendition && reader.rendition.themes) { reader.rendition.themes.register("customTheme", { body: { background: customColor, }, }); reader.rendition.themes.select("customTheme"); } } catch (e) { console.error("Failed to register/select customTheme", e); } } else { // Apply theme to epubjs iframe try { reader.rendition.themes.select(id); } catch (e) {} } // Apply theme to rest of the page.
```
--------------------------------
### Clone Autocaliweb Source Code
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Manual-Installation
Clone the Autocaliweb repository to the required /app/autocaliweb path and set ownership. This step is crucial for mimicking the Docker environment's directory structure.
```bash
sudo git clone https://github.com/gelbphoenix/autocaliweb.git /app/autocaliweb
sudo chown -R $USER:$USER /app
```
--------------------------------
### Initialize Navigation Mode on Load
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Immediately invoked function that retrieves the saved navigation mode from localStorage or defaults to 'sizes', then applies it using the selectNavMode function.
```javascript
(function () { var savedMode = localStorage.getItem("calibre.reader.navMode") || "sizes"; selectNavMode(savedMode); })();
```
--------------------------------
### Basic Pagination Controls
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/basic_index.html
Displays 'Previous' and 'Next' pagination links if they exist. Links are generated using url_for_other_page.
```html
{% if pagination.has_prev %} [« {{_('Previous')}}]({{ (pagination.page - 1)|url_for_other_page }}) {% endif %}
{% if pagination.has_next %} [{_('Next')} »]({{ (pagination.page + 1)|url_for_other_page }}) {% endif %}
```
--------------------------------
### Configure PDF Viewer Options
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/readpdf.html
Sets various options for the PDF viewer application upon loading, such as disabling auto-fetch, configuring cmap URL, and specifying worker source. This is useful for customizing the viewer's behavior and resource loading.
```javascript
window.addEventListener("webviewerloaded", function () {
PDFViewerApplicationOptions.set("disableAutoFetch", true);
PDFViewerApplicationOptions.set("disableRange", false);
PDFViewerApplicationOptions.set("disableStream", true);
PDFViewerApplicationOptions.set("disablePreferences", true);
PDFViewerApplicationOptions.set( "cMapUrl", "{{ url_for('static', filename='cmaps/') }}" );
PDFViewerApplicationOptions.set("sidebarViewOnLoad", 0);
PDFViewerApplicationOptions.set( "imageResourcesPath", "{{ url_for('static', filename='css/images/') }}" );
PDFViewerApplicationOptions.set( "workerSrc", "{{ url_for('static', filename='js/libs/pdf.worker.js') }}" );
PDFViewerApplicationOptions.set( "defaultUrl", "{{ url_for('web.serve_book', book_id=pdffile, book_format='pdf') }}" );
});
```
--------------------------------
### Run JavaScript Linting (CI Alias)
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
A CI-friendly alias for running JavaScript linting. This command is typically used in continuous integration pipelines.
```bash
npm run lint:ci
```
--------------------------------
### Generate Book Cover with Cache Busting
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/book_edit.html
Triggers a POST request to generate a book cover. On success, it reloads the cover image using a cache-busting query parameter and updates the button state. Handles errors by showing alerts.
```javascript
$(document).ready(() => {
$('#confirm-generate-cover').click(() => {
$.ajax({
type: 'POST',
url: "{{ url_for('edit-book.generate_book_cover', book_id=book.id) }}",
success: (response) => {
if (response.success) {
const coImg = document.getElementById('detailcover');
let cuSrc = coImg.src;
let newSrc;
if (cuSrc.includes("?")) {
newSrc = cuSrc + "&reload=" + new Date().getTime();
} else {
newSrc = cuSrc + "?reload=" + new Date().getTime();
}
coImg.src = newSrc;
const genButton = document.getElementById('generate-cover');
genButton.disabled = true;
genButton.innerText = "{{ _('Cover Generated – Click Save to save it') }}";
} else {
alert("{{ _('Error generating cover:') }} " + (response.error || "{{ _('Unknown error') }}"));
}
},
error: () => {
alert("{{ _('Error communicating with server') }}");
}
});
$('#generateCoverModal').modal('hide');
})
})
```
--------------------------------
### Main Entry Loop with Conditional Break
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/list.html
Iterates through a list of 'entries'. It includes a conditional check to potentially insert content after a certain number of items, specifically when the list length is greater than 20 and the current item is near the middle.
```html
{% for entry in entries %} {% if loop.index0 == (loop.length/2+loop.length%2)|int and loop.length > 20 %}
{% endif %}
{{entry[1]}}
[{% if entry.name %}
{% for number in range(entry.name|int) %} {% if loop.last and loop.index < 5 %} {% for numer in range(5 - loop.index) %} {% endfor %} {% endif %} {% endfor %}
{% else %} {% if entry.format %} {{entry.format}} {% else %} {{entry[0].name}}{% endif %}{% endif %}]({% if entry.format %}{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry.format )}}{% else %}{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry[0].id )}}{% endif %})
{% endfor %}
```
--------------------------------
### Run JavaScript Linting
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Executes ESLint to check for code style and potential errors in the JavaScript files. This command helps maintain code quality.
```bash
npm run lint
```
--------------------------------
### Compare and Display Cover Image Dimensions
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/book_edit.html
Compares the dimensions of a newly loaded image with an existing cover image and updates the display text with 'smaller' or 'larger' class if dimensions differ.
```javascript
function coverDimensions(el) {
var existing_cover = document.querySelector("#detailcover")
el.nextElementSibling.innerText = el.naturalWidth + 'x' + el.naturalHeight
if (existing_cover.naturalHeight*existing_cover.naturalWidth > el.naturalWidth * el.naturalHeight){
el.nextElementSibling.classList.add("smaller")
} else if (existing_cover.naturalHeight*existing_cover.naturalWidth < el.naturalWidth * el.naturalHeight){
el.nextElementSibling.classList.add("larger")
}
}
```
--------------------------------
### Jinja Macro for Series Cover Image
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/image.html
Generates a Markdown image link for a series cover. It sets the alt text and constructs a srcset attribute. The image URL is created for the series cover, incorporating a cache timestamp.
```html
{% macro series(series, alt=None) -%}
{%- set image_alt = alt if alt else image_title -%}
{% set srcset = series|get_series_srcset %}
 }})
{%- endmacro %}
```
--------------------------------
### Basic Search Form Fields
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/search_form.html
Renders input fields for book title, author, publisher, and date ranges. Includes options for read status and selection of tags, series, shelves, languages, and extensions.
```html
{% extends "layout.html" %} {% block body %} {{title}} ========= {{_('Book Title')}} {{_('Author')}} {{_('Publisher')}} {{_('Published Date From')}} {{_('Published Date To')}} {{_('Read Status')}} {{\_('Any')}} {{\_('Empty')}} {{\_('Yes')}} {{\_('No')}} {{_('Tags')}} {% for tag in tags %} {{tag.name}} {% endfor %} {{_('Exclude Tags')}} {% for tag in tags %} {{tag.name}} {% endfor %} {{_('Series')}} {% for serie in series %} {{serie.name}} {% endfor %} {{_('Exclude Series')}} {% for serie in series %} {{serie.name}} {% endfor %} {{_('Shelves')}} {% for shelf in shelves %} {{shelf.name}} {% endfor %} {{_('Exclude Shelves')}} {% for shelf in shelves %} {{shelf.name}} {% endfor %} {% if languages %} {{_('Languages')}} {% for language in languages %} {{language.name}} {% endfor %} {{_('Exclude Languages')}} {% for language in languages %} {{language.name}} {% endfor %} {% endif%} {{_('Extensions')}} {% for extension in extensions %} {{extension.format}} {% endfor %} {{_('Exclude Extensions')}} {% for extension in extensions %} {{extension.format}} {% endfor %} {{_('Rating Above')}} {{_('Rating Below')}} {{_('Description')}} {% if cc|length > 0 %} {% for c in cc %} {{ c.name }} {% if c.datatype == 'bool' %} {{\_('Any')}} {{\_('Empty')}} {{\_('Yes')}} {{\_('No')}} {% endif %} {% if c.datatype == 'int' %} {{_('From:')}} {{_('To:')}} {% endif %} {% if c.datatype == 'float' %} {{_('From:')}} {{_('To:')}} {% endif %} {% if c.datatype == 'datetime' %} {{_('From:')}} {{_('To:')}} {% endif %} {% if c.datatype in ['text', 'series', 'comments'] and not c.is_multiple %} {% endif %} {% if c.datatype in ['text', 'series'] and c.is_multiple %} {% endif %} {% if c.datatype == 'enumeration' %} {% for opt in c.get_display_dict().enum_values %} {{ opt }} {% endfor %} {% endif %} {% if c.datatype == 'rating' %} {% endif %} {% endfor %} {% endif %} {{_('Search')}} {% endblock %}
```
--------------------------------
### Initialize ACW Auto-Ingest Automerge Settings
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/acw_settings.html
This script initializes the ACW Auto-Ingest Automerge settings on page load. It fetches available metadata providers, populates the provider list, sets up drag-and-drop functionality for reordering, and handles fallback mechanisms if API calls fail.
```javascript
document.addEventListener('DOMContentLoaded', () => {
// Get current hierarchy from Autocaliweb settings
const currentHierarchyStr = {{ acw_settings.get("metadata_provider_hierarchy", '["ibdb","google","dnb"]') | tojson }};
let providerHierarchy = [];
try {
if (typeof currentHierarchyStr === 'string') {
providerHierarchy = JSON.parse(currentHierarchyStr);
} else {
providerHierarchy = currentHierarchyStr;
}
} catch (e) {
console.error('Error parsing hierarchy:', e);
providerHierarchy = ["ibdb", "google", "dnb"]; // fallback
}
// Fetch available providers from the API
fetch('/metadata/provider')
.then(response => response.json())
.then(providers => {
populateProviderList(providers, providerHierarchy);
setupDragAndDrop();
})
.catch(error => {
console.error('Error fetching providers:', error);
// Fallback with static list
const fallbackProviders = [
{id: 'google', name: 'Google Books', active: true},
{id: 'dnb', name: 'DNB', active: true},
{id: 'ibdb', name: 'IBDb', active: true},
{id: 'comicvine', name: 'ComicVine', active: true},
{id: 'douban', name: 'Douban', active: true}
];
populateProviderList(fallbackProviders, providerHierarchy);
setupDragAndDrop();
});
function populateProviderList(providers, hierarchy) {
const container = document.getElementById('metadata_provider_list');
const hiddenInput = document.getElementById('metadata_provider_hierarchy_hidden');
// Clear any existing content
container.innerHTML = '';
// Create a map of providers by ID for easy lookup
const providerMap = {};
providers.forEach(p => {
providerMap[p.id] = p;
});
// First add providers in the current hierarchy order (this is the saved user preference)
hierarchy.forEach(providerId => {
if (providerMap[providerId]) {
addProviderItem(container, providerMap[providerId]);
delete providerMap[providerId]; // Remove so we don't add twice
}
});
// Then add any remaining providers that weren't in the hierarchy (new providers)
// These will be added in the order they come from the API (alphabetical)
Object.values(providerMap).forEach(provider => {
addProviderItem(container, provider);
});
updateHiddenInput();
}
function addProviderItem(container, provider) {
const item = document.createElement('div');
item.className = 'metadata-provider-item';
item.draggable = false; // Disable native drag
item.dataset.providerId = provider.id;
// For admin settings, show all providers as enabled/available
item.innerHTML = ` ⋮⋮ ${provider.name} `;
container.appendChild(item);
}
function setupDragAndDrop() {
const container = document.getElementById('metadata_provider_list');
let draggedElement = null;
let isDragging = false;
let startY = 0;
let startX = 0;
container.addEventListener('mousedown', function(e) {
const item = e.target.closest('.metadata-provider-item');
if (!item) return;
draggedElement = item;
isDragging = true;
startY = e.clientY;
startX = e.clientX;
item.classList.add('dragging');
document.body.style.userSelect = 'none';
e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (!isDragging || !draggedElement) return;
const container = document.getElementById('metadata_provider_list');
const afterElement = getMouseAfterElement(container, e.clientY);
if (afterElement == null) {
container.appendChild(draggedElement);
} else {
container.insertBefore(draggedElement, afterElement);
}
});
document.addEventListener('mouseup', function(e) {
if (!isDragging) return;
isDragging = false;
if (draggedElement) {
draggedElement.classList.remove('dragging');
draggedElement = null;
}
document.body.style.userSelect = '';
updateHiddenInput();
});
}
function getMouseAfterElement(container, y) {
const draggableElements = [...container.querySelectorAll('.metadata-provider-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 };
} else {
return closest;
}
}, { offset: Number.NEGATIVE_INFINITY }).element;
}
function updateHiddenInput() {
const container = document.getElementById('metadata_provider_list');
const hiddenInput = document.getElementById('metadata_provider_hierarchy_hidden');
const items = container.querySelectorAll('.metadata-provider-item');
const hierarchy = Array.from(items).map(item => item.dataset.providerId);
hiddenInput.value = JSON.stringify(hierarchy);
}
// Initialize the hidden input value
updateHiddenInput();
});
```
--------------------------------
### Configure Pocket ID OIDC Provider in Autocaliweb
Source: https://github.com/gelbphoenix/autocaliweb/wiki/Single-Sign-On-and-OpenID-Connect
Configure Autocaliweb to use Pocket ID as an OIDC provider. Replace placeholders with your obtained Client ID, Client Secret, and OIDC Discovery URL.
```text
generic OAuth Client Id:
generic OAuth Client Secret:
generic OAuth scope: openid profile email
generic OAuth Metadata URL:
Use Manual URLs: []
generic OAuth Username mapper: preferred_username
generic OAuth Email mapper: email
generic OAuth Login Button: Pocket ID
```
--------------------------------
### Select Navigation Mode Function
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Controls the navigation mode (sides or gestures) by updating UI indicators and saving the preference to localStorage. It also calls an external function to apply the mode.
```javascript
function selectNavMode(mode) { var tickSides = document.getElementById("navSidesTick"); var tickGest = document.getElementById("navGesturesTick"); tickSides.textContent = mode === "sides" ? "✓" : ""; tickGest.textContent = mode === "gestures" ? "✓" : ""; localStorage.setItem("calibre.reader.navMode", mode); if (window.applyNavigationMode) { window.applyNavigationMode(mode); } }
```
--------------------------------
### Default Admin Credentials for Autocaliweb
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/README.md
Use these default credentials to log in to your Autocaliweb instance for the first time. Ensure you change them after initial access for security.
```text
Username: admin
Password: admin123
```
--------------------------------
### Conditional Display of 'All' Link
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/list.html
Displays the translated string 'All' if the 'charlist' has any elements. This is typically used to show a link to view all items.
```html
{% if charlist|length %}
{{\_('All')}}
{% endif %}
```
--------------------------------
### Epub Reader JavaScript Configuration
Source: https://github.com/gelbphoenix/autocaliweb/blob/main/cps/templates/read.html
Defines global JavaScript variables for the Epub Reader, including paths, URLs, and book-specific information. This configuration is essential for the reader's functionality.
```javascript
window.calibre = { filePath: "{{ url_for('static', filename='js/libs/') }}", cssPath: "{{ url_for('static', filename='css/') }}", bookmarkUrl: "{{ url_for('web.set_bookmark', book_id=bookid, book_format=book_format) }}", bookUrl: "{{ url_for('web.serve_book', book_id=bookid, book_format=book_format, anyname='file.epub') }}", bookmark: "{{ bookmark.bookmark_key if bookmark != None }}", useBookmarks: "{{ current_user.is_authenticated | tojson }}", }; var _savedCustomThemeColor = null; try { _savedCustomThemeColor = localStorage.getItem("calibre.reader.customTheme") } catch (e) {}
```