Quellcode durchsuchen

Post waiting messages with emoji reactions

Zulip lacks "X is typing" in topics, so during meetings it can be difficult to
determine whether to move on or not. This should be a solution!
Mark Rousskov vor 4 Jahren
Ursprung
Commit
7489986e6a
1 geänderte Dateien mit 86 neuen und 1 gelöschten Zeilen
  1. 86 1
      src/zulip.rs

+ 86 - 1
src/zulip.rs

@@ -156,6 +156,16 @@ fn handle_command<'a>(
                 })
                 .unwrap(),
             },
+            Some("await") => match post_waiter(&ctx, message_data).await {
+                Ok(r) => r,
+                Err(e) => serde_json::to_string(&Response {
+                    content: &format!(
+                        "Failed to await at this time: {:?}",
+                        e
+                    ),
+                })
+                .unwrap(),
+            },
             _ => serde_json::to_string(&Response {
                 content: "Unknown command.",
             })
@@ -430,7 +440,13 @@ impl<'a> MessageApiRequest<'a> {
                     Recipient::Private { email, .. } => email.to_string(),
                 },
                 topic: match self.recipient {
-                    Recipient::Stream { topic, .. } => Some(topic),
+                    Recipient::Stream { topic, .. } => {
+                        if topic.is_empty() {
+                            None
+                        } else {
+                            Some(topic)
+                        }
+                    }
                     Recipient::Private { .. } => None,
                 },
                 content: self.content,
@@ -604,3 +620,72 @@ async fn move_notification(
         .unwrap()),
     }
 }
+
+#[derive(serde::Serialize, Debug)]
+struct ResponseNotRequired {
+    response_not_required: bool,
+}
+
+#[derive(serde::Deserialize, Debug)]
+struct SentMessage {
+    id: u64,
+}
+
+#[derive(serde::Serialize, Debug, Copy, Clone)]
+struct AddReaction<'a> {
+    message_id: u64,
+    emoji_name: &'a str,
+}
+
+impl<'a> AddReaction<'a> {
+    pub async fn send(self, client: &reqwest::Client) -> anyhow::Result<reqwest::Response> {
+        let bot_api_token = env::var("ZULIP_API_TOKEN").expect("ZULIP_API_TOKEN");
+
+        Ok(client
+            .post(&format!(
+                "https://rust-lang.zulipchat.com/api/v1/messages/{}/reactions",
+                self.message_id
+            ))
+            .basic_auth(BOT_EMAIL, Some(&bot_api_token))
+            .form(&self)
+            .send()
+            .await?)
+    }
+}
+
+async fn post_waiter(ctx: &Context, message: &Message) -> anyhow::Result<String> {
+    let posted = MessageApiRequest {
+        recipient: Recipient::Stream {
+            id: message
+                .stream_id
+                .ok_or_else(|| anyhow::format_err!("private waiting not supported"))?,
+            topic: "",
+        },
+        content: "Does anyone has something to add on this topic, or should we move on?\n\
+                  React with :working_on_it: if you have something to say.\n\
+                  React with :all_good: if we should move on.",
+    }
+    .send(ctx.github.raw())
+    .await?;
+    let body = posted.text().await?;
+    let message_id = serde_json::from_str::<SentMessage>(&body)
+        .with_context(|| format!("{:?} did not deserialize as SentMessage", body))?
+        .id;
+
+    let reaction_a = AddReaction {
+        message_id,
+        emoji_name: "working_on_it",
+    }
+    .send(&ctx.github.raw());
+    let reaction_b = AddReaction {
+        message_id,
+        emoji_name: "all_good",
+    }
+    .send(&ctx.github.raw());
+    futures::try_join!(reaction_a, reaction_b,)?;
+
+    Ok(serde_json::to_string(&ResponseNotRequired {
+        response_not_required: true,
+    })
+    .unwrap())
+}