{"id":13832825,"url":"https://github.com/slaninas/tostr","last_synced_at":"2025-07-09T20:30:41.336Z","repository":{"id":41405349,"uuid":"509058054","full_name":"slaninas/tostr","owner":"slaninas","description":"Bot that forwards tweets to nostr","archived":true,"fork":false,"pushed_at":"2023-07-06T14:22:46.000Z","size":101,"stargazers_count":27,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-02-16T05:34:51.366Z","etag":null,"topics":["bot","nostr","rust","twitter"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slaninas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-06-30T11:47:39.000Z","updated_at":"2024-02-09T10:57:55.000Z","dependencies_parsed_at":"2024-01-13T16:34:57.896Z","dependency_job_id":"8a7e31e8-054b-43a1-8a81-129ed776bab0","html_url":"https://github.com/slaninas/tostr","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/slaninas/tostr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaninas%2Ftostr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaninas%2Ftostr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaninas%2Ftostr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaninas%2Ftostr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slaninas","download_url":"https://codeload.github.com/slaninas/tostr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slaninas%2Ftostr/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264502642,"owners_count":23618663,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","nostr","rust","twitter"],"created_at":"2024-08-04T11:00:31.631Z","updated_at":"2025-07-09T20:30:40.979Z","avatar_url":"https://github.com/slaninas.png","language":"Rust","funding_links":[],"categories":["Tools"],"sub_categories":["Client reviews and/or comparisons"],"readme":"# tostr (doesn't work due to mandatory login policy)\n/ˈtəʊstə(r)/\n\n**T**witter to n**ostr**.\nBot that forwards tweets to [nostr](https://github.com/nostr-protocol/nostr).\n\nReply to its message with `!help` and it will show you all available commands.\n\nPowered by [nostr-bot](https://github.com/slaninas/nostr-bot.git).\n## How to run using Docker\n```\ngit clone https://github.com/slaninas/tostr/ \u0026\u0026 cd tostr\n# Now add secret (hex private key) to config file, tune config if you wish to\n./build_and_run.sh --clearnet|tor\n```\nNow the bot should be running and waiting for mentions. Just reply to its message to interact, see [Commands](#Commands).\nIt relays only new tweets that were posted after you launched it.\n\n## Tor\nIn case `--tor` is used connections to both relay and Twitter *should* be going through tor. But if you need full anonymity please **check yourself there are no leaks**.\n\n## Known limitations/issues\n- Heavy CPU load when starting the bot that already follows lot of users\n- in `update_user` function, `since` value may not correspond to the previous `until` value (seems it breaks shortly after a new tweet is found), this may lead to tweets being forwarded twice or not at all\n- twint is a Twitter scraper that currently works but who knows for how long\n- Doesn't work for retweets by users you follow (twint has `--retweets` option but it's extremely slow 1.5 vs 30 s for some accounts)\n- ~~There are multiple processes spawned for each account check and relaying, twint also takes some time to process so it's slow,\nI tested it with 40 accounts and it took almost a minute to check if there were any new tweets for them.~~ (under 4.5 s now, only twint process is spawned now)\n- ~~But it shows replies by people you follow (is that good or bad?)~~\n- ~~Tweets containing ' or \" are not relayed~~\n\n## TODOs\n- [ ] Check if tweets containing ' and \" are forwarded\n- [ ] After reconnection to relay, request events that were send when disconnected\n- [ ] Check the relay's response after sending subscription request\n- [ ] Better handling of handled event ids (add timestamp, remove old ones)\n- [ ] Don't send `set_metadata` again after reconnect\n- [ ] Cleanup\n- [ ] Set timeout for connection\n- [x] ~~Error handling~~\n- [x] ~~If tweets fetch fails include the time inverval from failed attempt in the next check~~\n- [x] Proxy support\n- [x] ~~Use existing websocket crate instead of spawning websocat process~~\n- [x] ~~Find solution better than spawning nostril process~~\n- [x] ~~Parallelization, async?~~\n- [x] ~~Follow Twitters redirects and send original url to nostr~~\n- [x] ~~Add proper logging~~\n- [x] ~~Check timestamps that are used for twint's --since option, if the new tweets check takes too long some tweets may get ignored during the next check~~\n- [x] ~~Read \"hello\" message from a config instead of using hardcoded one and post it when bot starts~~\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslaninas%2Ftostr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslaninas%2Ftostr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslaninas%2Ftostr/lists"}