Skip to main content

Barkr

Barkr1 is a social media cross-posting tool written in Python: set it up and never worry about manually posting the same message to multiple channels ever again!

With Barkr you can setup a series of channels (e.g. social media accounts) to read messages from and / or post messages to. You can mix and match read / write modes, and add multiple accounts of the same type of channel as well without worrying that the same message will be re-posted to a channel it comes from.

Note that Barkr is limited to text posts only. Want to see that change? Start a discussion on a new issue!

Motivation

I wrote Barkr for a personal use case after noting how much fragmentation there currently is (as of 2023) in the social media space, as a way to reduce the cost of engaging with multiple social media platforms, and also as a (very simple) way to practice using threads in Python.

Installation

Use the package manager pip to install barkr.

pip install barkr

Usage

Create a Python script and specify all the channels you want to use. Channel connections are present in the barkr.connections module.

A simple script showcasing how to set up three Mastodon connections with multiple modes that can run in the background is outlined below:

from barkr.main import Barkr

from barkr.connections import (
    ConnectionMode,
    BlueskyConnection,
    DiscordConnection,
    MastodonConnection,
    RSSConnection,
    TelegramConnection,
    TwitterConnection,
    WebhookConnection,
)

from barkr.models import Message

barkr = Barkr(
    [
        # Barkr will read new messages posted by this account, and queue them to
        # other accounts on write mode, but will not post anything to it.
        MastodonConnection(
            "Read only connection",
            [ConnectionMode.READ],
            "<ACCESS TOKEN HERE>",
            "<INSTANCE URL HERE>",
        ),
        # Barkr will write queued messages to this account, but will not read anything
        # new posted to this account or queue anything from this account to other ones.
        DiscordConnection(
            "Write only connection",
            [ConnectionMode.WRITE],
            "<BOT TOKEN ID HERE>",
            "<CHANNEL ID HERE>",
        ),
        # Barkr will read new messages from this account to be queued onto others, and will
        # post new messages from other channels into this one as well.
        BlueskyConnection(
            "R/W connection",
            [ConnectionMode.READ, ConnectionMode.WRITE],
            "<BLUESKY HANDLE HERE>",
            "<PASSWORD / APP PASSWORD HERE>",
        ),
        # Another example using Twitter -- note that the TwitterConnection only
        # supports write-only mode through the Twitter V2 API
        TwitterConnection(
            "Write only Twitter Connection",
            [ConnectionMode.WRITE],
            "<CONSUMER KEY HERE>",
            "<CONSUMER SECRET HERE>",
            "<ACCESS KEY HERE>",
            "<ACCESS SECRET HERE>",
            "<BEARER TOKEN HERE>",
        ),
        # One more, showcasing a Telegram write-only connection
        TelegramConnection(
            "Write only Telegram connection",
            [ConnectionMode.WRITE],
            "<TELEGRAM BOT TOKEN HERE>",
            "<TELEGRAM CHAT / CHANNEL ID HERE>",
        ),
        # You can also read from an RSS feed!
        RSSConnection(
            "Read only RSS connection",
            [ConnectionMode.READ],
            "<RSS FEED URL HERE>"
        ),
        # And post messages to a custom webhook as well!
        WebhookConnection(
            "Write only Webhook connection",
            [ConnectionMode.WRITE],
            "<WEBHOOK URL HERE>",
        ),
    ]
)

# Blocking: will start reading and writing threads to keep the connections in sync
barkr.start()

# Non-blocking, if you only need to write messages to your connections
barkr.write_message(
    Message(
        id="123456",
        message="Hello, world!",
    )
)

Always keep in mind proper secret management practices when using Barkr: instead of hardcoding access tokens / cookies / user and passwords, use tools like environment variables, dotenv or other secret managers!

Connection groups

By default, every read-mode connection in a Barkr instance relays messages to every write-mode connection (minus the message's own source, if read-write).

You can optionally assign each connection to a group to create independent pipelines/relays within the same Barkr instance.

Connections only relay messages to other connections that share the same group. The group argument is optional: when omitted, the connection is placed in a default group, i.e. if you don't specify any groups, all messages from read-mode connections will be relayed to all write-mode connections.

Connection names must be unique within a Barkr instance, even across different groups. Duplicate names raise ValueError during initialization. Each destination connection owns its reply mappings; these mappings are not shared between connection objects.

from barkr.main import Barkr
from barkr.connections import ConnectionMode, BlueskyConnection, MastodonConnection

barkr = Barkr(
    [
        # Group "account-1": these two only sync with each other.
        BlueskyConnection(
            "Bluesky account 1",
            [ConnectionMode.READ, ConnectionMode.WRITE],
            "<HANDLE 1>",
            "<PASSWORD 1>",
            group="account-1",
        ),
        MastodonConnection(
            "Mastodon account 1",
            [ConnectionMode.READ, ConnectionMode.WRITE],
            "<ACCESS TOKEN 1>",
            "<INSTANCE URL 1>",
            group="account-1",
        ),
        # Group "account-2": fully isolated from "account-1".
        BlueskyConnection(
            "Bluesky account 2",
            [ConnectionMode.READ, ConnectionMode.WRITE],
            "<HANDLE 2>",
            "<PASSWORD 2>",
            group="account-2",
        ),
        MastodonConnection(
            "Mastodon account 2",
            [ConnectionMode.READ, ConnectionMode.WRITE],
            "<ACCESS TOKEN 2>",
            "<INSTANCE URL 2>",
            group="account-2",
        ),
    ]
)

barkr.start()

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Contributions for issues that are already open by maintainers are welcome and encouraged.

Please make sure to update tests as appropriate; a minimum coverage of 80% is expected (and enforced by Github Actions!).

License

This project is licensed under the GNU Affero General Public License v3.0.

  1. "Barkr" (missing "e") as in "entity that barks". See: dogs. ↩

Metadata

Release files for barkr 0.16.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for barkr 0.16.1
File Size Uploaded Provenance
barkr-0.16.1.tar.gz 43.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for barkr 0.16.1
File Interpreter ABI Platform
barkr-0.16.1-py3-none-any.whl Python 3 none any Details

Total release size: 97.6 kB

Release files / barkr-0.16.1.tar.gz

Download URL barkr-0.16.1.tar.gz
Size 43.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b95cd467ef4154aed3e844dd6fd5d5ffdc93f6090722cd72333e40db0bf76c25
BLAKE2b-256 checksum
How to use checksums
bb59b4a004ab82dd49af1f94e8056e0270cc3472a1efea49b603052fb142afea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / barkr-0.16.1-py3-none-any.whl

Download URL barkr-0.16.1-py3-none-any.whl
Size 54.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ddd409387f953cf5ba63789106c56df5b33abd7983b895e2831006ddaaa9e5b
BLAKE2b-256 checksum
How to use checksums
acdf1f2c8281999da5fb2357396b8bf53c614f8a5070278d3bb7eb635d4f52c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Security for barkr 0.16.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.16.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page