implement list command

This commit is contained in:
Pierre de Lacroix 2026-06-27 13:32:01 +02:00
parent 8309d26c9f
commit 3210581a22
Signed by: lateralus23
GPG key ID: 53E0CEC29C24EF39
7 changed files with 467 additions and 25 deletions

210
Cargo.lock generated
View file

@ -391,9 +391,9 @@ dependencies = [
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.44" version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [ dependencies = [
"iana-time-zone", "iana-time-zone",
"js-sys", "js-sys",
@ -613,6 +613,40 @@ dependencies = [
"syn 2.0.117", "syn 2.0.117",
] ]
[[package]]
name = "darling"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.117",
]
[[package]]
name = "darling_macro"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
dependencies = [
"darling_core",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "date_header" name = "date_header"
version = "1.0.5" version = "1.0.5"
@ -690,6 +724,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
"serde_core",
] ]
[[package]] [[package]]
@ -788,6 +823,12 @@ dependencies = [
"syn 2.0.117", "syn 2.0.117",
] ]
[[package]]
name = "dyn-clone"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]] [[package]]
name = "ed25519" name = "ed25519"
version = "2.2.3" version = "2.2.3"
@ -1135,6 +1176,20 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "grist-client"
version = "0.0.1"
source = "git+https://github.com/QazCetelic/grist-client-rs#a5e41d8a0debbb06bf2ff87c0a8aa80734251a32"
dependencies = [
"reqwest",
"serde",
"serde_json",
"serde_repr",
"serde_with",
"url",
"uuid",
]
[[package]] [[package]]
name = "growable-bloom-filter" name = "growable-bloom-filter"
version = "2.1.1" version = "2.1.1"
@ -1159,13 +1214,19 @@ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"http", "http",
"indexmap", "indexmap 2.14.0",
"slab", "slab",
"tokio", "tokio",
"tokio-util", "tokio-util",
"tracing", "tracing",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.5" version = "0.15.5"
@ -1226,6 +1287,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "hkdf" name = "hkdf"
version = "0.12.4" version = "0.12.4"
@ -1496,6 +1563,12 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "idna" name = "idna"
version = "1.1.0" version = "1.1.0"
@ -1571,6 +1644,17 @@ dependencies = [
"quote", "quote",
] ]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
"serde",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.14.0" version = "2.14.0"
@ -1878,7 +1962,7 @@ dependencies = [
"gloo-timers", "gloo-timers",
"http", "http",
"imbl", "imbl",
"indexmap", "indexmap 2.14.0",
"itertools 0.14.0", "itertools 0.14.0",
"js_int", "js_int",
"language-tags", "language-tags",
@ -2141,6 +2225,16 @@ version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf6f36070878c42c5233846cd3de24cf9016828fd47bc22957a687298bb21fc" checksum = "cbf6f36070878c42c5233846cd3de24cf9016828fd47bc22957a687298bb21fc"
[[package]]
name = "mime_guess"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.8.9" version = "0.8.9"
@ -2676,6 +2770,26 @@ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
] ]
[[package]]
name = "ref-cast"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
dependencies = [
"ref-cast-impl",
]
[[package]]
name = "ref-cast-impl"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.12.3" version = "1.12.3"
@ -2725,6 +2839,7 @@ dependencies = [
"hyper-util", "hyper-util",
"js-sys", "js-sys",
"log", "log",
"mime_guess",
"native-tls", "native-tls",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
@ -2832,7 +2947,7 @@ dependencies = [
"form_urlencoded", "form_urlencoded",
"getrandom 0.2.17", "getrandom 0.2.17",
"http", "http",
"indexmap", "indexmap 2.14.0",
"js-sys", "js-sys",
"js_int", "js_int",
"konst", "konst",
@ -2861,7 +2976,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dbdeccb62cb4ffe3282325de8ba28cbc0fdce7c78a3f11b7241fbfdb9cb9907" checksum = "2dbdeccb62cb4ffe3282325de8ba28cbc0fdce7c78a3f11b7241fbfdb9cb9907"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"indexmap", "indexmap 2.14.0",
"js_int", "js_int",
"js_option", "js_option",
"percent-encoding", "percent-encoding",
@ -3044,6 +3159,30 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "schemars"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
dependencies = [
"dyn-clone",
"ref-cast",
"serde",
"serde_json",
]
[[package]]
name = "schemars"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
dependencies = [
"dyn-clone",
"ref-cast",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@ -3148,7 +3287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"indexmap", "indexmap 2.14.0",
"itoa", "itoa",
"ryu", "ryu",
"serde_core", "serde_core",
@ -3178,6 +3317,17 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "serde_repr"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "1.1.1" version = "1.1.1"
@ -3199,6 +3349,38 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_with"
version = "3.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c"
dependencies = [
"base64",
"bs58",
"chrono",
"hex",
"indexmap 1.9.3",
"indexmap 2.14.0",
"schemars 0.9.0",
"schemars 1.2.1",
"serde_core",
"serde_json",
"serde_with_macros",
"time",
]
[[package]]
name = "serde_with_macros"
version = "3.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.10.6" version = "0.10.6"
@ -3235,10 +3417,12 @@ name = "shift_bot"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono",
"clap", "clap",
"dirs", "dirs",
"either", "either",
"futures-util", "futures-util",
"grist-client",
"log", "log",
"matrix-sdk", "matrix-sdk",
"pulldown-cmark", "pulldown-cmark",
@ -3666,7 +3850,7 @@ version = "0.25.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
dependencies = [ dependencies = [
"indexmap", "indexmap 2.14.0",
"toml_datetime 1.1.1+spec-1.1.0", "toml_datetime 1.1.1+spec-1.1.0",
"toml_parser", "toml_parser",
"winnow 1.0.3", "winnow 1.0.3",
@ -4076,7 +4260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"indexmap", "indexmap 2.14.0",
"wasm-encoder", "wasm-encoder",
"wasmparser", "wasmparser",
] ]
@ -4120,7 +4304,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"indexmap", "indexmap 2.14.0",
"semver", "semver",
] ]
@ -4353,7 +4537,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"heck", "heck",
"indexmap", "indexmap 2.14.0",
"prettyplease", "prettyplease",
"syn 2.0.117", "syn 2.0.117",
"wasm-metadata", "wasm-metadata",
@ -4384,7 +4568,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitflags", "bitflags",
"indexmap", "indexmap 2.14.0",
"log", "log",
"serde", "serde",
"serde_derive", "serde_derive",
@ -4403,7 +4587,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"id-arena", "id-arena",
"indexmap", "indexmap 2.14.0",
"log", "log",
"semver", "semver",
"serde", "serde",

View file

@ -21,3 +21,5 @@ log = "^0.4"
simple_logger = "^5.2" simple_logger = "^5.2"
either = "^1.15" either = "^1.15"
shlex = "2.0.1" shlex = "2.0.1"
grist-client = { git = "https://github.com/QazCetelic/grist-client-rs", version = "0.0.1" }
chrono = "0.4.45"

View file

@ -64,10 +64,12 @@ pub fn get_serve() -> Arc<Serve> {
pub struct Main { pub struct Main {
/// The data directory. /// The data directory.
static_dir: PathBuf, static_dir: PathBuf,
/// Grist APIKEY
grist_api_key: String,
} }
impl Main { impl Main {
/// Constructor. /// Constructor.
pub fn new() -> Self { pub fn new(grist_api_key: impl Into<String>) -> Self {
let static_dir_root = match dirs::data_dir().context("no `static_dir` directory found") { let static_dir_root = match dirs::data_dir().context("no `static_dir` directory found") {
Ok(root) => root, Ok(root) => root,
Err(e) => { Err(e) => {
@ -77,6 +79,7 @@ impl Main {
}; };
Self { Self {
static_dir: static_dir_root.join("shift_bot"), static_dir: static_dir_root.join("shift_bot"),
grist_api_key: grist_api_key.into(),
} }
} }
@ -96,11 +99,16 @@ impl Main {
pub fn session_file(&self) -> PathBuf { pub fn session_file(&self) -> PathBuf {
self.from_static_dir(Self::SESSION_FILE_NAME) self.from_static_dir(Self::SESSION_FILE_NAME)
} }
/// Grist APIKEY
pub fn grist_api_key(&self) -> &str {
&self.grist_api_key
}
} }
impl Default for Main { impl Default for Main {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new("")
} }
} }

View file

@ -1,5 +1,4 @@
use std::fmt::Write; use crate::grist::Shift;
use clap::{CommandFactory, Parser, Subcommand}; use clap::{CommandFactory, Parser, Subcommand};
use matrix_sdk::{Client, Room}; use matrix_sdk::{Client, Room};
@ -27,19 +26,37 @@ enum Action {
Aide, Aide,
} }
/// Sends a message to a room.
pub async fn send_room_msg(_client: Client, room: Room, content: String) -> Res<OwnedEventId> { pub async fn send_room_msg(_client: Client, room: Room, content: String) -> Res<OwnedEventId> {
use matrix_sdk::ruma::events::room::message::RoomMessageEventContent; use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
// let md_parser = pulldown_cmark::Parser::new(&content);
// let mut html_body = String::with_capacity(250);
// pulldown_cmark::html::push_html(&mut html_body, md_parser);
// let content = RoomMessageEventContent::text_html(content, html_body);
let content = RoomMessageEventContent::text_plain(content); let content = RoomMessageEventContent::text_plain(content);
let sent = room.send(content).await?; let sent = room.send(content).await?;
Ok(sent.event_id) Ok(sent.event_id)
} }
// pub fn handle(command: impl Into<String>) -> Res<()> { pub async fn send_room_msg_html(
_client: Client,
room: Room,
html_body: String,
) -> Res<OwnedEventId> {
use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
// let md_parser = pulldown_cmark::Parser::new(&content);
// let mut html_body = String::with_capacity(250);
// pulldown_cmark::html::push_html(&mut html_body, md_parser);
let content = RoomMessageEventContent::text_html(html_body.clone(), html_body);
let sent = room.send(content).await?;
Ok(sent.event_id)
}
pub fn format_shifts(shifts: Vec<Shift>) -> String {
let mut output = String::new();
output.push_str("Shifts:\n<ul>");
for shift in shifts {
output.push_str(format!("<li>{}</li>", shift).as_ref());
}
output.push_str("</ul>");
output
}
pub async fn handle(command: impl AsRef<str>, room: Room, client: Client) -> Res<()> { pub async fn handle(command: impl AsRef<str>, room: Room, client: Client) -> Res<()> {
debug!("handling command: {}", command.as_ref()); debug!("handling command: {}", command.as_ref());
@ -50,6 +67,9 @@ pub async fn handle(command: impl AsRef<str>, room: Room, client: Client) -> Res
match clap.action { match clap.action {
Action::Lister => { Action::Lister => {
debug!("user asked for list"); debug!("user asked for list");
let shifts = crate::grist::list_shifts().await?;
debug!("{:?}", shifts);
send_room_msg_html(client, room, format_shifts(shifts)).await?;
} }
Action::Ajouter { nom, infos } => { Action::Ajouter { nom, infos } => {
debug!("user asked for add"); debug!("user asked for add");

220
src/grist.rs Normal file
View file

@ -0,0 +1,220 @@
prelude! {}
use chrono::DateTime;
use grist_client::apis::configuration::Configuration;
use grist_client::apis::records_api::list_records;
use grist_client::models::{RecordsList, RecordsListRecordsInner};
pub const API_URL: &str = "https://grist.interhacker.space/api";
pub const SHIFTS_DOC: &str = "iwSaC82TsQiuD3MYSG9RXX";
pub const SHIFTS_TABLE: &str = "Shifts";
pub const SHIFT_TYPES_TABLE: &str = "Types_de_shifts";
pub const INSCRIPTIONS_TABLE: &str = "Inscriptions";
#[derive(Clone, Debug)]
pub enum Priority {
Prioritaire,
Secondaire,
Bonus,
Urgent,
}
impl Display for Priority {
fn fmt(&self, f: &mut Fmt<'_>) -> FmtRes {
match self {
Priority::Prioritaire => write!(f, "<b>Prioritaire</b>"),
Priority::Secondaire => write!(f, "Secondaire"),
Priority::Bonus => write!(f, "Bonus"),
Priority::Urgent => write!(f, "<font color=\"red\">Prioritaire</font>"),
}
}
}
#[derive(Clone, Debug)]
pub struct ShiftType {
pub name: String,
pub priority: Priority,
pub frequency: u64,
pub persons: u64,
pub duration: u64,
pub guide: String,
}
impl ShiftType {
pub fn new(
name: impl Into<String>,
priority: Priority,
frequency: u64,
persons: u64,
duration: u64,
guide: impl Into<String>,
) -> Self {
Self {
name: name.into(),
priority: priority,
frequency: frequency,
persons: persons,
duration: duration,
guide: guide.into(),
}
}
}
impl Display for ShiftType {
fn fmt(&self, f: &mut Fmt<'_>) -> FmtRes {
write!(
f,
"{} ({}): {} x/j, {} personnes, {} h",
self.name, self.priority, self.frequency, self.persons, self.duration
)
}
}
// {"Autres_infos": Null, "Heure_de_debut": Number(1782144000), "Inscriptions": Array [String("L"), Number(1)], "Type_de_shift": Number(23)}
#[derive(Clone, Debug)]
pub struct Shift {
pub shift_type: ShiftType,
pub start_time: u64,
pub inscriptions: Vec<String>,
}
impl Shift {
pub fn new(shift_type: ShiftType, start_time: u64, inscriptions: Vec<String>) -> Self {
Self {
shift_type: shift_type,
start_time: start_time.into(),
inscriptions: inscriptions,
}
}
}
impl Display for Shift {
fn fmt(&self, f: &mut Fmt<'_>) -> FmtRes {
let start_time = DateTime::from_timestamp(self.start_time as i64, 0)
.expect("failed to parse timestamp")
.format("%H:%M");
write!(
f,
"{} ({}): à {}, durée {} h, inscrit·es: {}/{}",
self.shift_type.name,
self.shift_type.priority,
start_time,
self.shift_type.duration,
self.inscriptions.len(),
self.shift_type.persons
)
}
}
pub fn get_number(record: &RecordsListRecordsInner, column: &str) -> Res<u64> {
record
.fields
.get(column)
.ok_or(anyhow!("Failed to get column {}", column))?
.as_u64()
.ok_or(anyhow!("Failed to parse number"))
}
pub fn get_string(record: &RecordsListRecordsInner, column: &str) -> Res<String> {
record
.fields
.get(column)
.ok_or(anyhow!("Failed to get column {}", column))?
.as_str()
.ok_or(anyhow!("Failed to parse number"))
.map(|s| s.into())
}
pub fn get_priority(record: &RecordsListRecordsInner, column: &str) -> Res<Priority> {
match get_string(record, column)? {
s if s.starts_with("1") => Ok(Priority::Prioritaire),
s if s.starts_with("2") => Ok(Priority::Secondaire),
s if s.starts_with("3") => Ok(Priority::Bonus),
s if s.starts_with("0") => Ok(Priority::Urgent),
_ => Err(anyhow!("can't parse priority")),
}
}
pub fn get_number_array(record: RecordsListRecordsInner, column: &str) -> Res<Vec<u64>> {
let val_col = record
.fields
.get(column)
.ok_or(anyhow!("Failed to get column {}", column))?;
if val_col.is_null() {
return Ok(vec![]);
}
let mut val_array = val_col
.as_array()
.ok_or(anyhow!("Failed to parse array"))?
.clone();
val_array.remove(0);
debug!("{:?}", val_array);
let mut u64_array = Vec::new();
for val in val_array {
let u = val.as_u64().ok_or(anyhow!("Failed to parse number"))?;
u64_array.push(u);
}
Ok(u64_array)
}
pub async fn get_records(doc: &str, table: &str) -> Res<RecordsList> {
let conf = conf::get();
let api_key = conf.grist_api_key();
let grist_conf = Configuration::new(API_URL.into(), Some(api_key.into()));
list_records(&grist_conf, doc, table, None, None, None, None, None, None)
.await
.context("Failed to list records")
}
pub async fn get_shift_type(index: u64) -> Res<ShiftType> {
let record_list = get_records(SHIFTS_DOC, SHIFT_TYPES_TABLE).await?;
let record = record_list
.records
.iter()
.find(|record| record.id == index)
.ok_or(anyhow!("can't find shift type"))?;
Ok(ShiftType::new(
get_string(&record, "Nom")?,
get_priority(&record, "Priorite")?,
get_number(&record, "Frequence_jour")?,
get_number(&record, "Personnes_shift")?,
get_number(&record, "Duree_h_")?,
get_string(&record, "Guide")?,
))
}
pub async fn get_inscription(index: u64) -> Res<String> {
let record_list = get_records(SHIFTS_DOC, INSCRIPTIONS_TABLE).await?;
let record = record_list
.records
.iter()
.find(|record| record.id == index)
.ok_or(anyhow!("can't find inscription"))?
.clone();
let name = get_string(&record, "Personne")?.into();
Ok(name)
}
pub async fn list_shifts() -> Res<Vec<Shift>> {
let record_list = get_records(SHIFTS_DOC, SHIFTS_TABLE).await?;
debug!("{:?}", record_list);
let mut shifts: Vec<Shift> = Vec::new();
for record in record_list.records {
let shift_type_ref =
get_number(&record, "Type_de_shift").context("getting shift type ref")?;
let shift_type = get_shift_type(shift_type_ref).await?;
let start_time = get_number(&record, "Heure_de_debut")?;
let inscriptions_refs =
get_number_array(record, "Inscriptions").context("getting inscriptions refs")?;
// let inscriptions = inscriptions_refs
// .iter()
// .filter_map(async |i| get_inscription(i).await.ok())
// .collect();
let mut inscriptions = Vec::new();
for inscription_ref in inscriptions_refs {
inscriptions.push(get_inscription(inscription_ref).await?);
}
let shift = Shift::new(shift_type, start_time, inscriptions);
shifts.push(shift);
}
Ok(shifts)
}

View file

@ -41,6 +41,8 @@ pub mod serve;
pub mod command; pub mod command;
pub mod grist;
prelude! {} prelude! {}
/// Warmup, runs before anything. /// Warmup, runs before anything.

View file

@ -13,7 +13,7 @@ WARNING: The contents of this file may NOT be used to train AI/LLM models. See N
details. details.
*/ */
use clap::{Parser}; use clap::Parser;
use shift_bot::*; use shift_bot::*;
@ -39,6 +39,7 @@ struct Clap {
default_value = "shift_bot_dev" default_value = "shift_bot_dev"
)] )]
username: String, username: String,
/// Homeserver. /// Homeserver.
#[arg( #[arg(
short = 's', short = 's',
@ -47,9 +48,14 @@ struct Clap {
default_value = "matrix.org" default_value = "matrix.org"
)] )]
homeserver: String, homeserver: String,
/// Password of the element bot account. /// Password of the element bot account.
#[arg(short, long, value_name = "PASSWORD")] #[arg(short, long, value_name = "PASSWORD")]
password: String, password: String,
/// Grist APIKEY
#[arg(short, long)]
grist_api_key: String,
} }
impl Clap { impl Clap {
@ -69,7 +75,7 @@ impl Clap {
async fn run(self) -> Res<()> { async fn run(self) -> Res<()> {
simple_logger::init_with_level(self.verb_level()) simple_logger::init_with_level(self.verb_level())
.context("something when wrong while initializing logger")?; .context("something when wrong while initializing logger")?;
conf::set(conf::Main::new()); conf::set(conf::Main::new(self.grist_api_key));
warmup(self.wipe)?; warmup(self.wipe)?;
let bot = MatrixId::new(self.username, self.homeserver); let bot = MatrixId::new(self.username, self.homeserver);
let conf = conf::Serve::new(bot, self.password); let conf = conf::Serve::new(bot, self.password);