separate defintions
This commit is contained in:
parent
4f8fd9dc18
commit
859eb74ed8
4 changed files with 149 additions and 140 deletions
141
server/Lib.cs
141
server/Lib.cs
|
|
@ -1,140 +1 @@
|
||||||
using System.Text.RegularExpressions;
|
public static partial class Module { }
|
||||||
using SpacetimeDB;
|
|
||||||
|
|
||||||
public static partial class Module
|
|
||||||
{
|
|
||||||
[Table(Name = "User", Public = true)]
|
|
||||||
public partial class User
|
|
||||||
{
|
|
||||||
[PrimaryKey]
|
|
||||||
public Identity Identity;
|
|
||||||
public string? Name;
|
|
||||||
public string? Color;
|
|
||||||
public bool Online;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Table(Name = "Message", Public = true)]
|
|
||||||
public partial class Message
|
|
||||||
{
|
|
||||||
public Identity Sender;
|
|
||||||
public Timestamp Sent;
|
|
||||||
public string Text = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reducer]
|
|
||||||
public static void SetName(ReducerContext ctx, string name)
|
|
||||||
{
|
|
||||||
name = ValidateName(name);
|
|
||||||
|
|
||||||
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
|
||||||
if (user is not null)
|
|
||||||
{
|
|
||||||
user.Name = name;
|
|
||||||
ctx.Db.User.Identity.Update(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes a name and checks if it's acceptable as a user's name.
|
|
||||||
private static string ValidateName(string name)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
throw new Exception("Names must not be empty");
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reducer]
|
|
||||||
public static void SetColor(ReducerContext ctx, string color)
|
|
||||||
{
|
|
||||||
color = ValidateColor(color);
|
|
||||||
|
|
||||||
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
|
||||||
if (user is not null)
|
|
||||||
{
|
|
||||||
user.Color = color;
|
|
||||||
ctx.Db.User.Identity.Update(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ValidateColor(string color)
|
|
||||||
{
|
|
||||||
var regex = new Regex("^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
|
|
||||||
if (!regex.IsMatch(color))
|
|
||||||
{
|
|
||||||
throw new Exception("Invalid color code");
|
|
||||||
}
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reducer]
|
|
||||||
public static void SendMessage(ReducerContext ctx, string text)
|
|
||||||
{
|
|
||||||
text = ValidateMessage(text);
|
|
||||||
Log.Info(text);
|
|
||||||
ctx.Db.Message.Insert(
|
|
||||||
new Message
|
|
||||||
{
|
|
||||||
Sender = ctx.Sender,
|
|
||||||
Text = text,
|
|
||||||
Sent = ctx.Timestamp,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes a message's text and checks if it's acceptable to send.
|
|
||||||
private static string ValidateMessage(string text)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(text))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Messages must not be empty");
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reducer(ReducerKind.ClientConnected)]
|
|
||||||
public static void ClientConnected(ReducerContext ctx)
|
|
||||||
{
|
|
||||||
Log.Info($"Connect {ctx.Sender}");
|
|
||||||
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
|
||||||
|
|
||||||
if (user is not null)
|
|
||||||
{
|
|
||||||
// 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.Online = true;
|
|
||||||
ctx.Db.User.Identity.Update(user);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If this is a new user, create a `User` object for the `Identity`,
|
|
||||||
// which is online, but hasn't set a name.
|
|
||||||
ctx.Db.User.Insert(
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Name = null,
|
|
||||||
Identity = ctx.Sender,
|
|
||||||
Online = true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Reducer(ReducerKind.ClientDisconnected)]
|
|
||||||
public static void ClientDisconnected(ReducerContext ctx)
|
|
||||||
{
|
|
||||||
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
|
||||||
|
|
||||||
if (user is not null)
|
|
||||||
{
|
|
||||||
// This user should exist, so set `Online: false`.
|
|
||||||
user.Online = false;
|
|
||||||
ctx.Db.User.Identity.Update(user);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// User does not exist, log warning
|
|
||||||
Log.Warn("Warning: No user found for disconnected client.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
37
server/module/MessageTable.cs
Normal file
37
server/module/MessageTable.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
using SpacetimeDB;
|
||||||
|
|
||||||
|
public static partial class Module
|
||||||
|
{
|
||||||
|
[Table(Name = "Message", Public = true)]
|
||||||
|
public partial class Message
|
||||||
|
{
|
||||||
|
public Identity Sender;
|
||||||
|
public Timestamp Sent;
|
||||||
|
public string Text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes a message's text and checks if it's acceptable to send.
|
||||||
|
private static string ValidateMessage(string text)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Messages must not be empty");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reducer]
|
||||||
|
public static void SendMessage(ReducerContext ctx, string text)
|
||||||
|
{
|
||||||
|
text = ValidateMessage(text);
|
||||||
|
Log.Info(text);
|
||||||
|
ctx.Db.Message.Insert(
|
||||||
|
new Message
|
||||||
|
{
|
||||||
|
Sender = ctx.Sender,
|
||||||
|
Text = text,
|
||||||
|
Sent = ctx.Timestamp,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
server/module/Reducers.cs
Normal file
50
server/module/Reducers.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
using SpacetimeDB;
|
||||||
|
|
||||||
|
public static partial class Module
|
||||||
|
{
|
||||||
|
[Reducer(ReducerKind.ClientConnected)]
|
||||||
|
public static void ClientConnected(ReducerContext ctx)
|
||||||
|
{
|
||||||
|
Log.Info($"Connect {ctx.Sender}");
|
||||||
|
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
||||||
|
|
||||||
|
if (user is not null)
|
||||||
|
{
|
||||||
|
// 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.Online = true;
|
||||||
|
ctx.Db.User.Identity.Update(user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this is a new user, create a `User` object for the `Identity`,
|
||||||
|
// which is online, but hasn't set a name.
|
||||||
|
ctx.Db.User.Insert(
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
Name = null,
|
||||||
|
Identity = ctx.Sender,
|
||||||
|
Online = true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reducer(ReducerKind.ClientDisconnected)]
|
||||||
|
public static void ClientDisconnected(ReducerContext ctx)
|
||||||
|
{
|
||||||
|
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
||||||
|
|
||||||
|
if (user is not null)
|
||||||
|
{
|
||||||
|
// This user should exist, so set `Online: false`.
|
||||||
|
user.Online = false;
|
||||||
|
ctx.Db.User.Identity.Update(user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User does not exist, log warning
|
||||||
|
Log.Warn("Warning: No user found for disconnected client.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
server/module/UserTable.cs
Normal file
61
server/module/UserTable.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using SpacetimeDB;
|
||||||
|
|
||||||
|
public static partial class Module
|
||||||
|
{
|
||||||
|
[Table(Name = "User", Public = true)]
|
||||||
|
public partial class User
|
||||||
|
{
|
||||||
|
[PrimaryKey]
|
||||||
|
public Identity Identity;
|
||||||
|
public string? Name;
|
||||||
|
public string? Color;
|
||||||
|
public bool Online;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes a name and checks if it's acceptable as a user's name.
|
||||||
|
private static string ValidateName(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
throw new Exception("Names must not be empty");
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reducer]
|
||||||
|
public static void SetName(ReducerContext ctx, string name)
|
||||||
|
{
|
||||||
|
name = ValidateName(name);
|
||||||
|
|
||||||
|
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
||||||
|
if (user is not null)
|
||||||
|
{
|
||||||
|
user.Name = name;
|
||||||
|
ctx.Db.User.Identity.Update(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ValidateColor(string color)
|
||||||
|
{
|
||||||
|
var regex = new Regex("^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
|
||||||
|
if (!regex.IsMatch(color))
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid color code");
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reducer]
|
||||||
|
public static void SetColor(ReducerContext ctx, string color)
|
||||||
|
{
|
||||||
|
color = ValidateColor(color);
|
||||||
|
|
||||||
|
var user = ctx.Db.User.Identity.Find(ctx.Sender);
|
||||||
|
if (user is not null)
|
||||||
|
{
|
||||||
|
user.Color = color;
|
||||||
|
ctx.Db.User.Identity.Update(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue