diff --git a/src/graphql/mod.rs b/src/graphql/mod.rs
index 0476ee9..5267712 100644
--- a/src/graphql/mod.rs
+++ b/src/graphql/mod.rs
@@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
pub mod models;
-pub mod mutations;
pub mod queries;
use std::sync::Arc;
diff --git a/src/graphql/models.rs b/src/graphql/models.rs
index 570b3af..519e77f 100644
--- a/src/graphql/models.rs
+++ b/src/graphql/models.rs
@@ -18,21 +18,28 @@ along with this program. If not, see .
use serde::Deserialize;
#[derive(Clone, Debug, Deserialize)]
-pub struct StreakWithMemberId {
- #[serde(rename = "memberId")]
- pub member_id: i32,
- #[serde(rename = "currentStreak")]
- pub current_streak: i32,
- #[serde(rename = "maxStreak")]
- pub max_streak: i32,
+pub struct StatusOnDate {
+ #[serde(rename = "isSent")]
+ pub is_sent: bool,
+ #[serde(rename = "onBreak")]
+ pub on_break: bool,
}
#[derive(Clone, Debug, Deserialize)]
-pub struct Streak {
+pub struct StatusStreak {
#[serde(rename = "currentStreak")]
- pub current_streak: i32,
+ pub current_streak: Option,
#[serde(rename = "maxStreak")]
- pub max_streak: i32,
+ pub max_streak: Option,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct MemberStatus {
+ #[serde(rename = "onDate")]
+ pub on_date: Option,
+ pub streak: Option,
+ #[serde(rename = "consecutiveMisses")]
+ pub consecutive_misses: Option,
}
#[derive(Clone, Debug, Deserialize)]
@@ -42,10 +49,9 @@ pub struct Member {
pub name: String,
#[serde(rename = "discordId")]
pub discord_id: String,
- #[serde(default)]
- pub streak: Vec, // Note that Root will NOT have multiple Streak elements but it may be an empty list which is why we use a vector here
pub track: Option,
pub year: i32,
+ pub status: Option,
}
#[derive(Debug, Deserialize, Clone)]
diff --git a/src/graphql/mutations.rs b/src/graphql/mutations.rs
deleted file mode 100644
index 4654d39..0000000
--- a/src/graphql/mutations.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use anyhow::anyhow;
-use anyhow::Context as _;
-use tracing::debug;
-use tracing::instrument;
-
-use crate::graphql::models::Streak;
-
-use super::models::Member;
-use super::GraphQLClient;
-
-impl GraphQLClient {
- #[instrument(level = "debug")]
- pub async fn increment_streak(&self, member: &mut Member) -> anyhow::Result<()> {
- let mutation = format!(
- r#"
- mutation {{
- incrementStreak(input: {{ memberId: {} }}) {{
- currentStreak
- maxStreak
- }}
- }}"#,
- member.member_id
- );
-
- debug!("Sending mutation {}", mutation);
- let response = self
- .http()
- .post(self.root_url())
- .json(&serde_json::json!({"query": mutation}))
- .send()
- .await
- .context("Failed to succesfully post query to Root")?;
-
- if !response.status().is_success() {
- return Err(anyhow!(
- "Server responded with an error: {:?}",
- response.status()
- ));
- }
- let response_json: serde_json::Value = response
- .json()
- .await
- .context("Failed to parse response JSON")?;
- debug!("Response: {}", response_json);
-
- if let Some(data) = response_json
- .get("data")
- .and_then(|data| data.get("incrementStreak"))
- {
- let current_streak = data
- .get("currentStreak")
- .and_then(|v| v.as_i64())
- .ok_or_else(|| anyhow!("current_streak was parsed as None"))?
- as i32;
- let max_streak = data
- .get("maxStreak")
- .and_then(|v| v.as_i64())
- .ok_or_else(|| anyhow!("max_streak was parsed as None"))?
- as i32;
-
- if member.streak.is_empty() {
- member.streak.push(Streak {
- current_streak,
- max_streak,
- });
- } else {
- for streak in &mut member.streak {
- streak.current_streak = current_streak;
- streak.max_streak = max_streak;
- }
- }
- } else {
- return Err(anyhow!(
- "Failed to access data from response: {}",
- response_json
- ));
- }
-
- Ok(())
- }
-
- #[instrument(level = "debug")]
- pub async fn reset_streak(&self, member: &mut Member) -> anyhow::Result<()> {
- let mutation = format!(
- r#"
- mutation {{
- resetStreak(input: {{ memberId: {} }}) {{
- currentStreak
- maxStreak
- }}
- }}"#,
- member.member_id
- );
-
- debug!("Sending mutation {}", mutation);
- let response = self
- .http()
- .post(self.root_url())
- .json(&serde_json::json!({ "query": mutation }))
- .send()
- .await
- .context("Failed to succesfully post query to Root")?;
-
- if !response.status().is_success() {
- return Err(anyhow!(
- "Server responded with an error: {:?}",
- response.status()
- ));
- }
-
- let response_json: serde_json::Value = response
- .json()
- .await
- .context("Failed to parse response JSON")?;
- debug!("Response: {}", response_json);
-
- if let Some(data) = response_json
- .get("data")
- .and_then(|data| data.get("resetStreak"))
- {
- let current_streak = data
- .get("currentStreak")
- .and_then(|v| v.as_i64())
- .ok_or_else(|| anyhow!("current_streak was parsed as None"))?
- as i32;
- let max_streak = data
- .get("maxStreak")
- .and_then(|v| v.as_i64())
- .ok_or_else(|| anyhow!("max_streak was parsed as None"))?
- as i32;
-
- if member.streak.is_empty() {
- member.streak.push(Streak {
- current_streak,
- max_streak,
- });
- } else {
- for streak in &mut member.streak {
- streak.current_streak = current_streak;
- streak.max_streak = max_streak;
- }
- }
- } else {
- return Err(anyhow!("Failed to access data from {}", response_json));
- }
-
- Ok(())
- }
-}
diff --git a/src/graphql/queries.rs b/src/graphql/queries.rs
index 9608d42..0cb6a6f 100644
--- a/src/graphql/queries.rs
+++ b/src/graphql/queries.rs
@@ -16,36 +16,51 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
use anyhow::{anyhow, Context};
-use chrono::Local;
+use chrono::{Local, NaiveDate};
use serde_json::Value;
use tracing::debug;
use crate::graphql::models::{AttendanceRecord, Member};
-use super::{models::StreakWithMemberId, GraphQLClient};
+use super::GraphQLClient;
impl GraphQLClient {
- pub async fn fetch_members(&self) -> anyhow::Result> {
+ pub async fn fetch_member_data(&self, date: NaiveDate) -> anyhow::Result> {
let query = r#"
- {
- members {
+ query($date: NaiveDate!) {
+ allMembers {
memberId
name
discordId
groupId
- streak {
- currentStreak
- maxStreak
+ status {
+ onDate(date: $date) {
+ isSent
+ onBreak
+ }
+ streak {
+ currentStreak,
+ maxStreak
+ }
+ consecutiveMisses
}
track
- }
- }"#;
+ year
+ }
+ }"#;
debug!("Sending query {}", query);
+
+ let variables = serde_json::json!({
+ "date": date.format("%Y-%m-%d").to_string()
+ });
+
+ debug!("With variables: {}", variables);
+
let response = self
.http()
.post(self.root_url())
- .json(&serde_json::json!({"query": query}))
+ .json(&serde_json::json!({"query": query, "variables":variables}))
.send()
.await
.context("Failed to successfully post request")?;
@@ -65,7 +80,7 @@ impl GraphQLClient {
debug!("Response: {}", response_json);
let members = response_json
.get("data")
- .and_then(|data| data.get("members"))
+ .and_then(|data| data.get("allMembers"))
.and_then(|members| members.as_array())
.ok_or_else(|| {
anyhow::anyhow!(
@@ -128,48 +143,4 @@ impl GraphQLClient {
);
Ok(attendance)
}
-
- pub async fn fetch_streaks(&self) -> anyhow::Result> {
- let query = r#"
- {
- streaks {
- memberId
- currentStreak
- maxStreak
- }
- }
- "#;
-
- debug!("Sending query {}", query);
- let response = self
- .http()
- .post(self.root_url())
- .json(&serde_json::json!({"query": query}))
- .send()
- .await
- .context("Failed to successfully post request")?;
-
- if !response.status().is_success() {
- return Err(anyhow!(
- "Server responded with an error: {:?}",
- response.status()
- ));
- }
-
- let response_json: serde_json::Value = response
- .json()
- .await
- .context("Failed to serialize response")?;
-
- debug!("Response: {}", response_json);
- let streaks = response_json
- .get("data")
- .and_then(|data| data.get("streaks"))
- .and_then(|streaks| {
- serde_json::from_value::>(streaks.clone()).ok()
- })
- .context("Failed to parse streaks data")?;
-
- Ok(streaks)
- }
}
diff --git a/src/ids.rs b/src/ids.rs
index d34dfcc..fbf20d3 100644
--- a/src/ids.rs
+++ b/src/ids.rs
@@ -33,10 +33,5 @@ pub const RESEARCH_ROLE_ID: u64 = 1298553855474270219;
pub const DEVOPS_ROLE_ID: u64 = 1298553883169132554;
pub const WEB_ROLE_ID: u64 = 1298553910167994428;
-// Channel IDs for status updates
-pub const SYSTEMS_CHANNEL_ID: u64 = 1378426650152271902;
-pub const MOBILE_CHANNEL_ID: u64 = 1378685538835365960;
-pub const WEB_CHANNEL_ID: u64 = 1378685360133115944;
-pub const AI_CHANNEL_ID: u64 = 1343489220068507649;
pub const STATUS_UPDATE_CHANNEL_ID: u64 = 764575524127244318;
pub const THE_LAB_CHANNEL_ID: u64 = 1208438766893670451;
diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs
index a08946c..f4f1b8b 100644
--- a/src/tasks/mod.rs
+++ b/src/tasks/mod.rs
@@ -25,7 +25,7 @@ use anyhow::Result;
use async_trait::async_trait;
use lab_attendance::PresenseReport;
use serenity::client::Context;
-use status_update::StatusUpdateCheck;
+use status_update::StatusUpdateReport;
use tokio::time::Duration;
use crate::graphql::GraphQLClient;
@@ -52,5 +52,5 @@ impl Debug for Box {
/// Analogous to [`crate::commands::get_commands`], every task that is defined
/// must be included in the returned vector in order for it to be scheduled.
pub fn get_tasks() -> Vec> {
- vec![Box::new(StatusUpdateCheck), Box::new(PresenseReport)]
+ vec![Box::new(PresenseReport), Box::new(StatusUpdateReport)]
}
diff --git a/src/tasks/status_update.rs b/src/tasks/status_update.rs
index 1c23f6a..23e9128 100644
--- a/src/tasks/status_update.rs
+++ b/src/tasks/status_update.rs
@@ -15,34 +15,30 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
-use chrono::{DateTime, Utc};
-use serenity::all::{
- CacheHttp, ChannelId, Context, CreateEmbed, CreateMessage, GetMessages, Message,
-};
+use serenity::all::{CacheHttp, ChannelId, Context, CreateEmbed, CreateMessage};
use serenity::async_trait;
use tracing::instrument;
use super::Task;
-use crate::graphql::models::{Member, StreakWithMemberId};
+use crate::graphql::models::Member;
use crate::graphql::GraphQLClient;
-use crate::ids::{
- AI_CHANNEL_ID, MOBILE_CHANNEL_ID, STATUS_UPDATE_CHANNEL_ID, SYSTEMS_CHANNEL_ID, WEB_CHANNEL_ID,
-};
+use crate::ids::STATUS_UPDATE_CHANNEL_ID;
use crate::utils::time::time_until;
/// Checks for status updates daily at 5 AM.
-pub struct StatusUpdateCheck;
+pub struct StatusUpdateReport;
#[async_trait]
-impl Task for StatusUpdateCheck {
+impl Task for StatusUpdateReport {
fn name(&self) -> &str {
- "Status Update Check"
+ "Status Update Report"
}
fn run_in(&self) -> tokio::time::Duration {
- time_until(5, 00)
+ time_until(5, 15)
+ // Duration::from_secs(1) // for development
}
async fn run(&self, ctx: Context, client: GraphQLClient) -> anyhow::Result<()> {
@@ -52,26 +48,18 @@ impl Task for StatusUpdateCheck {
type GroupedMember = HashMap