Files
Zeke Foppa 4af892a122 [bfops/update-quickstart]: do thing (#1348)
Co-authored-by: Zeke Foppa <github.com/bfops>
2024-06-06 20:40:45 +00:00

97 lines
2.7 KiB
Rust

use spacetimedb::{spacetimedb, Identity, ReducerContext, Timestamp};
#[spacetimedb(table(public))]
pub struct User {
#[primarykey]
identity: Identity,
name: Option<String>,
online: bool,
}
#[spacetimedb(table(public))]
pub struct Message {
sender: Identity,
sent: Timestamp,
text: String,
}
fn validate_name(name: String) -> Result<String, String> {
if name.is_empty() {
Err("Names must not be empty".to_string())
} else {
Ok(name)
}
}
#[spacetimedb(reducer)]
pub fn set_name(ctx: ReducerContext, name: String) -> Result<(), String> {
let name = validate_name(name)?;
if let Some(user) = User::filter_by_identity(&ctx.sender) {
User::update_by_identity(
&ctx.sender,
User {
name: Some(name),
..user
},
);
Ok(())
} else {
Err("Cannot set name for unknown user".to_string())
}
}
fn validate_message(text: String) -> Result<String, String> {
if text.is_empty() {
Err("Messages must not be empty".to_string())
} else {
Ok(text)
}
}
#[spacetimedb(reducer)]
pub fn send_message(ctx: ReducerContext, text: String) -> Result<(), String> {
// Things to consider:
// - Rate-limit messages per-user.
// - Reject messages from unnamed users.
let text = validate_message(text)?;
Message::insert(Message {
sender: ctx.sender,
text,
sent: ctx.timestamp,
});
Ok(())
}
#[spacetimedb(init)]
// Called when the module is initially published
pub fn init() {}
#[spacetimedb(connect)]
pub fn identity_connected(ctx: ReducerContext) {
if let Some(user) = User::filter_by_identity(&ctx.sender) {
// If this is a returning user, i.e. we already have a `User` with this `Identity`,
// set `online: true`, but leave `name` and `identity` unchanged.
User::update_by_identity(&ctx.sender, User { online: true, ..user });
} else {
// If this is a new user, create a `User` row for the `Identity`,
// which is online, but hasn't set a name.
User::insert(User {
name: None,
identity: ctx.sender,
online: true,
})
.unwrap();
}
}
#[spacetimedb(disconnect)]
pub fn identity_disconnected(ctx: ReducerContext) {
if let Some(user) = User::filter_by_identity(&ctx.sender) {
User::update_by_identity(&ctx.sender, User { online: false, ..user });
} else {
// This branch should be unreachable,
// as it doesn't make sense for a client to disconnect without connecting first.
log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender);
}
}