Skip to content

Commit 0741388

Browse files
authored
Merge pull request #36 from pganssle/update_docs
Redo the README.rst
2 parents c2ba9a2 + c759018 commit 0741388

File tree

8 files changed

+112
-27
lines changed

8 files changed

+112
-27
lines changed

MANIFEST.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
include LICENSE *.rst *.toml *.yml *.yaml *.ini
2+
global-exclude *.pyc
3+
global-exclude *.pyo
4+
global-exclude *.pyd
25
recursive-include licenses *
36
graft .github
47

@@ -9,9 +12,12 @@ recursive-include src *.pyi
912
# Tests
1013
include tox.ini
1114
recursive-include tests *.py
15+
recursive-include tests/data *.*
1216

1317
# Documentation
1418
recursive-include docs *.png
19+
recursive-include docs *.jpg
20+
recursive-include docs *.jpeg
1521
recursive-include docs *.svg
1622
recursive-include docs *.py
1723
recursive-include docs *.rst

README.rst

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,71 @@
11
``audio-feeder`` is a Flask-based web-app that hosts your audiobooks (or other audio content) as RSS feeds compatible with podcatchers.
22

3-
Installation
4-
============
5-
Currently, there is no installer that will install things "correctly", so you should look into the proper way to deploy this web app. In 'development mode', you can install it using these steps:
3+
Features
4+
========
5+
6+
.. image:: docs/images/screenshots/list_entry_p0.jpg
7+
:width: 800px
8+
:alt: The main list interface
9+
10+
The main interface lists all your audiobooks once the database is updated (either by using ``audio-feeder update`` or by visiting the ``/update`` url. The default interface should also work well on mobile:
11+
12+
.. image:: docs/images/screenshots/list_mobile.jpg
13+
:width: 400px
14+
:alt: The mobile list interface
15+
16+
Rendered feeds
17+
**************
18+
For each entry, ``audio-feeder`` can also generate "rendered" feeds, depending on what metadata is available:
19+
20+
- Single file: This feed consists of a single file; if the original directory contains multiple files, they will be merged together using ``ffmpeg``. If chapter information is not available in the original files, each file will be considered a separate "chapter".
21+
22+
- Chapters: This feed has one file per chapter; it is only available if explicit chapter metadata is available in the file (e.g. in an ``m4b`` file, or using Overdrive MediaMarkers).
23+
24+
- Segmented: This is a feed that splits up and recombines files in such a way as to create files that are ~1 hour long (preferring longer files to shorter files). Files will only be split up along chapter boundaries, but they can be combined from files without chapter information. This mode is available if the original entry has more than one file, or if it has chapter information (or both).
25+
26+
QR Codes
27+
********
28+
29+
Each feed has an associated QR code, so that you can easily browse the list from a computer, but scan the individual feeds from your phone. In the default front-end, QR codes are displayed via modal pop-ups:
30+
31+
32+
.. image:: docs/images/screenshots/list_p0_qr.jpg
33+
:width: 800px
34+
:alt: Demonstration of the QR code mobile.
635

7-
- Download the source code, ``cd`` into the extracted directory.
8-
- In your virtualenv, run ``pip install .``
9-
- Run ``audio-feeder install`` - this should create a basic ``{{CONFIG}}`` directory in ``/etc/audio_feeder`` or ``~/.config/audio_feeder``
10-
- Modify the configuration files in ``{{CONFIG}}/config.yml`` as desired.
11-
- Modify the templates and CSS files as desired.
12-
- Create a symbolic link to your audiobooks directory under ``{{CONFIG}}/static/media/`` (e.g. ``~/.config/audio_feeder/static/media/audiobooks``) - we'll call this ``{{AUDIOBOOKS}}``.
13-
- Run ``audio-feeder update {{AUDIOBOOKS}}`` to pull metadata from Google Books (for a large number of audiobooks, you may need to get a `Google API key <https://developers.google.com/maps/documentation/javascript/get-api-key>`_, which should be entered in your ``config.yml`` page under ``google_api_key``).
14-
- Run the server with ``audio-feeder run``
15-
- Visit your page at ``localhost:9090`` (default value). *Note:* You should specify your computer's specific IP address if you are planning on serving your audiobooks directly to a phone or device over wifi.
1636

17-
If you add more audiobooks to your audiobook path, run ``audio-feeder update {{AUDIOBOOKS}}`` again and restart the application.
37+
Display options
38+
***************
39+
40+
The user can customize things like the sort order and the number of entries per page:
41+
42+
.. image:: docs/images/screenshots/settings_pulldown.jpg
43+
:width: 800px
44+
:alt: Demonstration of the settings pulldown
45+
46+
47+
Installation and use
48+
====================
49+
50+
Probably the easiest way to deploy this is via docker. For your convenience, I have created `a repository with a docker-compose configuration <https://github.com/pganssle/audio_feeder_docker>`_. It uses ``nginx`` to serve static media files, and ``gunicorn`` to deploy the application.
51+
52+
If you want to test it out locally, you can use ``tox -e start_server`` to run a test server. This will create a temporary server directory at ``/tmp/audio_feeder_server``, and you can play around with, and you can mount your audiobook directory at ``/tmp/audio_feeder_server/static/media`` to have it work on your own audiobooks (bind mount, symlink or hard link should work just fine).
53+
54+
In a ``virtualenv`` with ``audio-feeder`` installed, you can run ``audio-feeder --help`` to see the various command line tools bundled with the application.
55+
1856

1957
Note
2058
=====
21-
Version 0.1.0 is a very rough initial cut, and if you're looking for something easy to use out of the box, you may have to wait a bit longer. The odd choice of using YAML files as a pseudo-database is *not* intended to be permanent, and these will be replaced with a proper database soon.
59+
60+
While the state of this is getting much closer to something production-ready, I am emphatically *not* a front-end developer, and I don't have extremely high confidence in the security of this project. Use at your own risk (and if you do come up with some security and/or usability improvements, please do send a PR).
61+
62+
This is only tested on Linux, but it may also work on other platforms.
2263

2364
Dependencies
2465
============
25-
The following dependencies are required for installation, and will be installed if missing when installed through `pip`:
26-
27-
- ``Flask``
28-
- ``ruamel.yaml``
29-
- ``qrcode``
30-
- ``Pillow``
31-
- ``requests``
32-
- ``jinja2``
33-
- ``click``
34-
- ``progressbar2``
35-
36-
To run the test suite, ``pytest`` is also required.
66+
67+
In addition to the python dependencies specified in ``pyproject.toml``, this project also requires installing ``ffmpeg`` with at least the ``aac`` codec, and the tests also require the ``libmp3lame`` codec.
68+
3769

3870
License
3971
=======
96.9 KB
Loading
55.9 KB
Loading
84.4 KB
Loading
47.9 KB
Loading

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ authors = [{name = "Paul Ganssle"}]
1111
description = """
1212
audio-feeder provides a server that serves your audiobooks and other audio
1313
content as RSS feeds, with rich metadata, and provides a web frontent for navigation."""
14-
readme = "README.rst"
1514
license = {file = "LICENSE"}
1615
requires-python = ">= 3.9"
1716
dependencies = [
@@ -39,6 +38,7 @@ classifiers = [
3938
"Programming Language :: Python :: 3",
4039
"Programming Language :: Python :: 3.9",
4140
"Programming Language :: Python :: 3.10",
41+
"Programming Language :: Python :: 3.11",
4242
]
4343
dynamic = ["version"]
4444

setup.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import itertools
2+
import pathlib
3+
import re
4+
import typing
5+
6+
from setuptools import setup
7+
8+
ROOT: typing.Final[pathlib.Path] = pathlib.Path(__file__).parent
9+
10+
11+
def strip_images(rst_file: pathlib.Path) -> str:
12+
pattern = re.compile(r"(?P<whitespace>\s*).. image:: (?P<path>.*)$")
13+
text = rst_file.read_text()
14+
lines = text.split("\n")
15+
lines_out = []
16+
in_block = False
17+
indent = None
18+
for line in lines:
19+
if pattern.match(line):
20+
in_block = True
21+
continue
22+
else:
23+
if in_block:
24+
prefix_m = re.match("\s+", line)
25+
if not prefix_m or (
26+
(indent is not None) and indent != line[slice(*prefix_m.span())]
27+
):
28+
in_block = False
29+
indent = None
30+
else:
31+
if indent is None:
32+
indent = line[slice(*prefix_m.span())]
33+
continue
34+
35+
lines_out.append(line)
36+
37+
lines_with_newlines = itertools.groupby(lines_out, key=bool)
38+
lines_with_collapsed_newlines = (
39+
grp if has_contents else ("",) for has_contents, grp in lines_with_newlines
40+
)
41+
return "\n".join(itertools.chain.from_iterable(lines_with_collapsed_newlines))
42+
43+
44+
setup(
45+
long_description=strip_images(ROOT / "README.rst"),
46+
long_description_content_type="text/x-rst",
47+
)

0 commit comments

Comments
 (0)