visit
Mastodon is free and open-source software for running self-hosted social networking services. It has microblogging features similar to the Twitter service, which are offered by a large number of independently run Mastodon nodes (technically known as instances), each with its own code of conduct, terms of service, privacy options, and moderation policies.
Each user is a member of a specific Mastodon instance (also called a server), which can interoperate as a federated social network, allowing users on different nodes to interact with each other. This is intended to give users the flexibility to select a server whose policies they prefer, but keep access to a larger social network. Mastodon is also part of the Fediverse ensemble of server platforms, which use shared protocols allowing users to also interact with users on other compatible platforms, such as PeerTube and Friendica.
—
One of the main things I wanted to do with Mastodon was to replicate my twitter feed there, so that folks who would rather follow me on Mastodon could get everything. To do this, I used moa.party. You have to give it credentials to access both your Twitter and Mastodon feeds, which is a little worrisome, but my Mastodon-aware colleagues have used it without problems.
This tool synchronizes posts from Mastodon to Twitter and back. It does not matter where you post your stuff — it will get synchronized to the other!
—
The has no tags, save latest
, and I had some issues mapping volumes.
name: Sync Twitter to and from Mastodon
on:
schedule:
- cron: "24 */2 * * *" #1
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Check out the synchronization code #2
uses: actions/checkout@v3
with:
repository: klausi/mastodon-twitter-sync
- name: Install Rust #3
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal #4
- name: Execute synchronization #5
uses: actions-rs/cargo@v1
with:
command: run
args: --release
The toolchain comes in different flavors called . For scripting, minimal
is enough, providing only rustc
, rust-std
, and cargo.
Spoiler: the workflow doesn’t work. By default, the code runs interactively: it will ask for credentials to connect to both Twitter and Mastodon. Alternatively, the project accepts a configuration file containing all data — mastodon-twitter-sync.toml
.
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Install GPG to decrypt the configuration file
run: sudo apt-get update && sudo apt-get install -y gnupg
- name: Decrypt the configuration file
run: gpg --quiet --batch --yes --decrypt --passphrase="$GPG_PASSPHRASE" --decrypt mastodon-twitter-sync.toml.gpg > mastodon-twitter-sync.toml
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
At this point, we have mixed the Rust source code with our configuration file in the same Git repository. Handling such a project involves a lot of git rebase
, which I want to avoid. Let's keep the code separate with its dedicated lifecycle locally.
mastodon-twitter-sync-job #1
|_ .github
| |_ workflows
| |_ sync.yml #2
|_ mastodon-twitter-sync.toml.gpg #3
mastodon-twitter-sync #4
|_ src
|_ ...
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Check out the repo itself
uses: actions/checkout@v3
with:
path: job
- name: Check out the synchronization code
uses: actions/checkout@v3
with:
repository: klausi/mastodon-twitter-sync
path: code
|_ job
| |_ .github
| | |_ workflows
| | |_ sync.yml
| |_ mastodon-twitter-sync.toml.gpg
|
|_ code
| |_ src
| |_ ...
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Decrypt the configuration file
run: |
gpg --quiet --batch --yes --decrypt --passphrase="$GPG_PASSPHRASE"
--decrypt job/mastodon-twitter-sync.toml.gpg > mastodon-twitter-sync.toml #1
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
- name: Execute synchronization
uses: actions-rs/cargo@v1
with:
command: run
args: --manifest-path=./code/Cargo.toml --release #2
Decrypt from the job
subfolder in the current root folder.
Run in the current folder using the code
subfolder.
The project creates a post_cache.json
file that contains all previously synced content to avoid duplicating the same content during each execution. We need to take it into account:
jobs:
sync:
runs-on: ubuntu-latest
- name: Update post cache
run: >
cp ./post_cache.json ./job/ 2>/dev/null || : #1
- name: Commit and push post cache
uses: EndBug/add-and-commit@v7 #2
with:
cwd: './job'
add: post_cache.json
default_author: github_actions
message: Update post cache
Copy the post_cache.json
in the job
subfolder. Only succeed the step if the job synchronizes no content, and the file is generated.
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
- name: Cache executable #1
uses: Swatinem/rust-cache@v2
with:
workspaces: code #2
Cache artifacts located in the code
subfolder
Error connecting to Mastodon: Http(
reqwest::Error {
kind: Request,
url: Url {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"mastodon.top",
),
),
port: None,
path: "//api/v1/accounts/verify_credentials",
query: None,
fragment: None,
},
source: TimedOut,
},
)
It’s not an issue per se; it just means that synchronization lags. Should I move to a more reliable instance or even host my own?
To go further:
Originally published at on December 11th, 2022