Skip to content

Commit

Permalink
v1.3.9 (#301)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajslater authored Apr 27, 2023
1 parent 7a2eef5 commit 30e28f0
Show file tree
Hide file tree
Showing 83 changed files with 2,944 additions and 1,809 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ dev-server: kill
.PHONY: dev-prod-server
## Run a bundled production webserver
## @category Run Server
dev-prod-server: collectstatic
dev-prod-server: build-frontend collectstatic
./bin/dev-prod-server.sh

.PHONY: dev-frontend-server
Expand Down
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ width: 128px;
border-radius: 128px;
" />

## v1.3.9

- Features
- Experimental OPDS 2.0 Support.
- Create all comic covers admin task.
- Faster Metadata pages for web and OPDS.
- Fix
- Two pages mode broken.
- Credits not imported bug.
- Failed imports not removed when file removed bug.

## v1.3.8

- Fix
Expand Down
49 changes: 30 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ border-radius: 128px;
- Watches the filesystem and automatically imports new or changed comics.
- Private Libraries accessible only to certain groups of users.
- Reads CBZ, CBR, CBT, and PDF formatted comics.
- Syndication with OPDS, streaming, search and authentication.
- Syndication with OPDS 1 & 2, streaming, search and authentication.
- Runs in 1GB of RAM, faster with more.

### Examples
Expand Down Expand Up @@ -350,6 +350,13 @@ the side drawer. It should take the form:

`http(s)://host.tld(:9810)(/root_path)/opds/v1.2/`

or

`http(s)://host.tld(:9810)(/root_path)/opds/v2.0/`

OPDS 2.0 support is experimental and not widely or well supported by clients.
OPDS 2.0 book readers exist, but I am not yet aware of an OPDS 2.0 comic reader.

#### Clients

- iOS has [Panels](https://panels.app/), [KYBook 3](http://kybook-reader.com/),
Expand Down Expand Up @@ -417,22 +424,6 @@ rebuild it. The database lives in the config directory as the file
`config/db.sqlite3`. If this procedure goes kablooey, you may recover the
original database at `config/db.sqlite3.backup`.

## \<a name="bug_reports>🐛 Bug Reports</a>

Issues and feature requests are best filed on the
[Github issue tracker](https://github.com/ajslater/codex/issues).

By the generosity of the good people of
[Mylar](https://github.com/mylar3/mylar3), I and other Codex users may be found
answering questions on the [Mylar Discord](https://discord.gg/6UG94R7E8T).
Please use the `#codex-support` channel to ask for help with Codex.

## <a name="out-of-scope">🚫 Out of Scope</a>

- I have no intention of making this an eBook reader.
- I think metadata editing would be better placed in a comic manager than a
reader.

## <a name="alternatives-to-codex">📚Alternatives</a>

- [Kavita](https://www.kavitareader.com/) has light metadata filtering/editing,
Expand All @@ -444,7 +435,20 @@ Please use the `#codex-support` channel to ask for help with Codex.
- [Comictagger](https://github.com/comictagger/comictagger) is a comic metadata
editor. It comes with a powerful command line and desktop GUI.

## <a name="develop-codex">🛠 Develop</a>
## <a name="contributing">🤝 Contributing</a>

### <a name="bug_reports">🐛 Bug Reports</a>

Issues and feature requests are best filed on the
[Github issue tracker](https://github.com/ajslater/codex/issues).

### <a name="out-of-scope">🚫 Out of Scope</a>

- I have no intention of making this an eBook reader.
- I think metadata editing would be better placed in a comic manager than a
reader.

### <a name="develop-codex">🛠 Develop</a>

Codex is a Django Python webserver with a VueJS front end.

Expand All @@ -456,7 +460,14 @@ database.
Most of Codex development is now controlled through the Makefile. Type `make`
for a list of commands.

## \<a name="links>🔗 Links</a>
## <a name="discord">💬 Support</a>

By the generosity of the good people of
[Mylar](https://github.com/mylar3/mylar3), I and other Codex users answer
questions on the [Mylar Discord](https://discord.gg/6UG94R7E8T). Please use the
`#codex-support` channel to ask for help with Codex.

## <a name="links">🔗 Links</a>

- [Docker Image](https://hub.docker.com/r/ajslater/codex)
- [PyPi Package](https://pypi.org/project/codex/)
Expand Down
1 change: 1 addition & 0 deletions codex/db_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.db.models.fields import CharField


# TODO unused
class GroupConcat(Aggregate):
"""Sqlite3 group_concat() function."""

Expand Down
14 changes: 3 additions & 11 deletions codex/librarian/covers/coverd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from codex.librarian.covers.create import CoverCreateMixin
from codex.librarian.covers.purge import CoverPurgeMixin
from codex.librarian.covers.tasks import (
CoverBulkCreateTask,
CoverCreateTask,
CoverCreateAllTask,
CoverRemoveAllTask,
CoverRemoveOrphansTask,
CoverRemoveTask,
Expand All @@ -24,14 +23,7 @@ def process_item(self, task):
self.purge_comic_covers(task.comic_pks)
elif isinstance(task, CoverRemoveOrphansTask):
self.cleanup_orphan_covers()

#####################
# UNUSED BELOW HERE #
#####################

elif isinstance(task, CoverCreateTask):
self.create_cover(task.pk)
elif isinstance(task, CoverBulkCreateTask):
self.bulk_create_comic_covers(task.comic_pks)
elif isinstance(task, CoverCreateAllTask):
self.create_all_covers()
else:
self.log.error(f"Bad task sent to {self.__class__.__name__}: {task}")
28 changes: 12 additions & 16 deletions codex/librarian/covers/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class CoverCreateMixin(CoverPathMixin):
"""Create methods for covers."""

_COVER_RATIO = 1.5372233400402415 # modal cover ratio
_THUMBNAIL_WIDTH = 165
_THUMBNAIL_HEIGHT = round(_THUMBNAIL_WIDTH * _COVER_RATIO)
_THUMBNAIL_SIZE = (_THUMBNAIL_WIDTH, _THUMBNAIL_HEIGHT)
THUMBNAIL_WIDTH = 165
THUMBNAIL_HEIGHT = round(THUMBNAIL_WIDTH * _COVER_RATIO)
_THUMBNAIL_SIZE = (THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)

@classmethod
def _create_cover_thumbnail(cls, cover_image_data):
Expand Down Expand Up @@ -81,19 +81,8 @@ def save_cover_to_cache(self, cover_path, data):
else:
cover_path.symlink_to(self.MISSING_COVER_PATH)

#####################
# UNUSED BELOW HERE #
#####################

def create_cover(self, pk):
"""Create a cover from a comic id."""
# XXX Unused.
cover_path = self.get_cover_path(pk)
self.create_cover_from_path(pk, cover_path, self.log, self.librarian_queue)

def bulk_create_comic_covers(self, comic_pks):
def _bulk_create_comic_covers(self, comic_pks):
"""Create bulk comic covers."""
# XXX Unused
num_comics = len(comic_pks)
if not num_comics:
return None
Expand All @@ -111,7 +100,9 @@ def bulk_create_comic_covers(self, comic_pks):
status.decrement_total()
else:
# bulk creator creates covers inline
self.create_cover(pk)
self.create_cover_from_path(
pk, cover_path, self.log, self.librarian_queue
)
status.increment_complete()
self.status_controller.update(status)

Expand All @@ -120,3 +111,8 @@ def bulk_create_comic_covers(self, comic_pks):
finally:
self.status_controller.finish(status)
return status.complete

def create_all_covers(self):
"""Create all covers for all libraries."""
pks = Comic.objects.values_list("pk", flat=True)
self._bulk_create_comic_covers(pks)
18 changes: 2 additions & 16 deletions codex/librarian/covers/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,6 @@ class CoverSaveToCache(CoverTask):
data: bytes


#####################
# UNUSED BELOW HERE #
#####################


@dataclass
class CoverCreateTask(CoverTask):
"""Create one comic cover."""

pk: int


@dataclass
class CoverBulkCreateTask(CoverTask):
"""A list of comic src and dest paths."""

comic_pks: frozenset
class CoverCreateAllTask(CoverTask):
"""A create all comic covers."""
2 changes: 2 additions & 0 deletions codex/librarian/importer/clean_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
"updated_at",
)
)
_MD_TRANFORMED_KEYS = frozenset(("credits",))
_MD_VALID_KEYS = (
frozenset([field.name for field in Comic._meta.get_fields()]) - _MD_INVALID_KEYS
| _MD_TRANFORMED_KEYS
)
_MD_DECIMAL_KEYS = frozenset(("community_rating", "critical_rating"))
_MD_PSI_KEYS = frozenset(
Expand Down
2 changes: 1 addition & 1 deletion codex/librarian/importer/create_fks.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,5 +249,5 @@ def bulk_create_creators(self, create_creator_tuples, status=None):
self.log.info(f"Created {count} creators.")
if status:
status.complete += count
status.update(status)
self.status_controller.update(status)
return count
5 changes: 4 additions & 1 deletion codex/librarian/importer/db_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,14 @@ def update_create_and_link_comics(

return imported_count

def fail_imports(self, library, failed_imports):
def fail_imports(self, library, failed_imports, is_files_deleted):
"""Handle failed imports."""
created_count = 0
try:
fis = {"update_fis": {}, "create_fis": {}, "delete_fi_paths": set()}
if is_files_deleted:
# if any files were deleted. Run the failed import check
failed_imports["files_deleted"] = True
status = Status(ImportStatusTypes.FAILED_IMPORTS, 0, len(failed_imports))
status.total = self.query_failed_imports(
failed_imports,
Expand Down
3 changes: 3 additions & 0 deletions codex/librarian/importer/failed_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ def query_failed_imports(
if not failed_imports:
return 0

# Remove the files deleted hack thing.
failed_imports.pop("files_deleted", None)

existing_failed_import_paths = set(
FailedImport.objects.filter(library=library).values_list("path", flat=True)
)
Expand Down
4 changes: 3 additions & 1 deletion codex/librarian/importer/importerd.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,9 @@ def _apply(self, task):
simple_metadata
) = modified_paths = created_paths = mds = m2m_mds = fks = None

new_failed_imports = self.fail_imports(library, fis)
new_failed_imports = self.fail_imports(
library, fis, bool(task.files_deleted)
)

changed += self.delete(library, task)
cache.clear()
Expand Down
9 changes: 8 additions & 1 deletion codex/librarian/janitor/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ def update_codex(self, force=False):
self.log.info("Codex seems outdated. Trying to update.")

subprocess.run(
(sys.executable, "-m", "pip", "install", "--upgrade", "codex"),
( # noqa: S603
sys.executable,
"-m",
"pip",
"install",
"--upgrade",
"codex",
),
check=True,
)
except Exception:
Expand Down
Loading

0 comments on commit 30e28f0

Please sign in to comment.