announcing good-first-issue tags added on @tangled.sh (not affiliated with tangled!)

Compare changes

Choose any two refs to compare.

Changed files
+63
docs
src
docs/october-dolly.png

This is a binary file and will not be displayed.

+7
license
··· 1 + Copyright (c) 2025 @bad-example.com 2 + 3 + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 + 5 + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 + 7 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+32
readme.md
··· 1 + # ๐ŸŽƒ Happy hacktober! ๐Ÿง™๐Ÿผโ€โ™€๏ธ 2 + 3 + ![tangle's dolly as a witchy pumpkin](./docs/october-dolly.png) 4 + 5 + [This bot](https://bsky.app/profile/hacktober.tngl.sh) listens to the [jetstream](github.com/bluesky-social/jetstream) firehose, filters for labels added to issues on [tangled.org](https://tangled.org/), checks if they are the official [`good-first-issue`](https://tangled.org/goodfirstissues) label, and then [posts](https://bsky.app/profile/hacktober.tngl.sh/post/3m2oflabdmc2u) about it! 6 + 7 + 8 + ### It's made with: 9 + 10 + - [jacquard](https://docs.rs/jacquard/latest/jacquard/): auth and posting 11 + - [microcosm slingshot](https://slingshot.microcosm.blue/): identity resolution and record fetching 12 + - [microcosm jetstream](https://tangled.org/@microcosm.blue/microcosm-rs/tree/main/jetstream): firehose listener 13 + - [tangled's](https://tangled.org/) PDS hosts the bot's account! 14 + 15 + ### It's made by: 16 + 17 + - [@bad-example.com](https://bsky.app/profile/bad-example.com): [ko-fi](https://ko-fi.com/bad_example), [github sponsors](https://github.com/sponsors/uniphil/) 18 + 19 + 20 + ### It would be nice if this bot would: 21 + 22 + - [ ] pull [OG repo images](https://bsky.app/profile/oppi.li/post/3m2orohxal22j) so it can post with an external link embed 23 + 24 + ### It would be nice if this bot *could*: 25 + 26 + - [ ] link directly to the issue, instead of the repo's all-issues page. i don't think it's possible right now because the issue page URL needs the issue id number, which is only kept in tangled's appview at the moment. 27 + - [ ] reply to its posts when issues are closed as complete! again currently the open/closed state for tangled is only in the appview, so this is not currently possible to detect. 28 + 29 + 30 + ### Things to watch out for if you hack on it 31 + 32 + - [ ] The microcosm jetstream package isn't published, so this currently uses a horrible local path reference for it, and that reference uses a very old folder name that you won't get by default from cloning [microcosm-rs](https://tangled.org/@microcosm.blue/microcosm-rs). If you rename microcosm-rs's folder name to `links`, it should work! or ping me and i'll fix it.
+24
src/main.rs
··· 50 50 /// don't actually post 51 51 #[arg(long, action)] 52 52 dry_run: bool, 53 + /// send a checkin to this url every 5 mins 54 + #[arg(long)] 55 + healthcheck_ping: Option<Url>, 53 56 } 54 57 55 58 struct IssueDetails { ··· 292 295 Ok(()) 293 296 } 294 297 298 + async fn hc_ping(url: Url, client: reqwest::Client) { 299 + let mut interval = tokio::time::interval(Duration::from_secs(5 * 60)); 300 + loop { 301 + interval.tick().await; 302 + log::trace!("sending healthcheck ping..."); 303 + if let Err(e) = client 304 + .get(url.clone()) 305 + .send() 306 + .await 307 + .and_then(reqwest::Response::error_for_status) 308 + { 309 + log::warn!("error sending healthcheck ping: {e}"); 310 + } 311 + } 312 + } 313 + 295 314 #[tokio::main] 296 315 async fn main() -> Result<()> { 297 316 env_logger::init(); ··· 325 344 let mut receiver = JetstreamConnector::new(jetstream_config)? 326 345 .connect_cursor(args.jetstream_cursor.map(Cursor::from_raw_u64)) 327 346 .await?; 347 + 348 + if let Some(hc) = args.healthcheck_ping { 349 + log::info!("starting healthcheck ping task..."); 350 + tokio::task::spawn(hc_ping(hc.clone(), slingshot_client.clone())); 351 + } 328 352 329 353 log::info!("receiving jetstream messages..."); 330 354 loop {