rustwave 0.1.0

A lightweight async event-driven WebSocket framework for Rust
Documentation
use rustwave::{Result, Server};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct GameMessage {
    mess: String,
    room: String,
}
#[tokio::main]
async fn main() -> Result<()> {
    let server = Server::bind("127.0.0.1:8080");

    server.on("ping", |_, cx| async move {
        let _ = cx.emit("pong", "accepted").await;
    });

    server.on("connection", |_data, ctx| async move {
        println!("[root] client connected: {}", ctx.get_socket_id());
    });

    server.on("disconnect", |_data, ctx| async move {
        println!("[root] client disconnected: {}", ctx.get_socket_id());
    });

    let chat = server.namespace("/chat");

    chat.on("mess", |payload, cx| async move {
        let _ = cx.emit("message", payload.raw()).await;
    });

    let game = server.namespace("game");

    game.on("online-count", {
        let game_ns = game.clone();
        move |_data, ctx| {
            let game_ns = game_ns.clone();
            async move {
                let count = game_ns.get_client_count();
                let _ = ctx.emit("online-count", count).await;
            }
        }
    });

    game.on("typing", |payload, ctx| async move {
        let room = payload.parse::<String>().unwrap_or_default();
        let sender_id = ctx.get_socket_id();
        let data = format!("user: {} type....", ctx.get_socket_id());

        let _ = ctx
            .broadcast_to_expect(&room, sender_id, "typing", data)
            .await;
    });

    game.on("join-room", |payload, ctx| async move {
        let room = payload.parse::<String>().unwrap_or_default();
        if room.is_empty() {
            return;
        }
        ctx.join_room(&room);

        let _ = ctx
            .broadcast_to_expect(
                &room,
                ctx.get_socket_id(),
                "player-joined",
                ctx.get_socket_id().to_string(),
            )
            .await;
    });

    game.on("leave-room", |payload, ctx| async move {
        let room = payload.parse::<String>().unwrap_or_default();
        if room.is_empty() {
            return;
        }
        ctx.leave_room(&room);

        let _ = ctx
            .broadcast_to_expect(
                &room,
                ctx.get_socket_id(),
                "player-left",
                ctx.get_socket_id().to_string(),
            )
            .await;
    });

    game.on("mess", |payload, cx| async move {
        let data = payload.parse::<GameMessage>().unwrap();
        let _ = cx
            .broadcast_to_expect(&data.room, cx.get_socket_id(), "mess", data.mess)
            .await;
    });

    let admin = server.namespace("/admin");

    admin.on("kick", {
        let admin_ns = admin.clone();
        move |payload, _ctx| {
            let admin_ns = admin_ns.clone();
            async move {
                let target = payload.parse::<String>().unwrap_or_default();
                if let Ok(target_id) = target.parse::<uuid::Uuid>() {
                    let _ = admin_ns.disconnect(&target_id).await;
                }
            }
        }
    });

    admin.on("kick-all", {
        let admin_ns = admin.clone();
        move |_data, _ctx| {
            let admin_ns = admin_ns.clone();
            async move {
                let _ = admin_ns.disconnect_all().await;
            }
        }
    });

    admin.on("is-online", {
        let admin_ns = admin.clone();
        move |payload, ctx| {
            let admin_ns = admin_ns.clone();
            async move {
                let target = payload.parse::<String>().unwrap_or_default();
                let online = target
                    .parse::<uuid::Uuid>()
                    .map(|id| admin_ns.is_connected(&id))
                    .unwrap_or(false);
                let _ = ctx.emit("is-online", online).await;
            }
        }
    });

    println!("Listening on ws://127.0.0.1:8080");
    server.run().await?;
    Ok(())
}