Explorar o código

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 %!s(int64=4) %!d(string=hai) anos
pai
achega
7489986e6a
Modificáronse 1 ficheiros con 86 adicións e 1 borrados
  1. 86 1
      src/zulip.rs

+ 86 - 1
src/zulip.rs

@@ -156,6 +156,16 @@ fn handle_command<'a>(
                 })
                 })
                 .unwrap(),
                 .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 {
             _ => serde_json::to_string(&Response {
                 content: "Unknown command.",
                 content: "Unknown command.",
             })
             })
@@ -430,7 +440,13 @@ impl<'a> MessageApiRequest<'a> {
                     Recipient::Private { email, .. } => email.to_string(),
                     Recipient::Private { email, .. } => email.to_string(),
                 },
                 },
                 topic: match self.recipient {
                 topic: match self.recipient {
-                    Recipient::Stream { topic, .. } => Some(topic),
+                    Recipient::Stream { topic, .. } => {
+                        if topic.is_empty() {
+                            None
+                        } else {
+                            Some(topic)
+                        }
+                    }
                     Recipient::Private { .. } => None,
                     Recipient::Private { .. } => None,
                 },
                 },
                 content: self.content,
                 content: self.content,
@@ -604,3 +620,72 @@ async fn move_notification(
         .unwrap()),
         .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())
+}