Serializes classic literature to Mastodon
Project description
Chapter by Chapter
A Python bot that serializes classic literature to Mastodon, posting one chapter at a time in a daily schedule.
Overview
Chapter by Chapter is a Mastodon bot built as a plug for the robotooter framework. It takes classic literature from Project Gutenberg and posts it chapter by chapter to social media. The bot processes text files, extracts chapters, and creates engaging daily posts with customizable templates.
Features
- Automated Chapter Processing: Converts full books into individual chapters with metadata
- Customizable Templates: Flexible templating system for post formatting
- Daily Scheduling: Posts chapters on a configurable schedule
- Project Gutenberg Integration: Direct support for Project Gutenberg text files
- Rich Content Creation: Generates engaging introductions and endings.
- Mastodon Integration: Built on robotooter for reliable social media posting
Examples
- Chapter By Chapter] The reason I created this. Posts a chapter a day from Public Domain litereature. Victorian-era Netflix.
Installation
Prerequisites
- Python 3.12+
- RoboTooter 0.2.2
- Poetry for dependency management
Setup
- Clone the repository:
git clone <repository-url>
cd chapter-by-chapter
- Install dependencies:
just init
# or manually: poetry install
Usage
Setting up a Book
To configure a new book for serialization:
robotooter -b <botname> setup --book KEY --file PATH
# or
robotooter -b <botname> setup --book KEY --url URL
KEYwill be how you refer to the book, and will also be the directory name for its files.- So, for example, for A Study in Scarlet I used
a_study_in_scarletbut you can use anything.
- So, for example, for A Study in Scarlet I used
PATHA local file path to a Project Gutenberg text fileURLA URL to download a text file
Example:
robotooter -b my_literature_bot setup -f /path/to/book.txt -bk "scarlet"
robotooter -b my_literature_bot setup -u "https://gutenberg.org/files/244/244.txt" -bk "study"
Setting the Book
This bot is mean to do most things automatically. So you have to tell it which book to post.
Examples:
# Defaults to chapter 1
robotooter --book a_study_in_scarlet
# You can set a specific chapter to start from, if you want
robotooter --book a_study_in_scarlet --chapter 2
Posting Content
After you've told it which book to use, it will post the next chapter automatically.
robotooter -b <botname> toot
If you run the command again, it will post the next chapter.
Development
Code Quality
Run linting and type checking:
just lint # Run ruff linter with auto-fix
just type # Run mypy type checker
just build # Run both lint and type checks, then build
Testing
Run the test suite:
poetry run pytest
Project Structure
src/chapter_by_chapter/
bot.py # Main bot implementation
content_creator.py # Content generation and templating
greeter.py # User interaction handling
models.py # Data models and configuration
processor.py # Text processing and chapter extraction
util.py # Utility functions
resources/
templates/ # Post templates
word_choices.json
Configuration
The bot uses a configuration system based on robotooter's BotConfig. Key configuration options include:
- Book Processing: Chapter extraction settings
- Content Templates: Customizable post formatting
- Scheduling: Daily posting configuration
- Social Media: Mastodon API credentials
Templates
The bot includes several customizable templates. When you create a new both they are copied to the bot's resources directory. So, if you create "chapter_bot" you will find the templates in <robotooter_root>/chapter_bot/resources/templates/:
chapter_text.txt- Main chapter content formatbook_intro/- Book introduction variationsdaily_intro/- Daily post introductionsbook_ending/- Book conclusion formatschapter_spoiler.txt- Spoiler warning template
The templates use jinja2 as the template engine.
When a specific template is called for, it will first to see if there is a template directory that matches. If so, it will randomly pick one of the files in the directoy as the template to use. This allows for some variety.
If there is not a directory that matches, it will look for "{template_name}.txt".
So, as an example, if you try to render the template book_intro, out of the box it will look in the templates/book_intro directory and pick a template. If you want to always use the same template, remove the directory and create templates/book_intro.txt.
Contributing
If you would like to add features, please feel free. If you use this yourself, please let me know!
License
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for details.
The AGPL-3.0 is a copyleft license that requires anyone who distributes the code or runs it on a server to make the source code available under the same license terms.
Author
Bryan L. Fordham bfordham@naughtybaptist.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chapter_by_chapter-0.1.0.tar.gz.
File metadata
- Download URL: chapter_by_chapter-0.1.0.tar.gz
- Upload date:
- Size: 31.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc795690c0b4913ecd652dc9ec95503375f267b237b6a12b62654265a0090fb1
|
|
| MD5 |
e5f5439d9af2de2d9b7f55a993964f32
|
|
| BLAKE2b-256 |
a4352c2269fc2bd96e6574de5231594b3b24dd539957028939d51f98d3d5c37c
|
File details
Details for the file chapter_by_chapter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: chapter_by_chapter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 39.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca20eb645f092a5951dc7df9ecebff3700f1d64bf6c02e4f9575f5336c5ec278
|
|
| MD5 |
c93cef661334872de61a8f5ccbbdcbea
|
|
| BLAKE2b-256 |
ece1f4dea94806f38c2aa1e6ef17011aeae3c2e71a33de85e158f8cbdfa7ab4a
|