-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(services, goval-ident): Implement chat variant of
goval-ident
…
…protocol - Fully implements [`goval-ident`](https://govaldocs.pages.dev/service/goval-ident/) - Makes `goval-ident` a disable-able feature - Unifies implemention of `chat` and `gcsfiles` variants
- Loading branch information
1 parent
f060083
commit 35ce3ad
Showing
13 changed files
with
245 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ use tracing::{debug, warn}; | |
impl traits::Service for GCSFiles { | ||
async fn message( | ||
&mut self, | ||
_info: &super::types::ChannelInfo, | ||
#[allow(unused)] info: &super::types::ChannelInfo, | ||
message: goval::Command, | ||
_session: SessionID, | ||
) -> Result<Option<goval::Command>> { | ||
|
@@ -64,19 +64,11 @@ impl traits::Service for GCSFiles { | |
let contents = match file.path.as_str() { | ||
// TODO: Read this from in the db | ||
".env" => vec![], | ||
#[cfg(feature = "goval-ident")] | ||
".config/goval/info" => { | ||
let val = serde_json::json!({ | ||
"server": "homeval", | ||
"version": env!("CARGO_PKG_VERSION").to_string(), | ||
"license": "AGPL", | ||
"authors": vec!["PotentialStyx <[email protected]>"], | ||
"repository": "https://github.com/goval-community/homeval", | ||
"description": "", // TODO: do dis | ||
"uptime": 0, // TODO: impl fo realz | ||
"services": super::IMPLEMENTED_SERVICES | ||
}); | ||
|
||
val.to_string().as_bytes().to_vec() | ||
serde_json::to_string(&info.server_info.get_serializable())? | ||
.as_bytes() | ||
.to_vec() | ||
} | ||
_ => match fs::read(&file.path).await { | ||
Err(err) => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
pub struct GovalIdent {} | ||
|
||
use crate::{server_info::ServerInfoSerialize, ClientInfo, IPCMessage, SessionID}; | ||
|
||
use super::traits; | ||
use anyhow::{format_err, Result}; | ||
use async_trait::async_trait; | ||
use serde::{Deserialize, Serialize}; | ||
use tracing::{error, warn}; | ||
|
||
#[derive(Deserialize)] | ||
enum IdentReqType { | ||
ServerInfo, | ||
|
||
#[serde(untagged)] | ||
Unknown(String), | ||
} | ||
|
||
#[derive(Deserialize)] | ||
struct IdentRequest { | ||
r#type: IdentReqType, | ||
r#ref: String, | ||
} | ||
|
||
#[derive(Serialize)] | ||
#[serde(untagged)] | ||
enum IdentResponseEnum<'a> { | ||
Error(String), | ||
Data(ServerInfoSerialize<'a>), | ||
} | ||
|
||
#[derive(Serialize)] | ||
struct IdentResponse<'a> { | ||
body: IdentResponseEnum<'a>, | ||
r#ref: String, | ||
} | ||
|
||
#[async_trait] | ||
impl traits::Service for GovalIdent { | ||
async fn message( | ||
&mut self, | ||
info: &super::types::ChannelInfo, | ||
message: goval::Command, | ||
session: SessionID, | ||
) -> Result<Option<goval::Command>> { | ||
let body = match message.body.clone() { | ||
None => return Err(format_err!("Expected command body")), | ||
Some(body) => body, | ||
}; | ||
|
||
match body { | ||
goval::command::Body::ChatMessage(msg) => { | ||
let req: IdentRequest = serde_json::from_str(&msg.text)?; | ||
|
||
match req.r#type { | ||
IdentReqType::ServerInfo => { | ||
let msg_text = serde_json::to_string(&IdentResponse { | ||
body: IdentResponseEnum::Data(info.server_info.get_serializable()), | ||
r#ref: req.r#ref, | ||
})?; | ||
|
||
let response_body = goval::command::Body::ChatMessage(goval::ChatMessage { | ||
username: "goval".to_string(), | ||
text: msg_text, | ||
}); | ||
|
||
let response = goval::Command { | ||
body: Some(response_body), | ||
..Default::default() | ||
}; | ||
|
||
Ok(Some(response)) | ||
} | ||
IdentReqType::Unknown(req_type) => { | ||
error!(req_type, "Unknown `goval-ident` request type"); | ||
|
||
let msg_text = serde_json::to_string(&IdentResponse { | ||
body: IdentResponseEnum::Error(format!( | ||
"Unknown request type {req_type}" | ||
)), | ||
r#ref: req.r#ref, | ||
})?; | ||
|
||
let response_body = goval::command::Body::ChatMessage(goval::ChatMessage { | ||
username: "goval".to_string(), | ||
text: msg_text, | ||
}); | ||
|
||
let response = goval::Command { | ||
body: Some(response_body), | ||
..Default::default() | ||
}; | ||
|
||
Ok(Some(response)) | ||
} | ||
} | ||
} | ||
goval::command::Body::ChatTyping(typing) => { | ||
warn!( | ||
%session, | ||
username = typing.username, | ||
"Chat#ChatTyping isn't supported by `goval-ident`", | ||
); | ||
Ok(None) | ||
} | ||
_ => { | ||
warn!(cmd = ?message, "Unknown goval-ident command"); | ||
Ok(None) | ||
} | ||
} | ||
} | ||
|
||
async fn attach( | ||
&mut self, | ||
_info: &super::types::ChannelInfo, | ||
_client: ClientInfo, | ||
_session: SessionID, | ||
_sender: tokio::sync::mpsc::UnboundedSender<IPCMessage>, | ||
) -> Result<Option<goval::Command>> { | ||
let mut scrollback = goval::Command::default(); | ||
|
||
let _inner = goval::ChatMessage { | ||
username: "goval".to_string(), | ||
text: "{\"type\": \"notification\"}".to_string(), | ||
}; | ||
|
||
scrollback.body = Some(goval::command::Body::ChatMessage(_inner)); | ||
|
||
Ok(Some(scrollback)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use std::{sync::LazyLock, time::Instant}; | ||
|
||
#[cfg(feature = "goval-ident")] | ||
use serde::Serialize; | ||
|
||
pub struct ServerInfo<'a> { | ||
pub name: &'a str, | ||
pub version: &'a str, | ||
pub license: &'a str, | ||
pub repository: &'a str, | ||
pub description: &'a str, | ||
|
||
pub start_time: &'a LazyLock<Instant>, | ||
|
||
// TODO: make this &[&str] (is this easily possible?) | ||
pub authors: &'a LazyLock<Vec<&'a str>>, | ||
} | ||
|
||
#[cfg(feature = "goval-ident")] | ||
#[derive(Serialize, Debug)] | ||
pub struct ServerInfoSerialize<'a> { | ||
pub server: &'a str, | ||
pub version: &'a str, | ||
pub license: &'a str, | ||
pub authors: &'a [&'a str], | ||
pub repository: &'a str, | ||
pub description: &'a str, | ||
pub uptime: u64, | ||
pub services: &'a [&'a str], | ||
} | ||
|
||
#[cfg(feature = "goval-ident")] | ||
impl<'a> ServerInfo<'a> { | ||
pub fn get_serializable(&self) -> ServerInfoSerialize<'a> { | ||
ServerInfoSerialize { | ||
server: self.name, | ||
version: self.version, | ||
license: self.license, | ||
authors: self.authors, | ||
repository: self.repository, | ||
description: self.description, | ||
uptime: self.start_time.elapsed().as_secs(), | ||
services: crate::IMPLEMENTED_SERVICES, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.