feat: add messages feature

This commit is contained in:
2026-06-25 01:11:13 +03:30
parent 27c20b1d34
commit 9a86d2bd4d
4 changed files with 100 additions and 1 deletions
+25
View File
@@ -65,6 +65,7 @@ type Room struct {
dealDelay time.Duration // پنجره‌ی پخشِ بقیه‌ی کارت‌ها (پس از انتخابِ حکم)
// graceUntil: تا این لحظه هیچ حرکتِ خودکاری انجام نمی‌شود (هماهنگ با انیمیشن‌های کلاینت).
graceUntil time.Time
chatAt [4]time.Time // آخرین زمانِ چتِ هر جایگاه (ضدِ اسپم)
}
func newRoom(id string, seats [4]*seatInfo, hub *Hub) *Room {
@@ -250,6 +251,8 @@ func (r *Room) handleInput(act roomAction) {
switch act.msg.Type {
case "leave":
r.handleLeave(act.seat)
case "chat":
r.handleChat(act.seat, act.msg.Text, act.msg.Emoji)
case "choose_trump":
suit, err := game.ParseSuit(act.msg.Suit)
if err != nil {
@@ -544,6 +547,28 @@ func (r *Room) broadcast(b []byte) {
}
}
// handleChat یک پیام/شکلکِ بازیکن را با کنترلِ نرخ (ضدِ اسپم) و طولِ مجاز برای
// همه‌ی میز پخش می‌کند تا کنارِ آواتارِ فرستنده نمایش داده شود.
func (r *Room) handleChat(seat int, text, emoji string) {
now := time.Now()
if now.Sub(r.chatAt[seat]) < 1200*time.Millisecond {
return // فاصله‌ی کمتر از ~۱.۲ ثانیه ⇒ نادیده (ضدِ اسپم)
}
clip := func(s string, n int) string {
r := []rune(s)
if len(r) > n {
return string(r[:n])
}
return s
}
text, emoji = clip(text, 60), clip(emoji, 16)
if text == "" && emoji == "" {
return
}
r.chatAt[seat] = now
r.broadcast(mustJSON(chatMsg{Type: "chat", Seat: seat, Text: text, Emoji: emoji}))
}
func (r *Room) sendError(seat int, msg string) {
if c := r.seats[seat].client; c != nil {
c.trySend(mustJSON(errorMsg{Type: "error", Message: msg}))