Compare commits
No commits in common. 'master' and '0.6.20' have entirely different histories.
@ -1,125 +1,109 @@
|
||||
# Short Notice from the maintainer
|
||||
# About
|
||||
|
||||
After 6 years of more or less intensive programming on Calibre-Web, I need a break.
|
||||
The last few months, maintaining Calibre-Web has felt more like work than a hobby. I felt pressured and teased by people to solve "their" problems and merge PRs for "their" Calibre-Web.
|
||||
I have turned off all notifications from Github/Discord and will now concentrate undisturbed on the development of “my” Calibre-Web over the next few weeks/months.
|
||||
I will look into the issues and maybe also the PRs from time to time, but don't expect a quick response from me.
|
||||
Calibre-Web is a web app providing a clean interface for browsing, reading and downloading eBooks using a valid [Calibre](https://calibre-ebook.com) database.
|
||||
|
||||
# Calibre-Web
|
||||
|
||||
Calibre-Web is a web app that offers a clean and intuitive interface for browsing, reading, and downloading eBooks using a valid [Calibre](https://calibre-ebook.com) database.
|
||||
|
||||
[![License](https://img.shields.io/github/license/janeczku/calibre-web?style=flat-square)](https://github.com/janeczku/calibre-web/blob/master/LICENSE)
|
||||
![Commit Activity](https://img.shields.io/github/commit-activity/w/janeczku/calibre-web?logo=github&style=flat-square&label=commits)
|
||||
[![All Releases](https://img.shields.io/github/downloads/janeczku/calibre-web/total?logo=github&style=flat-square)](https://github.com/janeczku/calibre-web/releases)
|
||||
[![GitHub License](https://img.shields.io/github/license/janeczku/calibre-web?style=flat-square)](https://github.com/janeczku/calibre-web/blob/master/LICENSE)
|
||||
[![GitHub commit activity](https://img.shields.io/github/commit-activity/w/janeczku/calibre-web?logo=github&style=flat-square&label=commits)]()
|
||||
[![GitHub all releases](https://img.shields.io/github/downloads/janeczku/calibre-web/total?logo=github&style=flat-square)](https://github.com/janeczku/calibre-web/releases)
|
||||
[![PyPI](https://img.shields.io/pypi/v/calibreweb?logo=pypi&logoColor=fff&style=flat-square)](https://pypi.org/project/calibreweb/)
|
||||
[![PyPI - Downloads](https://img.shields.io/pypi/dm/calibreweb?logo=pypi&logoColor=fff&style=flat-square)](https://pypi.org/project/calibreweb/)
|
||||
[![Discord](https://img.shields.io/discord/838810113564344381?label=Discord&logo=discord&style=flat-square)](https://discord.gg/h2VsJ2NEfB)
|
||||
|
||||
<details>
|
||||
<summary><strong>Table of Contents</strong> (click to expand)</summary>
|
||||
|
||||
1. [About](#calibre-web)
|
||||
2. [Features](#features)
|
||||
3. [Installation](#installation)
|
||||
- [Installation via pip (recommended)](#installation-via-pip-recommended)
|
||||
- [Quick start](#quick-start)
|
||||
- [Requirements](#requirements)
|
||||
4. [Docker Images](#docker-images)
|
||||
5. [Contributor Recognition](#contributor-recognition)
|
||||
6. [Contact](#contact)
|
||||
7. [Contributing to Calibre-Web](#contributing-to-calibre-web)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
*This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.*
|
||||
|
||||
![Main screen](https://github.com/janeczku/calibre-web/wiki/images/main_screen.png)
|
||||
|
||||
## Features
|
||||
|
||||
- Modern and responsive Bootstrap 3 HTML5 interface
|
||||
- Full graphical setup
|
||||
- Comprehensive user management with fine-grained per-user permissions
|
||||
- Bootstrap 3 HTML5 interface
|
||||
- full graphical setup
|
||||
- User management with fine-grained per-user permissions
|
||||
- Admin interface
|
||||
- Multilingual user interface supporting 20+ languages ([supported languages](https://github.com/janeczku/calibre-web/wiki/Translation-Status))
|
||||
- OPDS feed for eBook reader apps
|
||||
- Advanced search and filtering options
|
||||
- Custom book collection (shelves) creation
|
||||
- eBook metadata editing and deletion support
|
||||
- Metadata download from various sources (extensible via plugins)
|
||||
- eBook conversion through Calibre binaries
|
||||
- eBook download restriction to logged-in users
|
||||
- Public user registration support
|
||||
- Send eBooks to E-Readers with a single click
|
||||
- Sync Kobo devices with your Calibre library
|
||||
- In-browser eBook reading support for multiple formats
|
||||
- Upload new books in various formats, including audio formats
|
||||
- Calibre Custom Columns support
|
||||
- Content hiding based on categories and Custom Column content per user
|
||||
- User Interface in brazilian, czech, dutch, english, finnish, french, galician, german, greek, hungarian, indonesian, italian, japanese, khmer, korean, norwegian, polish, russian, simplified and traditional chinese, spanish, swedish, turkish, ukrainian, vietnamese
|
||||
- OPDS feed for eBook reader apps
|
||||
- Filter and search by titles, authors, tags, series, book format and language
|
||||
- Create a custom book collection (shelves)
|
||||
- Support for editing eBook metadata and deleting eBooks from Calibre library
|
||||
- Support for downloading eBook metadata from various sources, sources can be extended via external plugins
|
||||
- Support for converting eBooks through Calibre binaries
|
||||
- Restrict eBook download to logged-in users
|
||||
- Support for public user registration
|
||||
- Send eBooks to E-Readers with the click of a button
|
||||
- Sync your Kobo devices through Calibre-Web with your Calibre library
|
||||
- Support for reading eBooks directly in the browser (.txt, .epub, .pdf, .cbr, .cbt, .cbz, .djvu)
|
||||
- Upload new books in many formats, including audio formats (.mp3, .m4a, .m4b)
|
||||
- Support for Calibre Custom Columns
|
||||
- Ability to hide content based on categories and Custom Column content per user
|
||||
- Self-update capability
|
||||
- "Magic Link" login for easy access on eReaders
|
||||
- LDAP, Google/GitHub OAuth, and proxy authentication support
|
||||
- "Magic Link" login to make it easy to log on eReaders
|
||||
- Login via LDAP, google/github oauth and via proxy authentication
|
||||
|
||||
## Installation
|
||||
|
||||
#### Installation via pip (recommended)
|
||||
1. Create a virtual environment for Calibre-Web to avoid conflicts with existing Python dependencies
|
||||
2. Install Calibre-Web via pip: `pip install calibreweb` (or `pip3` depending on your OS/distro)
|
||||
3. Install optional features via pip as needed, see [this page](https://github.com/janeczku/calibre-web/wiki/Dependencies-in-Calibre-Web-Linux-and-Windows) for details
|
||||
4. Start Calibre-Web by typing `cps`
|
||||
1. To avoid problems with already installed python dependencies, it's recommended to create a virtual environment for Calibre-Web
|
||||
2. Install Calibre-Web via pip with the command `pip install calibreweb` (Depending on your OS and or distro the command could also be `pip3`).
|
||||
3. Optional features can also be installed via pip, please refer to [this page](https://github.com/janeczku/calibre-web/wiki/Dependencies-in-Calibre-Web-Linux-and-Windows) for details
|
||||
4. Calibre-Web can be started afterwards by typing `cps`
|
||||
|
||||
Issues with Raspberry Pi - Raspberry Pi OS:
|
||||
Depending on your version of pip it's possible that the installation fails with `Failed to build cryptography
|
||||
ERROR: Could not build wheels for cryptography, which is required to install pyproject.toml-based projects`.
|
||||
In this case please try to update pip with `./venv/bin/python3 -m pip install --upgrade pip` first, and then try installing Calibre-Web again.
|
||||
If this isn't working please also install cargo via `sudo apt install cargo`, and try installing Calibre-Web again.
|
||||
|
||||
*Note: Raspberry Pi OS users may encounter issues during installation. If so, please update pip (`./venv/bin/python3 -m pip install --upgrade pip`) and/or install cargo (`sudo apt install cargo`) before retrying the installation.*
|
||||
In the Wiki there are also examples for: a [manual installation](https://github.com/janeczku/calibre-web/wiki/Manual-installation), [installation on Linux Mint](https://github.com/janeczku/calibre-web/wiki/How-To:Install-Calibre-Web-in-Linux-Mint-19-or-20), [installation on a Cloud Provider](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-on-a-Cloud-Provider).
|
||||
|
||||
Refer to the Wiki for additional installation examples: [manual installation](https://github.com/janeczku/calibre-web/wiki/Manual-installation), [Linux Mint](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-in-Linux-Mint-19-or-20), [Cloud Provider](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-on-a-Cloud-Provider).
|
||||
## Quick start
|
||||
|
||||
## Quick Start
|
||||
Point your browser to `http://localhost:8083` or `http://localhost:8083/opds` for the OPDS catalog \
|
||||
Login with default admin login \
|
||||
If you don't have a Calibre database already, this [database](https://github.com/janeczku/calibre-web/blob/master/library/metadata.db) can be used. **IMPORTATNT** Please move the database out of the calibre-web folder structure, as it will be overwritten during update. \
|
||||
Set `Location of Calibre database` to the path of the folder where your Calibre library (metadata.db) lives, push "submit" button. \
|
||||
Optionally a Google Drive can be used to host the calibre library [-> Using Google Drive integration](https://github.com/janeczku/calibre-web/wiki/G-Drive-Setup#using-google-drive-integration) \
|
||||
Afterwards you can configure your Calibre-Web instance ([Basic Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#basic-configuration) and [UI Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#ui-configuration) on admin page)
|
||||
|
||||
1. Open your browser and navigate to `http://localhost:8083` or `http://localhost:8083/opds` for the OPDS catalog
|
||||
2. Log in with the default admin credentials
|
||||
3. If you don't have a Calibre database, you can use [this database](https://github.com/janeczku/calibre-web/raw/master/library/metadata.db) (move it out of the Calibre-Web folder to prevent overwriting during updates)
|
||||
4. Set `Location of Calibre database` to the path of the folder containing your Calibre library (metadata.db) and click "Save"
|
||||
5. Optionally, use Google Drive to host your Calibre library by following the [Google Drive integration guide](https://github.com/janeczku/calibre-web/wiki/G-Drive-Setup#using-google-drive-integration)
|
||||
6. Configure your Calibre-Web instance via the admin page, referring to the [Basic Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#basic-configuration) and [UI Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#ui-configuration) guides
|
||||
#### Default admin login:
|
||||
*Username:* admin\
|
||||
*Password:* admin123
|
||||
|
||||
#### Default Admin Login:
|
||||
- **Username:** admin
|
||||
- **Password:** admin123
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.5+
|
||||
- [Imagemagick](https://imagemagick.org/script/download.php) for cover extraction from EPUBs (Windows users may need to install [Ghostscript](https://ghostscript.com/releases/gsdnld.html) for PDF cover extraction)
|
||||
- Optional: [Calibre desktop program](https://calibre-ebook.com/download) for on-the-fly conversion and metadata editing (set "calibre's converter tool" path on the setup page)
|
||||
- Optional: [Kepubify tool](https://github.com/pgaskin/kepubify/releases/latest) for Kobo device support (place the binary in `/opt/kepubify` on Linux or `C:\Program Files\kepubify` on Windows)
|
||||
python 3.5+
|
||||
|
||||
## Docker Images
|
||||
[Download](https://imagemagick.org/script/download.php) Imagemagick to extract covers from epubs. On Windows the additional installation of [ghostscript](https://ghostscript.com/releases/gsdnld.html) might be necessary to extract covers from pdf files. On Linux Imagemagick and Ghostscript can often be installed using the system package manager.
|
||||
|
||||
Pre-built Docker images are available in the following Docker Hub repositories (maintained by the LinuxServer team):
|
||||
Optionally, to enable on-the-fly conversion from one ebook format to another when using the send-to-ereader feature, or during editing of ebooks metadata:
|
||||
|
||||
#### **LinuxServer - x64, aarch64**
|
||||
- [Docker Hub](https://hub.docker.com/r/linuxserver/calibre-web)
|
||||
- [GitHub](https://github.com/linuxserver/docker-calibre-web)
|
||||
- [GitHub - Optional Calibre layer](https://github.com/linuxserver/docker-mods/tree/universal-calibre)
|
||||
[Download and install](https://calibre-ebook.com/download) the Calibre desktop program for your platform and enter the folder including program name (normally /opt/calibre/ebook-convert, or C:\Program Files\calibre\ebook-convert.exe) in the field "calibre's converter tool" on the setup page.
|
||||
|
||||
Include the environment variable `DOCKER_MODS=linuxserver/mods:universal-calibre` in your Docker run/compose file to add the Calibre `ebook-convert` binary (x64 only). Omit this variable for a lightweight image.
|
||||
[Download](https://github.com/pgaskin/kepubify/releases/latest) Kepubify tool for your platform and place the binary starting with `kepubify` in Linux: `/opt/kepubify` Windows: `C:\Program Files\kepubify`.
|
||||
|
||||
Both the Calibre-Web and Calibre-Mod images are automatically rebuilt on new releases and updates.
|
||||
|
||||
- Set "path to convertertool" to `/usr/bin/ebook-convert`
|
||||
- Set "path to unrar" to `/usr/bin/unrar`
|
||||
## Docker Images
|
||||
|
||||
A pre-built Docker image is available in these Docker Hub repository (maintained by the LinuxServer team):
|
||||
|
||||
## Contributor Recognition
|
||||
#### **LinuxServer - x64, armhf, aarch64**
|
||||
+ Docker Hub - [https://hub.docker.com/r/linuxserver/calibre-web](https://hub.docker.com/r/linuxserver/calibre-web)
|
||||
+ Github - [https://github.com/linuxserver/docker-calibre-web](https://github.com/linuxserver/docker-calibre-web)
|
||||
+ Github - (Optional Calibre layer) - [https://github.com/linuxserver/docker-calibre-web/tree/calibre](https://github.com/linuxserver/docker-calibre-web/tree/calibre)
|
||||
|
||||
We would like to thank all the [contributors](https://github.com/janeczku/calibre-web/graphs/contributors) and maintainers of Calibre-Web for their valuable input and dedication to the project. Your contributions are greatly appreciated.
|
||||
This image has the option to pull in an extra docker manifest layer to include the Calibre `ebook-convert` binary. Just include the environmental variable `DOCKER_MODS=linuxserver/calibre-web:calibre` in your docker run/docker compose file. **(x64 only)**
|
||||
|
||||
If you do not need this functionality then this can be omitted, keeping the image as lightweight as possible.
|
||||
|
||||
Both the Calibre-Web and Calibre-Mod images are rebuilt automatically on new releases of Calibre-Web and Calibre respectively, and on updates to any included base image packages on a weekly basis if required.
|
||||
+ The "path to convertertool" should be set to `/usr/bin/ebook-convert`
|
||||
+ The "path to unrar" should be set to `/usr/bin/unrar`
|
||||
|
||||
## Contact
|
||||
# Contact
|
||||
|
||||
Join us on [Discord](https://discord.gg/h2VsJ2NEfB)
|
||||
Just reach us out on [Discord](https://discord.gg/h2VsJ2NEfB)
|
||||
|
||||
For more information, How To's, and FAQs, please visit the [Wiki](https://github.com/janeczku/calibre-web/wiki)
|
||||
For further information, How To's and FAQ please check the [Wiki](https://github.com/janeczku/calibre-web/wiki)
|
||||
|
||||
## Contributing to Calibre-Web
|
||||
# Contributing to Calibre-Web
|
||||
|
||||
Check out our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md)
|
||||
Please have a look at our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md)
|
||||
|
@ -1,53 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2018-2019 OzzieIsaacs
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import logger
|
||||
from lxml.etree import ParserError
|
||||
|
||||
try:
|
||||
# at least bleach 6.0 is needed -> incomplatible change from list arguments to set arguments
|
||||
from bleach import clean_text as clean_html
|
||||
BLEACH = True
|
||||
except ImportError:
|
||||
try:
|
||||
BLEACH = False
|
||||
from nh3 import clean as clean_html
|
||||
except ImportError:
|
||||
try:
|
||||
BLEACH = False
|
||||
from lxml.html.clean import clean_html
|
||||
except ImportError:
|
||||
clean_html = None
|
||||
|
||||
|
||||
log = logger.create()
|
||||
|
||||
|
||||
def clean_string(unsafe_text, book_id=0):
|
||||
try:
|
||||
if BLEACH:
|
||||
safe_text = clean_html(unsafe_text, tags=set(), attributes=set())
|
||||
else:
|
||||
safe_text = clean_html(unsafe_text)
|
||||
except ParserError as e:
|
||||
log.error("Comments of book {} are corrupted: {}".format(book_id, e))
|
||||
safe_text = ""
|
||||
except TypeError as e:
|
||||
log.error("Comments can't be parsed, maybe 'lxml' is too new, try installing 'bleach': {}".format(e))
|
||||
safe_text = ""
|
||||
return safe_text
|
@ -1,63 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2024 OzzieIsaacs
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
from uuid import uuid4
|
||||
import os
|
||||
|
||||
from .file_helper import get_temp_dir
|
||||
from .subproc_wrapper import process_open
|
||||
from . import logger, config
|
||||
from .constants import SUPPORTED_CALIBRE_BINARIES
|
||||
|
||||
log = logger.create()
|
||||
|
||||
|
||||
def do_calibre_export(book_id, book_format):
|
||||
try:
|
||||
quotes = [3, 5, 7, 9]
|
||||
tmp_dir = get_temp_dir()
|
||||
calibredb_binarypath = get_calibre_binarypath("calibredb")
|
||||
temp_file_name = str(uuid4())
|
||||
my_env = os.environ.copy()
|
||||
if config.config_calibre_split:
|
||||
my_env['CALIBRE_OVERRIDE_DATABASE_PATH'] = os.path.join(config.config_calibre_dir, "metadata.db")
|
||||
library_path = config.config_calibre_split_dir
|
||||
else:
|
||||
library_path = config.config_calibre_dir
|
||||
opf_command = [calibredb_binarypath, 'export', '--dont-write-opf', '--with-library', library_path,
|
||||
'--to-dir', tmp_dir, '--formats', book_format, "--template", "{}".format(temp_file_name),
|
||||
str(book_id)]
|
||||
p = process_open(opf_command, quotes, my_env)
|
||||
_, err = p.communicate()
|
||||
if err:
|
||||
log.error('Metadata embedder encountered an error: %s', err)
|
||||
return tmp_dir, temp_file_name
|
||||
except OSError as ex:
|
||||
# ToDo real error handling
|
||||
log.error_or_exception(ex)
|
||||
return None, None
|
||||
|
||||
|
||||
def get_calibre_binarypath(binary):
|
||||
binariesdir = config.config_binariesdir
|
||||
if binariesdir:
|
||||
try:
|
||||
return os.path.join(binariesdir, SUPPORTED_CALIBRE_BINARIES[binary])
|
||||
except KeyError as ex:
|
||||
log.error("Binary not supported by Calibre-Web: %s", SUPPORTED_CALIBRE_BINARIES[binary])
|
||||
pass
|
||||
return ""
|
@ -1,166 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2018 lemmsh, Kennyl, Kyosfonica, matthazinski
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import zipfile
|
||||
from lxml import etree
|
||||
|
||||
from . import isoLanguages
|
||||
|
||||
default_ns = {
|
||||
'n': 'urn:oasis:names:tc:opendocument:xmlns:container',
|
||||
'pkg': 'http://www.idpf.org/2007/opf',
|
||||
}
|
||||
|
||||
OPF_NAMESPACE = "http://www.idpf.org/2007/opf"
|
||||
PURL_NAMESPACE = "http://purl.org/dc/elements/1.1/"
|
||||
|
||||
OPF = "{%s}" % OPF_NAMESPACE
|
||||
PURL = "{%s}" % PURL_NAMESPACE
|
||||
|
||||
etree.register_namespace("opf", OPF_NAMESPACE)
|
||||
etree.register_namespace("dc", PURL_NAMESPACE)
|
||||
|
||||
OPF_NS = {None: OPF_NAMESPACE} # the default namespace (no prefix)
|
||||
NSMAP = {'dc': PURL_NAMESPACE, 'opf': OPF_NAMESPACE}
|
||||
|
||||
|
||||
def updateEpub(src, dest, filename, data, ):
|
||||
# create a temp copy of the archive without filename
|
||||
with zipfile.ZipFile(src, 'r') as zin:
|
||||
with zipfile.ZipFile(dest, 'w') as zout:
|
||||
zout.comment = zin.comment # preserve the comment
|
||||
for item in zin.infolist():
|
||||
if item.filename != filename:
|
||||
zout.writestr(item, zin.read(item.filename))
|
||||
|
||||
# now add filename with its new data
|
||||
with zipfile.ZipFile(dest, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
|
||||
zf.writestr(filename, data)
|
||||
|
||||
|
||||
def get_content_opf(file_path, ns=default_ns):
|
||||
epubZip = zipfile.ZipFile(file_path)
|
||||
txt = epubZip.read('META-INF/container.xml')
|
||||
tree = etree.fromstring(txt)
|
||||
cf_name = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0]
|
||||
cf = epubZip.read(cf_name)
|
||||
|
||||
return etree.fromstring(cf), cf_name
|
||||
|
||||
|
||||
def create_new_metadata_backup(book, custom_columns, export_language, translated_cover_name, lang_type=3):
|
||||
# generate root package element
|
||||
package = etree.Element(OPF + "package", nsmap=OPF_NS)
|
||||
package.set("unique-identifier", "uuid_id")
|
||||
package.set("version", "2.0")
|
||||
|
||||
# generate metadata element and all sub elements of it
|
||||
metadata = etree.SubElement(package, "metadata", nsmap=NSMAP)
|
||||
identifier = etree.SubElement(metadata, PURL + "identifier", id="calibre_id", nsmap=NSMAP)
|
||||
identifier.set(OPF + "scheme", "calibre")
|
||||
identifier.text = str(book.id)
|
||||
identifier2 = etree.SubElement(metadata, PURL + "identifier", id="uuid_id", nsmap=NSMAP)
|
||||
identifier2.set(OPF + "scheme", "uuid")
|
||||
identifier2.text = book.uuid
|
||||
for i in book.identifiers:
|
||||
identifier = etree.SubElement(metadata, PURL + "identifier", nsmap=NSMAP)
|
||||
identifier.set(OPF + "scheme", i.format_type())
|
||||
identifier.text = str(i.val)
|
||||
title = etree.SubElement(metadata, PURL + "title", nsmap=NSMAP)
|
||||
title.text = book.title
|
||||
for author in book.authors:
|
||||
creator = etree.SubElement(metadata, PURL + "creator", nsmap=NSMAP)
|
||||
creator.text = str(author.name)
|
||||
creator.set(OPF + "file-as", book.author_sort) # ToDo Check
|
||||
creator.set(OPF + "role", "aut")
|
||||
contributor = etree.SubElement(metadata, PURL + "contributor", nsmap=NSMAP)
|
||||
contributor.text = "calibre (5.7.2) [https://calibre-ebook.com]"
|
||||
contributor.set(OPF + "file-as", "calibre") # ToDo Check
|
||||
contributor.set(OPF + "role", "bkp")
|
||||
|
||||
date = etree.SubElement(metadata, PURL + "date", nsmap=NSMAP)
|
||||
date.text = '{d.year:04}-{d.month:02}-{d.day:02}T{d.hour:02}:{d.minute:02}:{d.second:02}'.format(d=book.pubdate)
|
||||
if book.comments and book.comments[0].text:
|
||||
for b in book.comments:
|
||||
description = etree.SubElement(metadata, PURL + "description", nsmap=NSMAP)
|
||||
description.text = b.text
|
||||
for b in book.publishers:
|
||||
publisher = etree.SubElement(metadata, PURL + "publisher", nsmap=NSMAP)
|
||||
publisher.text = str(b.name)
|
||||
if not book.languages:
|
||||
language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP)
|
||||
language.text = export_language
|
||||
else:
|
||||
for b in book.languages:
|
||||
language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP)
|
||||
language.text = str(b.lang_code) if lang_type == 3 else isoLanguages.get(part3=b.lang_code).part1
|
||||
for b in book.tags:
|
||||
subject = etree.SubElement(metadata, PURL + "subject", nsmap=NSMAP)
|
||||
subject.text = str(b.name)
|
||||
etree.SubElement(metadata, "meta", name="calibre:author_link_map",
|
||||
content="{" + ", ".join(['"' + str(a.name) + '": ""' for a in book.authors]) + "}",
|
||||
nsmap=NSMAP)
|
||||
for b in book.series:
|
||||
etree.SubElement(metadata, "meta", name="calibre:series",
|
||||
content=str(str(b.name)),
|
||||
nsmap=NSMAP)
|
||||
if book.series:
|
||||
etree.SubElement(metadata, "meta", name="calibre:series_index",
|
||||
content=str(book.series_index),
|
||||
nsmap=NSMAP)
|
||||
if len(book.ratings) and book.ratings[0].rating > 0:
|
||||
etree.SubElement(metadata, "meta", name="calibre:rating",
|
||||
content=str(book.ratings[0].rating),
|
||||
nsmap=NSMAP)
|
||||
etree.SubElement(metadata, "meta", name="calibre:timestamp",
|
||||
content='{d.year:04}-{d.month:02}-{d.day:02}T{d.hour:02}:{d.minute:02}:{d.second:02}'.format(
|
||||
d=book.timestamp),
|
||||
nsmap=NSMAP)
|
||||
etree.SubElement(metadata, "meta", name="calibre:title_sort",
|
||||
content=book.sort,
|
||||
nsmap=NSMAP)
|
||||
sequence = 0
|
||||
for cc in custom_columns:
|
||||
value = None
|
||||
extra = None
|
||||
cc_entry = getattr(book, "custom_column_" + str(cc.id))
|
||||
if cc_entry.__len__():
|
||||
value = [c.value for c in cc_entry] if cc.is_multiple else cc_entry[0].value
|
||||
extra = cc_entry[0].extra if hasattr(cc_entry[0], "extra") else None
|
||||
etree.SubElement(metadata, "meta", name="calibre:user_metadata:#{}".format(cc.label),
|
||||
content=cc.to_json(value, extra, sequence),
|
||||
nsmap=NSMAP)
|
||||
sequence += 1
|
||||
|
||||
# generate guide element and all sub elements of it
|
||||
# Title is translated from default export language
|
||||
guide = etree.SubElement(package, "guide")
|
||||
etree.SubElement(guide, "reference", type="cover", title=translated_cover_name, href="cover.jpg")
|
||||
|
||||
return package
|
||||
|
||||
def replace_metadata(tree, package):
|
||||
rep_element = tree.xpath('/pkg:package/pkg:metadata', namespaces=default_ns)[0]
|
||||
new_element = package.xpath('//metadata', namespaces=default_ns)[0]
|
||||
tree.replace(rep_element, new_element)
|
||||
return etree.tostring(tree,
|
||||
xml_declaration=True,
|
||||
encoding='utf-8',
|
||||
pretty_print=True).decode('utf-8')
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2023 OzzieIsaacs
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from tempfile import gettempdir
|
||||
import os
|
||||
import shutil
|
||||
|
||||
def get_temp_dir():
|
||||
tmp_dir = os.path.join(gettempdir(), 'calibre_web')
|
||||
if not os.path.isdir(tmp_dir):
|
||||
os.mkdir(tmp_dir)
|
||||
return tmp_dir
|
||||
|
||||
|
||||
def del_temp_dir():
|
||||
tmp_dir = os.path.join(gettempdir(), 'calibre_web')
|
||||
shutil.rmtree(tmp_dir)
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 60 KiB |
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="140px" height="140px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:1" fill="#45b29d" d="M 70.5,5.5 C 87.7691,3.12603 97.4358,10.4594 99.5,27.5C 95.637,46.6972 84.3037,59.1972 65.5,65C 60.9053,66.3929 56.2387,66.7262 51.5,66C 50.0692,65.5348 48.9025,64.7014 48,63.5C 47.3333,60.5 47.3333,57.5 48,54.5C 62.2513,56.0484 73.5846,50.715 82,38.5C 85.0332,33.8945 86.0332,28.8945 85,23.5C 83.0488,19.2854 79.7155,17.2854 75,17.5C 65.5257,19.0759 57.859,23.7425 52,31.5C 38.306,51.6368 33.9727,73.6368 39,97.5C 44.5639,116.532 56.7306,122.699 75.5,116C 80.6017,113.385 85.2684,110.218 89.5,106.5C 95.1927,108.891 96.6927,112.891 94,118.5C 78.4211,132.151 61.2544,134.651 42.5,126C 31.5182,117.21 25.3516,105.71 24,91.5C 20.9978,65.8515 27.3311,42.8515 43,22.5C 50.6154,14.1193 59.7821,8.45258 70.5,5.5 Z"/></g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1 +0,0 @@
|
||||
!function(a){a.fn.datepicker.dates.pt={days:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],daysShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],daysMin:["Do","Se","Te","Qu","Qu","Se","Sa"],months:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthsShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],today:"Hoje",monthsTitle:"Meses",clear:"Limpar",format:"dd/mm/yyyy"}}(jQuery);
|
@ -1 +0,0 @@
|
||||
!function(a){a.fn.datepicker.dates.sk={days:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"],daysShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],daysMin:["Ne","Po","Ut","St","Št","Pia","So"],months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],today:"Dnes",clear:"Vymazať",weekStart:1,format:"d.m.yyyy"}}(jQuery);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,462 +0,0 @@
|
||||
tinymce.addI18n('pt_PT',{
|
||||
"Redo": "Refazer",
|
||||
"Undo": "Anular",
|
||||
"Cut": "Cortar",
|
||||
"Copy": "Copiar",
|
||||
"Paste": "Colar",
|
||||
"Select all": "Selecionar tudo",
|
||||
"New document": "Novo documento",
|
||||
"Ok": "Ok",
|
||||
"Cancel": "Cancelar",
|
||||
"Visual aids": "Ajuda visual",
|
||||
"Bold": "Negrito",
|
||||
"Italic": "It\u00e1lico",
|
||||
"Underline": "Sublinhado",
|
||||
"Strikethrough": "Rasurado",
|
||||
"Superscript": "Superior \u00e0 linha",
|
||||
"Subscript": "Inferior \u00e0 linha",
|
||||
"Clear formatting": "Limpar formata\u00e7\u00e3o",
|
||||
"Align left": "Alinhar \u00e0 esquerda",
|
||||
"Align center": "Alinhar ao centro",
|
||||
"Align right": "Alinhar \u00e0 direita",
|
||||
"Justify": "Justificar",
|
||||
"Bullet list": "Lista com marcas",
|
||||
"Numbered list": "Lista numerada",
|
||||
"Decrease indent": "Diminuir avan\u00e7o",
|
||||
"Increase indent": "Aumentar avan\u00e7o",
|
||||
"Close": "Fechar",
|
||||
"Formats": "Formatos",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "O seu navegador n\u00e3o suporta acesso direto \u00e0 \u00e1rea de transfer\u00eancia. Por favor, use os atalhos Ctrl+X\/C\/V do seu teclado.",
|
||||
"Headers": "Cabe\u00e7alhos",
|
||||
"Header 1": "Cabe\u00e7alho 1",
|
||||
"Header 2": "Cabe\u00e7alho 2",
|
||||
"Header 3": "Cabe\u00e7alho 3",
|
||||
"Header 4": "Cabe\u00e7alho 4",
|
||||
"Header 5": "Cabe\u00e7alho 5",
|
||||
"Header 6": "Cabe\u00e7alho 6",
|
||||
"Headings": "T\u00edtulos",
|
||||
"Heading 1": "T\u00edtulo 1",
|
||||
"Heading 2": "T\u00edtulo 2",
|
||||
"Heading 3": "T\u00edtulo 3",
|
||||
"Heading 4": "T\u00edtulo 4",
|
||||
"Heading 5": "T\u00edtulo 5",
|
||||
"Heading 6": "T\u00edtulo 6",
|
||||
"Preformatted": "Pr\u00e9-formatado",
|
||||
"Div": "Div",
|
||||
"Pre": "Pre",
|
||||
"Code": "C\u00f3digo",
|
||||
"Paragraph": "Par\u00e1grafo",
|
||||
"Blockquote": "Blockquote",
|
||||
"Inline": "Inline",
|
||||
"Blocks": "Blocos",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "O comando colar est\u00e1 em modo de texto simples. O conte\u00fado ser\u00e1 colado como texto simples at\u00e9 desativar esta op\u00e7\u00e3o.",
|
||||
"Fonts": "Tipos de letra",
|
||||
"Font Sizes": "Tamanhos dos tipos de letra",
|
||||
"Class": "Classe",
|
||||
"Browse for an image": "Procurar uma imagem",
|
||||
"OR": "OU",
|
||||
"Drop an image here": "Largar aqui uma imagem",
|
||||
"Upload": "Carregar",
|
||||
"Block": "Bloco",
|
||||
"Align": "Alinhar",
|
||||
"Default": "Padr\u00e3o",
|
||||
"Circle": "C\u00edrculo",
|
||||
"Disc": "Disco",
|
||||
"Square": "Quadrado",
|
||||
"Lower Alpha": "a. b. c. ...",
|
||||
"Lower Greek": "\\u03b1. \\u03b2. \\u03b3. ...",
|
||||
"Lower Roman": "i. ii. iii. ...",
|
||||
"Upper Alpha": "A. B. C. ...",
|
||||
"Upper Roman": "I. II. III. ...",
|
||||
"Anchor...": "\u00c2ncora...",
|
||||
"Name": "Nome",
|
||||
"Id": "ID",
|
||||
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "O ID deve come\u00e7ar com uma letra, seguido apenas por letras, n\u00fameros, pontos, dois pontos, tra\u00e7os ou sobtra\u00e7os.",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "Existem altera\u00e7\u00f5es que ainda n\u00e3o foram guardadas. Tem a certeza que pretende sair?",
|
||||
"Restore last draft": "Restaurar o \u00faltimo rascunho",
|
||||
"Special character...": "Car\u00e1ter especial...",
|
||||
"Source code": "C\u00f3digo fonte",
|
||||
"Insert\/Edit code sample": "Inserir\/editar amostra de c\u00f3digo",
|
||||
"Language": "Idioma",
|
||||
"Code sample...": "Amostra de c\u00f3digo...",
|
||||
"Color Picker": "Seletor de cores",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"B": "B",
|
||||
"Left to right": "Da esquerda para a direita",
|
||||
"Right to left": "Da direita para a esquerda",
|
||||
"Emoticons": "Emo\u00e7\u00f5es",
|
||||
"Emoticons...": "\u00cdcones expressivos...",
|
||||
"Metadata and Document Properties": "Metadados e propriedades do documento",
|
||||
"Title": "T\u00edtulo",
|
||||
"Keywords": "Palavras-chave",
|
||||
"Description": "Descri\u00e7\u00e3o",
|
||||
"Robots": "Rob\u00f4s",
|
||||
"Author": "Autor",
|
||||
"Encoding": "Codifica\u00e7\u00e3o",
|
||||
"Fullscreen": "Ecr\u00e3 completo",
|
||||
"Action": "A\u00e7\u00e3o",
|
||||
"Shortcut": "Atalho",
|
||||
"Help": "Ajuda",
|
||||
"Address": "Endere\u00e7o",
|
||||
"Focus to menubar": "Foco na barra de menu",
|
||||
"Focus to toolbar": "Foco na barra de ferramentas",
|
||||
"Focus to element path": "Foco no caminho do elemento",
|
||||
"Focus to contextual toolbar": "Foco na barra de contexto",
|
||||
"Insert link (if link plugin activated)": "Inserir hiperliga\u00e7\u00e3o (se o plugin de liga\u00e7\u00f5es estiver ativado)",
|
||||
"Save (if save plugin activated)": "Guardar (se o plugin de guardar estiver ativado)",
|
||||
"Find (if searchreplace plugin activated)": "Pesquisar (se o plugin pesquisar e substituir estiver ativado)",
|
||||
"Plugins installed ({0}):": "Plugins instalados ({0}):",
|
||||
"Premium plugins:": "Plugins comerciais:",
|
||||
"Learn more...": "Saiba mais...",
|
||||
"You are using {0}": "Est\u00e1 a usar {0}",
|
||||
"Plugins": "Plugins",
|
||||
"Handy Shortcuts": "Atalhos \u00fateis",
|
||||
"Horizontal line": "Linha horizontal",
|
||||
"Insert\/edit image": "Inserir\/editar imagem",
|
||||
"Alternative description": "Descri\u00e7\u00e3o alternativa",
|
||||
"Accessibility": "Acessibilidade",
|
||||
"Image is decorative": "Imagem \u00e9 decorativa",
|
||||
"Source": "Localiza\u00e7\u00e3o",
|
||||
"Dimensions": "Dimens\u00f5es",
|
||||
"Constrain proportions": "Manter propor\u00e7\u00f5es",
|
||||
"General": "Geral",
|
||||
"Advanced": "Avan\u00e7ado",
|
||||
"Style": "Estilo",
|
||||
"Vertical space": "Espa\u00e7amento vertical",
|
||||
"Horizontal space": "Espa\u00e7amento horizontal",
|
||||
"Border": "Contorno",
|
||||
"Insert image": "Inserir imagem",
|
||||
"Image...": "Imagem...",
|
||||
"Image list": "Lista de imagens",
|
||||
"Rotate counterclockwise": "Rota\u00e7\u00e3o anti-hor\u00e1ria",
|
||||
"Rotate clockwise": "Rota\u00e7\u00e3o hor\u00e1ria",
|
||||
"Flip vertically": "Inverter verticalmente",
|
||||
"Flip horizontally": "Inverter horizontalmente",
|
||||
"Edit image": "Editar imagem",
|
||||
"Image options": "Op\u00e7\u00f5es de imagem",
|
||||
"Zoom in": "Mais zoom",
|
||||
"Zoom out": "Menos zoom",
|
||||
"Crop": "Recortar",
|
||||
"Resize": "Redimensionar",
|
||||
"Orientation": "Orienta\u00e7\u00e3o",
|
||||
"Brightness": "Brilho",
|
||||
"Sharpen": "Mais nitidez",
|
||||
"Contrast": "Contraste",
|
||||
"Color levels": "N\u00edveis de cor",
|
||||
"Gamma": "Gama",
|
||||
"Invert": "Inverter",
|
||||
"Apply": "Aplicar",
|
||||
"Back": "Voltar",
|
||||
"Insert date\/time": "Inserir data\/hora",
|
||||
"Date\/time": "Data\/hora",
|
||||
"Insert\/edit link": "Inserir\/editar liga\u00e7\u00e3o",
|
||||
"Text to display": "Texto a exibir",
|
||||
"Url": "URL",
|
||||
"Open link in...": "Abrir liga\u00e7\u00e3o em...",
|
||||
"Current window": "Janela atual",
|
||||
"None": "Nenhum",
|
||||
"New window": "Nova janela",
|
||||
"Open link": "Abrir liga\u00e7\u00e3o",
|
||||
"Remove link": "Remover liga\u00e7\u00e3o",
|
||||
"Anchors": "\u00c2ncora",
|
||||
"Link...": "Liga\u00e7\u00e3o...",
|
||||
"Paste or type a link": "Copiar ou escrever uma hiperliga\u00e7\u00e3o",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "O URL que indicou parece ser um endere\u00e7o de email. Quer adicionar o prefixo mailto: tal como necess\u00e1rio?",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "O URL que indicou parece ser um endere\u00e7o web. Quer adicionar o prefixo http:\/\/ tal como necess\u00e1rio?",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required https:\/\/ prefix?": "O URL que introduziu parece ser uma liga\u00e7\u00e3o externa. Deseja adicionar-lhe o prefixo https:\/\/ ?",
|
||||
"Link list": "Lista de liga\u00e7\u00f5es",
|
||||
"Insert video": "Inserir v\u00eddeo",
|
||||
"Insert\/edit video": "Inserir\/editar v\u00eddeo",
|
||||
"Insert\/edit media": "Inserir\/editar media",
|
||||
"Alternative source": "Localiza\u00e7\u00e3o alternativa",
|
||||
"Alternative source URL": "URL da origem alternativa",
|
||||
"Media poster (Image URL)": "Publicador de media (URL da imagem)",
|
||||
"Paste your embed code below:": "Colar c\u00f3digo para embeber:",
|
||||
"Embed": "Embeber",
|
||||
"Media...": "Media...",
|
||||
"Nonbreaking space": "Espa\u00e7o n\u00e3o quebr\u00e1vel",
|
||||
"Page break": "Quebra de p\u00e1gina",
|
||||
"Paste as text": "Colar como texto",
|
||||
"Preview": "Pr\u00e9-visualizar",
|
||||
"Print...": "Imprimir...",
|
||||
"Save": "Guardar",
|
||||
"Find": "Pesquisar",
|
||||
"Replace with": "Substituir por",
|
||||
"Replace": "Substituir",
|
||||
"Replace all": "Substituir tudo",
|
||||
"Previous": "Anterior",
|
||||
"Next": "Pr\u00f3ximo",
|
||||
"Find and Replace": "Pesquisar e substituir",
|
||||
"Find and replace...": "Localizar e substituir...",
|
||||
"Could not find the specified string.": "N\u00e3o foi poss\u00edvel localizar o termo especificado.",
|
||||
"Match case": "Diferenciar mai\u00fasculas e min\u00fasculas",
|
||||
"Find whole words only": "Localizar apenas palavras inteiras",
|
||||
"Find in selection": "Pesquisar na selec\u00e7\u00e3o",
|
||||
"Spellcheck": "Corretor ortogr\u00e1fico",
|
||||
"Spellcheck Language": "Idioma de verifica\u00e7\u00e3o lingu\u00edstica",
|
||||
"No misspellings found.": "N\u00e3o foram encontrados erros ortogr\u00e1ficos.",
|
||||
"Ignore": "Ignorar",
|
||||
"Ignore all": "Ignorar tudo",
|
||||
"Finish": "Concluir",
|
||||
"Add to Dictionary": "Adicionar ao dicion\u00e1rio",
|
||||
"Insert table": "Inserir tabela",
|
||||
"Table properties": "Propriedades da tabela",
|
||||
"Delete table": "Eliminar tabela",
|
||||
"Cell": "C\u00e9lula",
|
||||
"Row": "Linha",
|
||||
"Column": "Coluna",
|
||||
"Cell properties": "Propriedades da c\u00e9lula",
|
||||
"Merge cells": "Unir c\u00e9lulas",
|
||||
"Split cell": "Dividir c\u00e9lula",
|
||||
"Insert row before": "Inserir linha antes",
|
||||
"Insert row after": "Inserir linha depois",
|
||||
"Delete row": "Eliminar linha",
|
||||
"Row properties": "Propriedades da linha",
|
||||
"Cut row": "Cortar linha",
|
||||
"Copy row": "Copiar linha",
|
||||
"Paste row before": "Colar linha antes",
|
||||
"Paste row after": "Colar linha depois",
|
||||
"Insert column before": "Inserir coluna antes",
|
||||
"Insert column after": "Inserir coluna depois",
|
||||
"Delete column": "Eliminar coluna",
|
||||
"Cols": "Colunas",
|
||||
"Rows": "Linhas",
|
||||
"Width": "Largura",
|
||||
"Height": "Altura",
|
||||
"Cell spacing": "Espa\u00e7amento entre c\u00e9lulas",
|
||||
"Cell padding": "Espa\u00e7amento interno da c\u00e9lula",
|
||||
"Caption": "Legenda",
|
||||
"Show caption": "Mostrar legenda",
|
||||
"Left": "Esquerda",
|
||||
"Center": "Centro",
|
||||
"Right": "Direita",
|
||||
"Cell type": "Tipo de c\u00e9lula",
|
||||
"Scope": "Escopo",
|
||||
"Alignment": "Alinhamento",
|
||||
"H Align": "Alinhamento H",
|
||||
"V Align": "Alinhamento V",
|
||||
"Top": "Superior",
|
||||
"Middle": "Meio",
|
||||
"Bottom": "Inferior",
|
||||
"Header cell": "C\u00e9lula de cabe\u00e7alho",
|
||||
"Row group": "Agrupar linha",
|
||||
"Column group": "Agrupar coluna",
|
||||
"Row type": "Tipo de linha",
|
||||
"Header": "Cabe\u00e7alho",
|
||||
"Body": "Corpo",
|
||||
"Footer": "Rodap\u00e9",
|
||||
"Border color": "Cor de contorno",
|
||||
"Insert template...": "Inserir modelo...",
|
||||
"Templates": "Modelos",
|
||||
"Template": "Tema",
|
||||
"Text color": "Cor do texto",
|
||||
"Background color": "Cor de fundo",
|
||||
"Custom...": "Personalizada...",
|
||||
"Custom color": "Cor personalizada",
|
||||
"No color": "Sem cor",
|
||||
"Remove color": "Remover cor",
|
||||
"Table of Contents": "\u00cdndice",
|
||||
"Show blocks": "Mostrar blocos",
|
||||
"Show invisible characters": "Mostrar caracteres invis\u00edveis",
|
||||
"Word count": "Contagem de palavras",
|
||||
"Count": "Contagem",
|
||||
"Document": "Documento",
|
||||
"Selection": "Sele\u00e7\u00e3o",
|
||||
"Words": "Palavras",
|
||||
"Words: {0}": "Palavras: {0}",
|
||||
"{0} words": "{0} palavras",
|
||||
"File": "Ficheiro",
|
||||
"Edit": "Editar",
|
||||
"Insert": "Inserir",
|
||||
"View": "Ver",
|
||||
"Format": "Formatar",
|
||||
"Table": "Tabela",
|
||||
"Tools": "Ferramentas",
|
||||
"Powered by {0}": "Criado em {0}",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Caixa de texto formatado. Pressione ALT-F9 para exibir o menu. Pressione ALT-F10 para exibir a barra de ferramentas. Pressione ALT-0 para exibir a ajuda",
|
||||
"Image title": "T\u00edtulo da imagem",
|
||||
"Border width": "Largura do limite",
|
||||
"Border style": "Estilo do limite",
|
||||
"Error": "Erro",
|
||||
"Warn": "Aviso",
|
||||
"Valid": "V\u00e1lido",
|
||||
"To open the popup, press Shift+Enter": "Para abrir o pop-up, prima Shift+Enter",
|
||||
"Rich Text Area. Press ALT-0 for help.": "\u00c1rea de texto formatado. Prima ALT-0 para exibir a ajuda.",
|
||||
"System Font": "Tipo de letra do sistema",
|
||||
"Failed to upload image: {0}": "Falha ao carregar imagem: {0}",
|
||||
"Failed to load plugin: {0} from url {1}": "Falha ao carregar plugin: {0} do URL {1}",
|
||||
"Failed to load plugin url: {0}": "Falha ao carregar o URL do plugin: {0}",
|
||||
"Failed to initialize plugin: {0}": "Falha ao inicializar plugin: {0}",
|
||||
"example": "exemplo",
|
||||
"Search": "Pesquisar",
|
||||
"All": "Tudo",
|
||||
"Currency": "Moeda",
|
||||
"Text": "Texto",
|
||||
"Quotations": "Aspas",
|
||||
"Mathematical": "Matem\u00e1tico",
|
||||
"Extended Latin": "Carateres latinos estendidos",
|
||||
"Symbols": "S\u00edmbolos",
|
||||
"Arrows": "Setas",
|
||||
"User Defined": "Definido pelo utilizador",
|
||||
"dollar sign": "cifr\u00e3o",
|
||||
"currency sign": "sinal monet\u00e1rio",
|
||||
"euro-currency sign": "sinal monet\u00e1rio do euro",
|
||||
"colon sign": "sinal de dois pontos",
|
||||
"cruzeiro sign": "sinal de cruzeiro",
|
||||
"french franc sign": "sinal de franco franc\u00eas",
|
||||
"lira sign": "sinal de lira",
|
||||
"mill sign": "sinal de por mil",
|
||||
"naira sign": "sinal de naira",
|
||||
"peseta sign": "sinal de peseta",
|
||||
"rupee sign": "sinal de r\u00fapia",
|
||||
"won sign": "sinal de won",
|
||||
"new sheqel sign": "sinal de novo sheqel",
|
||||
"dong sign": "sinal de dong",
|
||||
"kip sign": "sinal kip",
|
||||
"tugrik sign": "sinal tugrik",
|
||||
"drachma sign": "sinal drachma",
|
||||
"german penny symbol": "sinal de penny alem\u00e3o",
|
||||
"peso sign": "sinal de peso",
|
||||
"guarani sign": "sinal de guarani",
|
||||
"austral sign": "sinal de austral",
|
||||
"hryvnia sign": "sinal hryvnia",
|
||||
"cedi sign": "sinal de cedi",
|
||||
"livre tournois sign": "sinal de libra de tours",
|
||||
"spesmilo sign": "sinal de spesmilo",
|
||||
"tenge sign": "sinal de tengue",
|
||||
"indian rupee sign": "sinal de rupia indiana",
|
||||
"turkish lira sign": "sinal de lira turca",
|
||||
"nordic mark sign": "sinal de marca n\u00f3rdica",
|
||||
"manat sign": "sinal manat",
|
||||
"ruble sign": "sinal de rublo",
|
||||
"yen character": "sinal de iene",
|
||||
"yuan character": "sinal de iuane",
|
||||
"yuan character, in hong kong and taiwan": "sinal de iuane, em Hong Kong e Taiwan",
|
||||
"yen\/yuan character variant one": "variante um de sinal de iene\/iuane",
|
||||
"Loading emoticons...": "A carregar \u00edcones expressivos...",
|
||||
"Could not load emoticons": "N\u00e3o foi poss\u00edvel carregar \u00edcones expressivos",
|
||||
"People": "Pessoas",
|
||||
"Animals and Nature": "Animais e natureza",
|
||||
"Food and Drink": "Comida e bebida",
|
||||
"Activity": "Atividade",
|
||||
"Travel and Places": "Viagens e lugares",
|
||||
"Objects": "Objetos",
|
||||
"Flags": "Bandeiras",
|
||||
"Characters": "Carateres",
|
||||
"Characters (no spaces)": "Carateres (sem espa\u00e7os)",
|
||||
"{0} characters": "{0} carateres",
|
||||
"Error: Form submit field collision.": "Erro: conflito no campo de submiss\u00e3o de formul\u00e1rio.",
|
||||
"Error: No form element found.": "Erro: nenhum elemento de formul\u00e1rio encontrado.",
|
||||
"Update": "Atualizar",
|
||||
"Color swatch": "Cole\u00e7\u00e3o de cores",
|
||||
"Turquoise": "Turquesa",
|
||||
"Green": "Verde",
|
||||
"Blue": "Azul",
|
||||
"Purple": "P\u00farpura",
|
||||
"Navy Blue": "Azul-atl\u00e2ntico",
|
||||
"Dark Turquoise": "Turquesa escuro",
|
||||
"Dark Green": "Verde escuro",
|
||||
"Medium Blue": "Azul interm\u00e9dio",
|
||||
"Medium Purple": "P\u00farpura interm\u00e9dio",
|
||||
"Midnight Blue": "Azul muito escuro",
|
||||
"Yellow": "Amarelo",
|
||||
"Orange": "Laranja",
|
||||
"Red": "Vermelho",
|
||||
"Light Gray": "Cinzento claro",
|
||||
"Gray": "Cinzento",
|
||||
"Dark Yellow": "Amarelo escuro",
|
||||
"Dark Orange": "Laranja escuro",
|
||||
"Dark Red": "Vermelho escuro",
|
||||
"Medium Gray": "Cinzento m\u00e9dio",
|
||||
"Dark Gray": "Cinzento escuro",
|
||||
"Light Green": "Verde claro",
|
||||
"Light Yellow": "Amarelo claro",
|
||||
"Light Red": "Vermelho claro",
|
||||
"Light Purple": "P\u00farpura claro",
|
||||
"Light Blue": "Azul claro",
|
||||
"Dark Purple": "P\u00farpura escuro",
|
||||
"Dark Blue": "Azul escuro",
|
||||
"Black": "Preto",
|
||||
"White": "Branco",
|
||||
"Switch to or from fullscreen mode": "Entrar ou sair do modo de ecr\u00e3 inteiro",
|
||||
"Open help dialog": "Abrir caixa de di\u00e1logo Ajuda",
|
||||
"history": "hist\u00f3rico",
|
||||
"styles": "estilos",
|
||||
"formatting": "formata\u00e7\u00e3o",
|
||||
"alignment": "alinhamento",
|
||||
"indentation": "avan\u00e7o",
|
||||
"Font": "Tipo de letra",
|
||||
"Size": "Tamanho",
|
||||
"More...": "Mais...",
|
||||
"Select...": "Selecionar...",
|
||||
"Preferences": "Prefer\u00eancias",
|
||||
"Yes": "Sim",
|
||||
"No": "N\u00e3o",
|
||||
"Keyboard Navigation": "Navega\u00e7\u00e3o com teclado",
|
||||
"Version": "Vers\u00e3o",
|
||||
"Code view": "Vista do c\u00f3digo-fonte",
|
||||
"Open popup menu for split buttons": "Abrir o menu popup para bot\u00f5es divididos",
|
||||
"List Properties": "Propriedades da lista",
|
||||
"List properties...": "Propriedades da lista\u2026",
|
||||
"Start list at number": "Come\u00e7ar a lista pelo n\u00famero",
|
||||
"Line height": "Altura da linha",
|
||||
"comments": "coment\u00e1rios",
|
||||
"Format Painter": "Pincel de formata\u00e7\u00e3o",
|
||||
"Insert\/edit iframe": "Inserir\/editar iframe",
|
||||
"Capitalization": "Capitaliza\u00e7\u00e3o",
|
||||
"lowercase": "min\u00fasculas",
|
||||
"UPPERCASE": "MAI\u00daSCULAS",
|
||||
"Title Case": "Iniciais mai\u00fasculas",
|
||||
"permanent pen": "caneta permanente",
|
||||
"Permanent Pen Properties": "Propriedades da Caneta Permanente",
|
||||
"Permanent pen properties...": "Propriedades da caneta permanente...",
|
||||
"case change": "mudan\u00e7a de capitaliza\u00e7\u00e3o",
|
||||
"page embed": "incorporar p\u00e1gina",
|
||||
"Advanced sort...": "Ordena\u00e7\u00e3o avan\u00e7ada\u2026",
|
||||
"Advanced Sort": "Ordena\u00e7\u00e3o avan\u00e7ada",
|
||||
"Sort table by column ascending": "Ordenar tabela por coluna ascendente",
|
||||
"Sort table by column descending": "Ordenar tabela por coluna descendente",
|
||||
"Sort": "Ordenar",
|
||||
"Order": "Ordem",
|
||||
"Sort by": "Ordenar por",
|
||||
"Ascending": "Ascendente",
|
||||
"Descending": "Descendente",
|
||||
"Column {0}": "Coluna {0}",
|
||||
"Row {0}": "Linha {0}",
|
||||
"Spellcheck...": "Verifica\u00e7\u00e3o ortogr\u00e1fica...",
|
||||
"Misspelled word": "Palavra mal escrita",
|
||||
"Suggestions": "Sugest\u00f5es",
|
||||
"Change": "Alterar",
|
||||
"Finding word suggestions": "Encontrar sugest\u00f5es de palavras",
|
||||
"Success": "Sucesso",
|
||||
"Repair": "Reparar",
|
||||
"Issue {0} of {1}": "Problema {0} de {1}",
|
||||
"Images must be marked as decorative or have an alternative text description": "As imagens devem ser marcadas como decorativas ou ter uma descri\u00e7\u00e3o textual alternativa",
|
||||
"Images must have an alternative text description. Decorative images are not allowed.": "As imagens devem ter uma descri\u00e7\u00e3o textual alternativa. N\u00e3o s\u00e3o permitidas imagens meramente decorativas.",
|
||||
"Or provide alternative text:": "Ou forne\u00e7a um texto alternativo:",
|
||||
"Make image decorative:": "Marque a imagem como decorativa:",
|
||||
"ID attribute must be unique": "O atributo ID tem de ser \u00fanico",
|
||||
"Make ID unique": "Tornar o ID \u00fanico",
|
||||
"Keep this ID and remove all others": "Mantenha este ID e remova todos os outros",
|
||||
"Remove this ID": "Remover este ID",
|
||||
"Remove all IDs": "Remover todos os IDs",
|
||||
"Checklist": "Lista de verifica\u00e7\u00e3o",
|
||||
"Anchor": "\u00c2ncora",
|
||||
"Special character": "Car\u00e1cter especial",
|
||||
"Code sample": "Amostra de c\u00f3digo",
|
||||
"Color": "Cor",
|
||||
"Document properties": "Propriedades do documento",
|
||||
"Image description": "Descri\u00e7\u00e3o da imagem",
|
||||
"Image": "Imagem",
|
||||
"Insert link": "Inserir liga\u00e7\u00e3o",
|
||||
"Target": "Alvo",
|
||||
"Link": "Liga\u00e7\u00e3o",
|
||||
"Poster": "Autor",
|
||||
"Media": "Media",
|
||||
"Print": "Imprimir",
|
||||
"Prev": "Anterior",
|
||||
"Find and replace": "Pesquisar e substituir",
|
||||
"Whole words": "Palavras completas",
|
||||
"Insert template": "Inserir modelo"
|
||||
});
|
@ -1,47 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
|
||||
# Copyright (C) 2023 OzzieIsaacs
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from urllib.request import urlopen
|
||||
|
||||
from flask_babel import lazy_gettext as N_
|
||||
|
||||
from cps import logger, file_helper
|
||||
from cps.services.worker import CalibreTask
|
||||
|
||||
|
||||
class TaskDeleteTempFolder(CalibreTask):
|
||||
def __init__(self, task_message=N_('Delete temp folder contents')):
|
||||
super(TaskDeleteTempFolder, self).__init__(task_message)
|
||||
self.log = logger.create()
|
||||
|
||||
def run(self, worker_thread):
|
||||
try:
|
||||
file_helper.del_temp_dir()
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except (PermissionError, OSError) as e:
|
||||
self.log.error("Error deleting temp folder: {}".format(e))
|
||||
self._handleSuccess()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return "Delete Temp Folder"
|
||||
|
||||
@property
|
||||
def is_cancellable(self):
|
||||
return False
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue