social media crossposting tool. 3rd time's the charm
mastodon misskey crossposting bluesky
1# XPost 2 3XPost is a social media cross-posting tool that differs from others by using streaming APIs to allow instant, zero-input cross-posting. this means you can continue posting on your preferred platform without using special apps. 4 5XPost tries to support as many features as possible. for example, when cross-posting from mastodon to bluesky, unsupported file types will be attached as links. posts with mixed media or too many files will be split and spread across text. 6 7the tool may undergo breaking changes as new features are added, so proceed with caution when deploying. 8 9# Installation 10 11## Native 12 13first install `ffmpeg`, `ffprobe` and `libmagic`, make sure that `ffmpeg` is available on PATH! `ffmpeg` and `libmagic` are required to crosspost media. 14 15then get [uv](https://github.com/astral-sh/uv) and sync the project 16 17``` 18uv sync 19``` 20 21generate settings.json on first launch 22 23``` 24uv run main.py 25``` 26 27## Docker Compose 28 29the official immage is available on [docker hub](https://hub.docker.com/r/melontini/xpost). example `compose.yaml`. this assumes that data dir is `./data`, and env file is `./.config/docker.env`. add `:Z` to volume mounts for podman. 30 31```yaml 32services: 33 xpost: 34 image: melontini/xpost:latest 35 restart: unless-stopped 36 env_file: ./.config/docker.env 37 volumes: 38 - ./data:/app/data 39``` 40 41# Settings 42 43the tool allows you to specify an input and multiple outputs to post to. 44 45some options accept a envvar syntax: 46 47```json 48{ 49 "token": "env:TOKEN" 50} 51``` 52 53## Inputs 54 55all inputs have common options. 56 57```json5 58{ 59 "options": { 60 "regex_filters": [ //posts matching any of the following regexes will be skipped 61 "(?i)\\b(?:test|hello|hi)\\b" 62 ] 63 } 64} 65``` 66 67### Bluesky Jetstream 68 69listens to repo operation events emmited by Jetstream. handle becomes optional if you specify a DID. 70 71```json5 72{ 73 "type": "bluesky-jetstream-wss", 74 "handle": "env:BLUESKY_HANDLE", // handle (e.g. melontini.me) 75 "did": "env:BLUESKY_DID", // use a DID instead of handle (avoids handle resolution) 76 "jetstream": "wss://jetstream2.us-east.bsky.network/subscribe" //optional, change jetstream endpoint 77} 78``` 79 80### Mastodon WebSocket `mastodon-wss` 81 82listens to the user's home timeline for new posts, crossposts only the public/unlisted ones by the user. 83 84```json5 85{ 86 "type": "mastodon-wss", // type 87 "instance": "env:MASTODON_INSTANCE", // mastodon api compatible instance 88 "token": "env:MASTODON_TOKEN", // Must be a mastodon token. get from something like phanpy + webtools. or https://getauth.thms.uk/?client_name=xpost&scopes=read:statuses%20write:statuses%20profile but doesn't work with all software 89 "options": { 90 "allowed_visibility": [ 91 "public", 92 "unlisted" 93 ] 94 } 95} 96``` 97 98any instance implementing `/api/v1/instance`, `/api/v1/accounts/verify_credentials` and `/api/v1/streaming?stream` will work fine. 99 100confirmed supported: 101- Mastodon 102- Iceshrimp.NET 103- Akkoma 104 105confirmed unsupported: 106- Mitra 107- Sharkey 108 109### Misskey WebSocket 110 111listens to the homeTimeline channel for new posts, crossposts only the public/home ones by the user. 112 113**IMPORTANT**: Misskey WSS does Not support deletes, you must delete posts manually. if you know how i can listen to all note events, i would appreciate your help. 114 115```json5 116{ 117 "type": "misskey-wss", // type 118 "instance": "env:MISSKEY_INSTANCE", // misskey instance 119 "token": "env:MISSKEY_TOKEN", // access token with the `View your account information` scope 120 "options": { 121 "allowed_visibility": [ 122 "public", 123 "home" 124 ] 125 } 126} 127``` 128 129Misskey API is not very good, this also wasn't tested on vanilla misskey. 130 131confirmed supported: 132- Sharkey 133 134## Outputs 135 136### Mastodon API 137 138no remarks. 139 140```json5 141{ 142 "type": "mastodon", 143 "token": "env:MASTODON_TOKEN", // Must be a mastodon token. get from something like phanpy + webtools. or https://getauth.thms.uk/?client_name=xpost&scopes=read%20write%20profile but doesn't work with all software 144 "instance": "env:MASTODON_INSTNACE", // mastodon api compatible instance 145 "options": { 146 "visibility": "public" 147 } 148} 149``` 150 151### Bluesky 152 153in the bluesky block, you can configure who is allowed to reply to and quote the new posts. handle becomes optional if you specify a DID. 154 155```json5 156{ 157 "type": "bluesky", // type 158 "handle": "env:BLUESKY_HANDLE", // handle (e.g. melontini.me) 159 "app_password": "env:BLUESKY_APP_PASSWORD", // https://bsky.app/settings/app-passwords 160 "did": "env:BLUESKY_DID", // use a DID instead of handle (avoids handle resolution) 161 "pds": "env:BLUESKY_PDS", // specify Your PDS directly (avoids DID doc lookup) 162 "bsky_appview": "env:BLUESKY_APPVIEW", // bypass suspensions by specifying a different appview (e.g. did:web:bsky.zeppelin.social) 163 "options": { 164 "encode_videos": true, // bluesky only accepts mp4 videos, try to convert if the video is not mp4 165 "quote_gate": false, // block users from quoting the post 166 "thread_gate": [ // block replies. leave empty to disable replies 167 "mentioned", 168 "following", 169 "followers", 170 "everybody" // allow everybody to reply (ignores other options) 171 ] 172 } 173} 174```