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
- Python 3.9 or newer
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
$ pip install not-my-ex
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
from asyncio import gather
from httpx import AsyncClient
from not_my_ex.auth import EnvAuth
from not_my_ex.bluesky import Bluesky
from not_my_ex.mastodon import Mastodon
from not_my_ex.media import Media
from not_my_ex.post import Post
async def main():
auth = EnvAuth()
media_tasks = tuple(
Media.from_img(path, alt, auth.image_size_limit)
for path, alt in (("taylor.jpg", "Taylor"), ("swift.jpg", "Swift"))
)
media = await gather(*media_tasks)
post = Post("Magic, madness, heaven, sin", auth.limit, media, "en")
async with AsyncClient() as http:
post_tasks = tuple(cls(http).post(post) for cls in (Bluesky, Mastodon))
await gather(*post_tasks)
In Post, limit, media and lang are optional. In Media, both alt and image_size_limit are optional.
The usage of auth.limit and auth.image_size_limit makes sure the limits are set according to the authenticated clients.
Contributing
Requires uv Python package manager. The tests include Ruff and Mypy:
$ uv run pytest
Metadata
Release files for not-my-ex 1.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| not_my_ex-1.2.2.tar.gz | 161.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| not_my_ex-1.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 202.2 kB
Release files / not_my_ex-1.2.2.tar.gz
| Download URL | not_my_ex-1.2.2.tar.gz |
|---|---|
| Size | 161.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4bfa1a373e3bce67be934627688a4cc4e2892deb3d13b3f312a46ab5408d8032
|
|
BLAKE2b-256 checksum How to use checksums |
51b33c9dc51a4c5ae28b8353be7e4976b7eb9d1ed33202eaf1bea63b9e5f2ede
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.17
|
Release files / not_my_ex-1.2.2-py3-none-any.whl
| Download URL | not_my_ex-1.2.2-py3-none-any.whl |
|---|---|
| Size | 41.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
14a6e334ac0dff0c7b096870e1151bd5d3effe04d3e64bb6b7d69c7f6c551902
|
|
BLAKE2b-256 checksum How to use checksums |
0d346a8b7aec028513f3aa88c03a3ddedf68c46e54cc54d05afa89b4ee0cdb39
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.17
|
Security for not-my-ex 1.2.2
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.