If a book is part of multiple series, this patch adds a separator
between the series on the library item details page. With no separator,
it is not immediately clear that they are separate series.
The logger should include a source containing the location where the
logger was called. This works well for logging to `stdout`. Unfortunately,
the file logs contain the locations where the file logging is called
inside of the logger. This is not helpful:
```
{"timestamp":"2023-11-19 16:35:43","source":"Logger.js:114","message":"[oldDbFiles] Processed db data file with 1 entities","levelName":"INFO","level":2}
{"timestamp":"2023-11-19 16:35:43","source":"Logger.js:114","message":"[oldDbFiles] Finished loading db data with 2 entities","levelName":"INFO","level":2}
{"timestamp":"2023-11-19 16:35:43","source":"Logger.js:114","message":"[oldDbFiles] 2 settings loaded","levelName":"INFO","level":2}
```
This patch fixes the issue, ensureing that the actual source location
will be logged:
```
{"timestamp":"2024-02-29 18:12:59.832","source":"DailyLog.js:132","message":"[DailyLog] 2024-02-29: Loaded 20 Logs","levelName":"DEBUG","level":1}
{"timestamp":"2024-02-29 18:12:59.638","source":"Server.js:172","message":"=== Starting Server ===","levelName":"INFO","level":2}
{"timestamp":"2024-02-29 18:12:59.638","source":"Server.js:103","message":"[Server] Init v2.8.0","levelName":"INFO","level":2}
```
This patch ensures that files names like `series #3 xy.jpg` are actually
handled correctly instead of the part after `#` being interpreted as
fragment and being discarded.
I noticed that in a few rare cases the App wouldn't properly display
cover images. It turns out that due the file names containing a `#`, the
file path got corrupted, causing Audiobookshelf to return a 403.
This patch allows users to enable dev logs on production systems by
setting the `HIDE_DEV_LOGS` environment variable.
Before, you could only use this on a non-production environment. On
production, the logs would be disabled. This patch changes the behavior
and uses the `NODE_ENV` only as default. On production they are disabled
if `HIDE_DEV_LOGS` is undefined but can be enabled by setting
`HIDE_DEV_LOGS=0` on dev, they are enabled if undefined, but can be
disabled by setting `HIDE_DEV_LOGS=1`.
This patch adds milliseconds to the time string used for logging. This
helps when debugging some timing issues and should have no real negative
side effect.
This patch adds a minimal integration test building Audiobookshelf as a
binary, running it and checking if the server is available on each push
and pull request.
We can easily extend this with a Selenium or Playwright test later, but
it should already alert us about problems in the build pipeline without
the need for any developer to take a look at the new patches.
This patch updates the default value of the home page bookshelf view so
that it is identical to the default library view. Having different
styles by default seems odd. I picked the non-wooden view as default
based on the recent discussion on Matrx/Discord that that one looks more
modern.
This patch implements [X-Accel](https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/)
redirect headers as an optional way for offloading static file delivery
from Express to Nginx, which is far better optimized for static file
delivery.
This provides a really easy to configure way for getting a huge
performance boost over delivering all files through Audiobookshelf.
How it works
------------
The way this works is basically that Audiobookshelf gets an HTTP request
for delivering a static file (let's say an audiobook). It will first
check the user is authorized and then convert the API path to a local
file path.
Now, instead of reading and delivering the file, Audiobookshelf will
return just the HTTP header with an additional `X-Accel-Redirect`
pointing to the file location on the file syste.
This header is picked up by Nginx which will then deliver the file.
Configuration
-------------
The configuration for this is very simple. You need to run Nginx as
reverse proxy and it must have access to your Audiobookshelf data
folder.
You then configure Audiobookshelf to use X-Accel by setting
`USE_X_ACCEL=/protected`. The path is the internal redirect path used by
Nginx.
In the Nginx configuration you then configure this location and map it
to the storage area to serve like this:
```
location /protected/ {
internal;
alias /;
}
```
That's all.
Impact
------
I just did a very simple performance test, downloading a 1170620819
bytes large audiobook file from another machine on the same network
like this, using `time -p` to measure how log the process took:
```sh
URL='https://url to audiobook…'
for i in `seq 1 50`
do
echo "$i"
curl -s -o /dev/null "${URL}"
done
```
This sequential test with 50 iterations and without x-accel resulted in:
```
real 413.42
user 197.11
sys 82.04
```
That is an average download speed of about 1080 MBit/s.
With X-Accel enabled, serving the files through Nginx, the same test
yielded the following results:
```
real 200.37
user 86.95
sys 29.79
```
That is an average download speed of about 2229 MBit/s, more than
doubling the previous speed.
I have also run the same test with 4 parallel processes and 25 downloads
each. Without x-accel, that test resulted in:
```
real 364.89
user 273.09
sys 112.75
```
That is an average speed of about 2448 MBit/s.
With X-Accel enabled, the parallel test also shows a significant
speedup:
```
real 167.19
user 195.62
sys 78.61
```
That is an average speed of about 5342 MBit/s.
While doing that, I also peaked at the system load which was a bit lower
when using X-Accel. Even though the system was delivering far more data.
But I just looked at the `load1` values and did not build a proper test
for that. That means, I cant provide any definitive data.
Supported Media
---------------
The current implementation works for audio files and book covers. There
are other media files which would benefit from this mechanism like feed
covers or author pictures.
But that's something for a future developer ;-)
This patch slightly changes the behavior of the `AUDIOBOOKSHELF_UID` and
`AUDIOBOOKSHELF_GID` options. Instead of defining a default user and
group, trying to modify files and silently failing if the filesystem
mode cannot be changed, this patch will just skip the entire process in
the first place.
If these options are defined, Audiobookshelf should behave exactly as
before. If they are not defined, Audiobookshelf will now cause fewer
file modifications (or less failures when trying to modify files).
If this patch gets applied, it should probably be highlighted in the
release notes. This usually shouldn't cause problems for migrations
since the Docker guides explicitly configure the options and the
package installations do not seem to use this at all, but there is still
a change that it will and users should be aware of that.
If a problem arises, users can easily fix the problem by either setting
the permissions once manually to the audiobookshelf user or by simply
defining the `AUDIOBOOKSHELF_UID/GID` options.
This patch tries to make sure that defaults and options work in the same
way regardless of users using Docker or a package deployment.
- Commit 10295b0 updated `Host` to be empty by default to better support
IPv6. This fixes a missed occurrence of the old default.
- This makes sure the `SOURCE` environment variable is honored when
installing the packages. The `--source` option will still take
precedence though.
Sometimes, a book belongs to more than one series. If you listen to and
finish such a book, Audiobookshelf will list the next book in “Continue
Series” twice, right next to each other. That is not helpful.
This patch fixes the problem by not adding books to the list if they are
already in the list.
This patch fixes the problem that toggling one of the options in the
user account dialog will automatically submit the form.
The problem got introduced as a combination of the recent accessibility
fixes where some elements got turned into HTML button elements to make
them keyboard accessible. Doing that, I did not realize that the default
type of a button is `submit` [1]. This causes no problems at most places,
but will cause problem within a form (e.g. the user account settings)
where toggling an option is now identical to clicking submit.
This patch fixes the issue by setting the `type` attribute to `button`.
Not only for the toggle switch, but also for a few other elements which
have been recently converted to buttons.
[1] https://www.w3.org/TR/2011/WD-html5-20110525/the-button-element.html#attr-button-type
This patch changes the books displayed in “Continue Series”, avoiding
books if another book from the series is played back right now. This
prevents Audiobookshelf suggesting books to which users will not listen
to because they are still listening to the last one.
Once a book is finished, the next book in the series will pop still be
suggested to the user.
This fixes #1382
This patch updates the Gentium Book Basic font file [1]. While I
couldn't get any client to use the previous file, it doesn't seem to be
a problem with this file and now the text is being rendered correctly.
[1] https://gwfh.mranftl.com/fonts/gentium-book-basic?subsets=latin
The Audiobookshelf logs sometimes contain information about the source
of the log statement, but sometimes they don't This really depends on
developers adding these information to the log messages.
But even then, the information is usually just a hint about the module
logging this, like `[Db]` or [Watcher]`, and finding the exact line can
be hard.
This patch automatically adds the source of the log statement to the
logs. This means if someone calls `Logger.info(…)` in line `22` of
`foo.js`, the log statement will contain this file and line:
```
[2023-01-05 19:04:12[ (LogManager.js:85:18) DEBUG: Daily Log file found 2023-01-05.txt
[2023-01-05 19:04:12] (LogManager.js:59:12) INFO: [LogManager] Init current daily log filename: 2023-01-05.txt
```
This should make it much easier to identify the code where the log
statement originated from.
Long-term, this also means that we can probably remove the manually set
identifiers contained in the log messages, like the `[LogManager]` in
the example above.
This patch fixes several problems of the settings menu related to
display on mobile devices or small(ish) windows:
- The `isMobileLandscape` is now calculated correctly. Previously, this
was set to `true` if a device was in portrait mode.
- Showing the button to collapse the settings menu and making the menu
collapsible now use the same mechanism. Previously, it could happen
that the menu was opened and not fixed, but no button to close it
again was shown.
- The icons fore opening and closing the settings menu are now both
arrows, indicating that their functionality is reversed.
- The button to open the menu now always has the string “Settings”,
instead of using the name of the current page. The current page hader
is listed below that anyway and this is the action component to open
the settings menu after all.
This fixes#1334
This patch fixes some accessibility problems on the main settings page.
Most notably, it makes sure that the different options have labels which
are picked up by screen readers.
As a more generic addition, this also makes sure that the dropdown
component will always have a proper label constructed, explaining what
the dropdown is for and what its current value is.
This patch makes sure that the option in the user settings are
accessible via keyboard navigation and that the labels, if users use a
screen reader, actually make sense.
This patch introduces new strings which need to be translated. Although
I did already provide a German translation.
This patch should fix most of the problems for users trying to access
the user settings via screen reader. It makes sure user interface
elements can be reached via keyboard and provides proper labels, roles
and values so you not only can interact with elements but also know what
you are actually changing.
While not focused on other views, this should also already fix a number
of accessibility issues with other settings pages.
This patch fixes the keyboard navigation in the library selection of the
main app bar. Without this patch, no options are selectable via keyboard
and selecting an option and hitting return has no effect.
This patch highlights items in the app bar if a user uses the keyboard
to navigate in audiobookshelf. This ensures that users actually know
which item they have selected.
This also modifies the text for the library selector, so that users
which are using a screen reader understand that it is a selector for
libraries and not only a button related to the current library.
This patch adds the missing alt attribute to the image linking the home
page of audiobookshelf. This allows screen readers to explain to users
where this link leads to.
Assigning something to `process.env.profile`, Node stringifies the value. This
means that assigning `undefined` to an environment variable in Node will result
in it holding the string `undefined`.
This means, for example, that `module.exports.FFPROBE_PATH || 'ffprobe'` in
`server/libs/nodeFfprobe/index.js` will actually result in the string
`undefined`.
This patch fixes several such assignments in the `index.js`, potentially
causing problems in the development mode.
If the scanner detects new files with a path containing part of the name
of an already existing library item, the new item will incorrectly be
detected as being a parent directory of the already existing item and
the import will be aborted.
You can follow these steps to reproduce the issue:
```
❯ mkdir audiobooks/author/
❯ mv title\ 10 audiobooks/author
[2022-12-18 22:14:12] DEBUG: [Watcher] File Added /home/lars/dev/audiobookshelf/audiobooks/author/title 10/dictaphone.mp3
[2022-12-18 22:14:16] DEBUG: [DB] Library Items inserted 1
❯ mv title\ 1 audiobooks/author
[2022-12-18 22:15:03] DEBUG: [Watcher] File Added /home/lars/dev/audiobookshelf/audiobooks/author/title 1/dictaphone.mp3
[2022-12-18 22:15:07] WARN: [Scanner] Files were modified in a parent directory of a library item "title 10" - ignoring
```
Since `'title 10'.startsWith('title 1')` is `true`, the current code
makes this false assumption.
This patch fixes the issue by requiring a path separator to be part of
the matching path. This should ensure that only true parent directories
are detected.
This patch requires audiobookshelf to always use Unix file separators.
But that shouldn't be a problem since audiobookshelf always seems to use
these kinds of separators. Even on Windows.
The API for Google Books will return HTTP image URLs when matiching any
books using it as a search provider. In a secure environment, this
causes browser warnings.
All Google image links support HTTPS and we can safely switch to HTTOS
to avoid these warnings.
This patch removes `PermissionsStartOnly=true` from the systemd unit
file used for packaging. This shouldn't be necessary for any commands
run by the unit.
If no progress had been set before, setting `startedAt` did not work and
it would always been set to `finishedAt` or `Date.now()`. Settings this
if any progress had already been recorded did work.
This fixes the problem so that setting `startedAt` it properly works in
both cases.
This patch updates the batch progress update endpoint to respond with a
`400 Bad Request` instead of a `500 Internal Server Error` if a user
sends an invalid request with no body. This is a user error after all.
```
❯ curl -i -X PATCH \
'http://127.0.0.1:3333/api/me/progress/batch/update' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5Q_MoRptP0oI' \
-H 'Content-Type: application/json'
HTTP/1.1 400 Bad Request
…
Missing request payload
```
This patch is a minor extension to the update progress and batch update
progress API and allows you to specify `finishedAt` and `startedAt` when
updating a progress.
If not specified, both values are still automatically set to the current
time. If just `finishedAt` is specified, `startedAt` is set to the same
value.
Example API request:
```
❯ curl -i -X PATCH \
'http://127.0.0.1:3333/api/me/progress/li_ywupqxw5d22adcadpa' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJyb290IiwidXNlcm5hbWUiOiJyb290IiwiaWF0IjoxNjY4OTYxNjAxfQ._NbilCoFy_hfoqy7uvbV4E_0X6qgLYapQ_MoRptP0oI' \
-H 'Content-Type: application/json' \
--data-raw '{"isFinished":true, "finishedAt": 1668556852000, "startedAt": 1668056852000}'
```
This patch drops the log level for logging requests to non-existing
feeds from error to debug. The reasoning behind this is that this is a
client error and a client error is returned and can be handled by the
client.
Otherwise anyone can easily spam the logs with error messages by just
requesting non-existing feeds.
If you are on the home page and open the edit author modal, you can
automatically update all data by clicking “Quick Match” or you can
remove a set image by clicking 🗑.
Both options will update the actual data, but not the data in the open
modal. This means that, for example, a picture is still shown in the
modal after deleting it. That's confusing.
This patch fixes the bug and makes sure the modal is updated if the data
is updated.
When using accessibility tools like screen magnifiers, dynamic screen
content can be quite problematic. In particular content, which only
appears if you interact with elements somewhere else on the screen. That
is the case, for example, with the current implementation of tooltips
used by audiobookshelf.
This patch provides a slight adjustment, keeping the tooltips open if
you hover over them. This allows users to have better access to the
content.
Starting to use audiobookshelf, the function of some buttons weren't
very clear to me and while some buttons have tooltips, others have not.
This patch adds some additional tooltips to the user interface,
further explaining some of the functionality.