Telegram bot that journals private messages into an Obsidian vault
Project description
Telegram Journal Bot
A Telegram bot that journals every private message into your Obsidian daily notes.
Demo
User messages sent in a private chat are captured by the bot, including text and media.
Captured content is appended to your daily note with timestamped entries and structured formatting.
Features
- Private chat journal capture for text, photos, voice recordings, video messages (including circular video notes), and locations
- UTC daily note partitioning at
YYYY/YYYY-MM-DD.md - Media storage (photos, voice, video) in
YYYY/attachments/ - YAML frontmatter management for
mood,tags, andcreated - In-memory state only (
context.chat_dataandcontext.bot_data) - Date override commands (
/setdate,/resetdate) - Tags and mood management with inline keyboard callbacks
Usage
Installation
Choose one installation method:
From PyPI (recommended for end users):
python -m pip install --upgrade telejournal
From source (recommended for contributors):
git clone https://github.com/hugobatista/telejournal.git
cd telejournal
uv sync --extra dev
If running from source, use uv run before commands in the sections below.
Example: uv run telejournal run --verbose.
Quick Start
-
Configure your environment variables as documented in
Environment. -
Start the bot:
telejournal run --verbose
- Open your bot in Telegram and send:
/help
- Send a normal message (for example,
First journal entry) and confirm it appears in:
<VAULT_ROOT>/YYYY/YYYY-MM-DD.md
Run Modes
Use whichever configuration style best fits your setup.
Environment variables only:
telejournal run
YAML configuration file (config.yaml auto-detected if present):
telejournal run
telejournal run /path/to/config.yaml
CLI overrides (highest priority):
telejournal run \
--telegram-token your_token \
--vault-root /path/to/vault \
--allowed-user-ids 123456,987654 \
--message-timestamp-window-seconds 60 \
--secure-file-permissions
Telegram Commands
After the bot is running, these commands are available in your private chat:
/helpShow bot usage summary/setdate YYYY-MM-DD [HH:MM:SS]Set target note date/time/resetdateReturn to current day/tagsShow tag buttons/tags work kidsAdd/select one or more tags/moodOpen mood picker/showShow current effective day note/show YYYY-MM-DDShow a specific day note/deleteDelete last entry and show deleted content/delete day [YYYY-MM-DD]Delete full day note
Helpful CLI Commands
telejournal version
telejournal help
Using secret-tool
If you use Linux secret service (secret-tool), you can skip a local .env
and use secret-tool-run:
secret-tool-run telejournal run
Environment
Create a .env file:
TELEGRAM_TOKEN=your_bot_token
VAULT_ROOT=/path/to/obsidian/vault
LOG_LEVEL=INFO
TELEGRAM_ALLOWED_USER_IDS=123456,987654
Optional Environment Variables
MESSAGE_TIMESTAMP_WINDOW_SECONDS(default:60) - Messages within this window share the same timestampSECURE_FILE_PERMISSIONS(default:true) - Set restrictive permissions (0o700/0o600) on vault directories and files for security. Set tofalseonly if you need broader file access.
Configuration
The bot supports multiple configuration sources with a clear priority order:
Configuration Priority (highest to lowest)
- CLI Arguments - Command-line options override all other sources
- YAML File - Configuration file specified via
configargument - Environment Variables - Settings from
.envfile - Defaults - Built-in defaults for optional settings
Later sources override earlier ones. For example, if you specify --telegram-token on the command line, it will override the TELEGRAM_TOKEN environment variable.
YAML Configuration
You can provide a config.yaml file for more organized configuration management. The bot automatically looks for ./config.yaml if no config path is specified.
Example config.yaml:
telegram_token: "${TELEGRAM_TOKEN}" # Supports environment variable expansion
vault_root: /path/to/obsidian/vault
allowed_user_ids:
- 123456
- 987654
log_level: INFO
message_timestamp_window_seconds: 60
secure_file_permissions: true
Configuration Keys:
telegram_token(required) - Your Telegram bot tokenvault_root(required) - Absolute path to your Obsidian vaultallowed_user_ids(required) - List of Telegram user IDs that can use the botlog_level(optional, default:INFO) - Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)message_timestamp_window_seconds(optional, default:60) - Messages within this window share the same timestampsecure_file_permissions(optional, default:true) - Set restrictive file permissions for security
Environment Variable Expansion:
YAML configuration supports ${VAR_NAME} syntax for environment variable expansion:
telegram_token: "${TELEGRAM_TOKEN}"
vault_root: "${VAULT_ROOT}"
This allows you to keep sensitive values in environment variables while using a configuration file for other settings.
Test
uv run pytest
# With full coverage and type checking
bash validate.sh
Docker
You can run the bot in Docker using either docker run or docker compose.
Using Docker Compose
-
Create a
.env.dockerfile with your bot token and settings:TELEGRAM_TOKEN=your_bot_token VAULT_ROOT=/data LOG_LEVEL=INFO TELEGRAM_ALLOWED_USER_IDS=123456,987654 SECURE_FILE_PERMISSIONS=false # This will avoid permission issues when running as non-root, but use with caution!
-
Create an
obsidian-journaldirectory in the same location as yourdocker-compose.ymlto serve as your vault, and set permissions so the container can write to it:mkdir obsidian-journal chmod 777 obsidian-journal # Use with caution, or set specific user/group permissions as needed
-
Start the container:
docker compose up --build
This will mount your Obsidian vault from ./obsidian-journal to /data inside the container.
On SELinux-enabled Linux distributions (for example Fedora/RHEL), make sure
the bind mount uses :Z in docker-compose.yml:
volumes:
- ./obsidian-journal:/data:Z
Using Docker Run
-
Build the image:
docker build -t telejournal:latest .
-
Run the container:
docker run -d \ --env-file .env.docker \ -v "$PWD"/obsidian-journal:/data:Z \ --name telejournal \ telejournal:latest
This will start the bot in detached mode, using your local .env.docker file and mounting your Obsidian vault.
Note: If you see
pull access denied for telejournal, you must build the image first:docker build -t telejournal:latest .Then run the container as shown above.
For troubleshooting, check logs with:
docker logs telejournal
Signalbackup-Tools HTML Import Utility
A utility is provided to convert HTML exports generated by signalbackup-tools to Obsidian-compatible Markdown, preserving timestamps, attachments, and replies. This is useful for importing Signal chat history into your journal vault.
Usage
python tools/signalbackup-tool-import/html_to_markdown.py <input_html_file> <output_directory>
<input_html_file>: Path to your HTML export from signalbackup-tools (e.g.,html/self.html)<output_directory>: Directory where year folders and markdown files will be created
Example:
python tools/signalbackup-tool-import/html_to_markdown.py html/self.html obsidian-journal
This will create:
- Year folders (e.g.,
2022/,2023/) with daily markdown files - An
attachments/folder in each year for media files
See the script for more details and options.
Running as a Systemd Service
To run the Telegram Journal Bot as a background service on Linux, you can use systemd. This ensures the bot starts on boot and restarts automatically if it fails.
Automated Service File Generation (Recommended)
The install-service command generates the service file automatically with sensible defaults:
telejournal install-service
This will:
- Create the service file at
/etc/systemd/system/telejournal.service - Use your current user account
- Set working directory to
~/obsidian-journal - Use
.envfrom your home directory - Automatically detect the
telejournalexecutable path
You can customize these defaults:
# Use custom paths and user
telejournal install-service \
--user myuser \
--working-directory /obsidian-journal \
--environment-file /telejournal/.env \
--execstart "/home/myuser/.venv/bin/telejournal run"
After running the command, follow the on-screen instructions to enable and start the service.
Manual Service File Creation
Alternatively, you can manually create a service file at /etc/systemd/system/telejournal.service with the following content (adjust paths and user as needed):
[Unit]
Description=Telegram Journal Bot
After=network.target
[Service]
Type=simple
User=youruser
WorkingDirectory=/home/youruser/obsidian-journal
EnvironmentFile=/home/youruser/.env
ExecStart=/home/youruser/.venv/bin/telejournal run
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Configuration details:
User- The user account that will run the bot (should own the vault directory)WorkingDirectory- Your Obsidian vault root directory (where notes are stored)EnvironmentFile- Path to your.envfile with required environment variablesExecStart- Full path to thetelejournalcommand (installed in your virtual environment)RestartSec- Wait 5 seconds before restarting on failure
If you installed telejournal system-wide via pip, you can use just telejournal run without the full path.
Enable and Start the Service
sudo systemctl daemon-reload
sudo systemctl enable telejournal.service
sudo systemctl start telejournal.service
Check logs with:
journalctl -u telejournal.service -f
This will keep the bot running in the background and restart it automatically on failure or reboot.
Project details
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 telejournal-0.0.2.tar.gz.
File metadata
- Download URL: telejournal-0.0.2.tar.gz
- Upload date:
- Size: 391.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e0887cf983a88f2630c21195e63da77e8a7af283fcc2cffff456c73630a432c
|
|
| MD5 |
513d47a3e37b17845fb0ec2442df4f23
|
|
| BLAKE2b-256 |
c34a8a88ab7fac789a6cdd21835a543b9fa89666fb4376f64204e28ad3a1b735
|
Provenance
The following attestation bundles were made for telejournal-0.0.2.tar.gz:
Publisher:
pypi.yml on hugobatista/telejournal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
telejournal-0.0.2.tar.gz -
Subject digest:
3e0887cf983a88f2630c21195e63da77e8a7af283fcc2cffff456c73630a432c - Sigstore transparency entry: 1108444556
- Sigstore integration time:
-
Permalink:
hugobatista/telejournal@213975f8fa2a9e2ea8135e94b22fb103a087398a -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/hugobatista
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@213975f8fa2a9e2ea8135e94b22fb103a087398a -
Trigger Event:
release
-
Statement type:
File details
Details for the file telejournal-0.0.2-py3-none-any.whl.
File metadata
- Download URL: telejournal-0.0.2-py3-none-any.whl
- Upload date:
- Size: 39.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.0.1 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6c99a47858e351700fce370c44b1747c34b0c4ce9ed35cda78a6b42340bf513
|
|
| MD5 |
f97cc741a0cbba0a6e18434e029eabbb
|
|
| BLAKE2b-256 |
94dc060889a572966659127017a1dd98eec93ae9a1fdb6628489c347f4619ecc
|
Provenance
The following attestation bundles were made for telejournal-0.0.2-py3-none-any.whl:
Publisher:
pypi.yml on hugobatista/telejournal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
telejournal-0.0.2-py3-none-any.whl -
Subject digest:
d6c99a47858e351700fce370c44b1747c34b0c4ce9ed35cda78a6b42340bf513 - Sigstore transparency entry: 1108444560
- Sigstore integration time:
-
Permalink:
hugobatista/telejournal@213975f8fa2a9e2ea8135e94b22fb103a087398a -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/hugobatista
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@213975f8fa2a9e2ea8135e94b22fb103a087398a -
Trigger Event:
release
-
Statement type: