recent mize changes
This commit is contained in:
167
marts/src/discord/mod.rs
Normal file
167
marts/src/discord/mod.rs
Normal file
@@ -0,0 +1,167 @@
|
||||
pub use mize::*;
|
||||
|
||||
// ========== WASM-specific imports (Obsidian plugin) ==========
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
use js_sys;
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
use web_sys;
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
use crate::obsidian::{ObsidianPart, MartsCommand};
|
||||
|
||||
// ========== Native-specific imports (OS daemon) ==========
|
||||
#[cfg(feature = "target-os")]
|
||||
use serenity::{
|
||||
async_trait as serenity_async_trait,
|
||||
client::{Client, Context, EventHandler},
|
||||
model::{
|
||||
channel::Message,
|
||||
gateway::Ready,
|
||||
id::ChannelId,
|
||||
},
|
||||
prelude::GatewayIntents,
|
||||
};
|
||||
#[cfg(feature = "target-os")]
|
||||
use mize::async_trait;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[mize_part]
|
||||
pub struct DiscordPart {
|
||||
pub mize: Mize,
|
||||
// Native: serenity client
|
||||
#[cfg(feature = "target-os")]
|
||||
pub client: Option<Client>,
|
||||
}
|
||||
|
||||
impl DiscordPart {
|
||||
// ========== WASM (Obsidian plugin) methods ==========
|
||||
|
||||
/// Read a file from the Obsidian vault using the Obsidian API
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
pub fn read_obsidian_file(&self, path: &str) -> MizeResult<String> {
|
||||
// TODO: Implement using js_sys to call Obsidian's vault.read() or similar
|
||||
// Example approach:
|
||||
use wasm_bindgen::JsCast;
|
||||
use js_sys::Reflect;
|
||||
let obsidian_part = self.mize.get_part_native::<ObsidianPart>("obsidian")?;
|
||||
let plugin = &obsidian_part.plugin();
|
||||
let app = Reflect::get(plugin, &"app".into())?;
|
||||
let vault = Reflect::get(&app, &"vault".into())?;
|
||||
let content = Reflect::call(&vault, &"read".into(), &path.into())?;
|
||||
content.as_string().ok_or_else(|| mize_err!("Failed to read file"))
|
||||
}
|
||||
|
||||
/// Send content to Discord channel using Discord REST API
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
pub fn send_to_discord_rest(&self, content: String, channel_id: u64) -> MizeResult<()> {
|
||||
// TODO: Implement using web_sys to call Discord REST API
|
||||
// 1. Get token: mize.get_config("discord.token")
|
||||
// 2. POST to https://discord.com/api/v10/channels/{channel_id}/messages
|
||||
// 3. Headers: Authorization: Bot <token>, Content-Type: application/json
|
||||
// 4. Body: {"content": content}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ========== Native (OS daemon) methods ==========
|
||||
|
||||
/// Start the serenity Discord bot
|
||||
#[cfg(feature = "target-os")]
|
||||
pub async fn start_serenity_bot(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
let token = mize.get_config("discord.token")?.value_string()?;
|
||||
|
||||
// Define event handler
|
||||
struct Handler;
|
||||
|
||||
#[serenity_async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn ready(&self, _: Context, ready: Ready) {
|
||||
println!("Discord bot logged in as {}", ready.user.name);
|
||||
}
|
||||
|
||||
// TODO: Add message handler for receiving commands from plugin
|
||||
// This is where you'll implement communication with the Obsidian plugin
|
||||
// Example:
|
||||
// async fn message(&self, ctx: Context, msg: Message) {
|
||||
// if msg.content.starts_with("!send") {
|
||||
// // Parse command and send file to channel
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
let mut client = Client::builder(&token, GatewayIntents::non_privileged())
|
||||
.event_handler(Handler)
|
||||
.await?;
|
||||
|
||||
// Spawn the client in a tokio task
|
||||
tokio::spawn({
|
||||
let client_clone = client.clone();
|
||||
async move {
|
||||
if let Err(why) = client_clone.start().await {
|
||||
eprintln!("Discord client error: {:?}", why);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.client = Some(client);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MizePart for DiscordPart {
|
||||
fn init(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
// WASM: Add command to Obsidian
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
{
|
||||
let obsidian_part = mize.get_part_native::<ObsidianPart>("obsidian")?;
|
||||
|
||||
let callback = {
|
||||
let mize_clone = mize.clone();
|
||||
move |mize_inner: Mize| -> MizeResult<()> {
|
||||
// Get configuration values
|
||||
let file_path = mize_inner.get_config("sc2.shared_daily_journal_file")?
|
||||
.value_string()?;
|
||||
let channel_id_str = mize_inner.get_config("sc2.shared_daily_journal_channel")?
|
||||
.value_string()?;
|
||||
let channel_id = channel_id_str.parse::<u64>()?;
|
||||
|
||||
// Get DiscordPart and send the file
|
||||
let mut mize_mut = mize_inner;
|
||||
let discord_part = mize_mut.get_part_native::<DiscordPart>("discord")?;
|
||||
let content = discord_part.read_obsidian_file(&file_path)?;
|
||||
|
||||
// TODO: COMMUNICATION WITH DAEMON GOES HERE
|
||||
// For now, we send directly using REST API.
|
||||
// Replace this with your plugin-to-daemon messaging logic.
|
||||
discord_part.send_to_discord_rest(content, channel_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
|
||||
obsidian_part.add_command(MartsCommand {
|
||||
id: "send_to_discord".to_string(),
|
||||
name: "Send to Discord".to_string(),
|
||||
callback: Box::new(callback),
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Native: Override async_init to start serenity bot
|
||||
#[cfg(feature = "target-os")]
|
||||
async fn async_init(&mut self, mize: &mut Mize) -> MizeResult<()> {
|
||||
self.start_serenity_bot(mize).await
|
||||
}
|
||||
}
|
||||
|
||||
impl MizePartCreate for DiscordPart {}
|
||||
|
||||
pub fn part_discord(mize: &mut Mize) -> MizeResult<()> {
|
||||
mize.register_part(Box::new(DiscordPart {
|
||||
mize: mize.clone(),
|
||||
#[cfg(feature = "target-os")]
|
||||
client: None,
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user