Not my ex#
Tiny app to post simultaneously to Mastodon and Bluesky.
Obviously, based on cuducos/from-my-ex.
It supports:
- Post status updates to both networks with a simple CLI command
- Posting with images
- Including alt text for images
- Setting post language
It does not support:
- Tagging other users (they would have different IDs and servers in each platform)
It used to have:
- A simple GUI (version 0.1.1), but dropped support to focus on CLI — there are other great GUI out there by now
Getting started#
Requirements#
- Go 1.26+
Optionally, you can set some environment variables, but you don't have to.
Environment variables#
General settings#
| Name | Description | Example | Default value |
|---|---|---|---|
NOT_MY_EX_DEFAULT_LANG |
2-letter ISO 639-1 code | "pt" |
None |
To post to Bluesky#
| Name | Description | Example | Default value |
|---|---|---|---|
NOT_MY_EX_BSKY_AGENT |
Bluesky instance | "https://bsky.social" |
"https://bsky.social" |
NOT_MY_EX_BSKY_EMAIL |
Email used in Bluesky | "cuducos@mailinator.com" |
None |
NOT_MY_EX_BSKY_PASSWORD |
Password used in Bluesky | As created in App Passwords. | None |
Not setting NOT_MY_EX_BSKY_EMAIL or NOT_MY_EX_BSKY_PASSWORD disables posting to Bluesky.
To post to Mastodon#
| Name | Description | Example | Default value |
|---|---|---|---|
NOT_MY_EX_MASTODON_INSTANCE |
Mastodon instance | "https://tech.lgbt" |
"https://mastodon.social" |
NOT_MY_EX_MASTODON_TOKEN |
Mastodon access token | Go to your Settings, Development and then create an app to get the access token. Select the write:statuses and write:media scopes. |
None |
Not setting NOT_MY_EX_MASTODON_TOKEN disables posting to Mastodon.
Install#
$ go install tangled.org/cuducos.me/not-my-ex/cmd/not-my-ex@latest
Usage#
CLI#
$ not-my-ex post "Magic, madness, heaven, sin" --images /tmp/1989.gif
You can skip the post text; in that case, it will open $EDITOR so you can write your post.
You can skip --images or pass multiple images (e.g. --images taylor.jpg --images swift.gif).
Check --help for more details on commands and subcommand.
API#
package main
import (
"context"
"log"
"tangled.org/cuducos.me/not-my-ex/auth"
"tangled.org/cuducos.me/not-my-ex/client"
"tangled.org/cuducos.me/not-my-ex/post"
"golang.org/x/sync/errgroup"
)
func main() {
ctx := context.Background()
data, err := auth.Load(auth.Path)
if err != nil {
log.Fatal(err)
}
bsky, err := client.NewBluesky(ctx, data.Bluesky)
if err != nil {
log.Fatal(err)
}
mstd, err := client.NewMastodon(ctx, data.Mastodon)
if err != nil {
log.Fatal(err)
}
medias, err := post.NewMedias(
[]string{"taylor.jpg", "swift.jpg"},
[]string{"Taylor", "Swift"},
bsky.Limit().Image,
false,
)
if err != nil {
log.Fatal(err)
}
p, err := post.NewPost("Magic, madness, heaven, sin", medias, "en", bsky.Limit().Text, false)
if err != nil {
log.Fatal(err)
}
var g errgroup.Group
for _, c := range []client.Client{bsky, mstd} {
g.Go(func() error {
_, err := c.Post(ctx, p)
return err
})
}
if err := g.Wait(); err != nil {
log.Fatal(err)
}
}
Contributing#
Format, lint, and test with:
$ gofmt -l .
$ golangci-lint run
$ go test ./...