A web based comic book reader and library manager.
- Scan & manage comic books.
- Read your comic books anywhere.
- Log in with your Google account or username & password.
- Continue reading while offline.
- Automatically sync progress when connectivity is restored.
- Make use of embedded metadata from ComicRack.
- Look up missing metadata from the Comic Vine API.
- Edit metadata on individual comic books.
- Switch color schemes (aka dark mode).
- Spring Boot 2 back end.
- MongoDB.
- Google Sign-In or username/password authentication.
- Ionic v5 / Angular 9 PWA.
Building requires either Java 17 SDK or Docker.
Running the application requires a Java 17 JRE or Docker
Recommended: a Client ID for Google Sign-In.
This is the recommended way to build and run Alfred.
docker network create alfred-net
docker start mongo || docker run -d -p 27017:27017 --name mongo mongo:4.2
docker network connect alfred-net mongo
docker build -t de.wasenweg/alfred .
docker run --dns 8.8.8.8 -p 5000:8080 --net=alfred-net --rm \
-v <Path to your comic library>:/comics \
-v <Path to where you want to receive log files>:/logs \
-e SPRING_PROFILES_ACTIVE=prod \
-e SPRING_DATA_MONGODB_URI=mongodb://mongo/alfred \
-e COMICS_COMICVINE_APIKEY=<Your Comic Vine API key> \
-e LOGGING_FILE=/logs/alfred.log \
-e AUTH_CLIENT_ID=<Your Google Client ID, ends in .apps.googleusercontent.com> \
-e AUTH_USERS=<Comma separated list of allowed user IDs, e.g. email addresses> \
-e AUTH_JWT_SECRET=<Your own generated or custom JWT secret> \
--name alfred \
de.wasenweg/alfred
Configuration options are explained here.
For a detailed explanation, please continue reading:
Set up a common network:
docker network create alfred-net
Set up a new MongoDB connected to the network:
docker run --name mongo -p 27017:27017 --net=alfred-net mongo
If you want to use an existing MongoDB instead, run and connect it to the network:
docker start mongo
docker network connect alfred-net mongo
Build the docker image:
docker build -t de.wasenweg/alfred .
Run the image and connect to the MongoDB:
docker run -p 5000:8080 --net=alfred-net -v /path/to/comics:/comics de.wasenweg/alfred
Replace /path/to/comics
with the path to your comic library.
The application will now be available at http://localhost:5000.
Running Alfred on the host system directly requires Java 17 SDK and a running MongoDB instance, e.g. on localhost
.
./gradlew clean build -x check
java -jar build/libs/alfred.jar --spring.data.mongodb.uri=mongodb://localhost/alfred
The application will now be available at http://localhost:8080.
Apart from the JWT secret (auth.jwt.secret
), all settings can initially be passed to the application via Spring's configuration options. They're then stored and maintained in the MongoDB settings
collection and take precedence over configuration options. Once the application is running, settings can be changed on the settings
page.
To pass an option via docker, use an environment variable, e.g.: docker run -e AUTH_CLIENT_ID=000000.apps.googleusercontent.com ...
.
The default comics path is /comics
which allows you to associate it via a Docker volume mount.
Required when using Google Sign-In. Create a set of client credentials in the Google API console. Configure the Authorized JavaScript origins
as well as Authorized redirect URIs
to reflect the host name of your Alfred instance. The Client ID format should be 000000.apps.googleusercontent.com
.
The initial set of allowed users must be passed to the application on the first run. They're a comma separated list of email addresses associated with a Google ID when using Google Sign-In, otherwise they can have any format. Only matching users will be allowed to use the application and its API.
Required only when not using Google Sign-In. When using username & password authentication, a comma separated list of passwords must be specified here matching the users in auth.users
.
Once the application authenticates the user, it issues its own JWT authentication token which requires a secret key. A default key is supplied but should be overridden whenever the application is run (it's not stored in the DB).
Comic books not containing a meta data XML or an XML without enough attributes won't be usable. Missing meta data can be fetched from the Comic Vine API for which you need an API key.
Comic book files need to be in CBZ format which is essentially a zip archive containing page images. In order to recoginize a comic book, Alfred needs at least the following information:
- A publisher, e.g.
DC Comics
. - A series, e.g.
Batman
. - A volume, e.g.
1940
. - An issue number, e.g.
380
.
It expects to find these in a file named ComicInfo.xml
which is located on the top level of the zip archive. Its format is loosley compatible with that produced by ComicRack, see docs.
Failing that, Alfred will attempt to retrieve metadata from the Comic Vine API based on information found in the file path, which is why it must match the followin structure:
/any/directory/<publisher>/<series> (<volume>)/<series> <issue number> (<volume>).cbz
By default, the application logs only to the console it was started in. In order to output logs to a file, use the logging.file
application property, e.g. start the app with LOGGING_FILE=alfred.log
.
In docker, this can be achieved by settings a volume and an environment variable. Starting the container with these parameters
-v $PWD/logs:/logs -e LOGGING_FILE=/logs/alfred.log
will log to ./logs/alfred.log
on the host.
When running the application through a reverse proxy, make sure to enable streaming. This will allow for server-sent events to push updates during a library scan. Otherwise, there would be no feedback until the scan is complete.
To enable streaming in lighttpd, use the server.stream-response-body
option.
To run the entire test suite, install Docker and run:
docker-compose -f .docker-compose.test.yml up --build --abort-on-container-exit
This will:
- Install all dependencies
- Install Java 17
- Install Chrome
- Install Node.js
- Build and test the backend
- Run Checkstyle
- Run PMD
- Run Spotbugs
- Run JUnit unit & integration tests
- Build and test the frontend
- Run ESLint
- Run Jasmine unit tests
- Run end-to-end tests
- Build the both the front- and the backend into one Spring Boot application
- Start a MongoDB instance
- Run the Spring Boot application
- Execute Protractor end-to-end tests
These steps are also executed as part of the GitHub Actions workflow.
End-to-end tests run against a real application instance. The test runner will drop the specified MongoDB before each test scenario and fill it with configuration seed data.
These steps illustrate how to manually run end-to-end tests.
Start a test instance
docker pull mongo:4.2
docker run -d --name mongo mongo:4.2
./gradlew clean build -x check
java -jar build/libs/alfred.jar --spring.profiles.active=test --spring.data.mongodb.uri=mongodb://localhost/alfred
Switch to UI and install dependencies:
cd ui && npm i
Run via the ng-cli wrapper:
npm run e2e -- --base-url=http://localhost:8080/ --dev-server-target=
or directly via protractor, skipping webdriver update:
npm run protractor
There is also a headless version:
npm run protractorHeadless
In order to debug, add a debugger;
next to the statement you want to debug and then run the protractor config manually through node. Example for debugging library.e2e-spec.ts
:
node --inspect-brk node_modules/protractor/bin/protractor e2e/protractor.conf.js --specs=e2e/src/library.e2e-spec.ts