Products: chat command filter, request signing, saved state
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
2190230f81
commit
0c4f6caec1
4 files changed
+313
No files matched your search
@@ -0,0 +1,80 @@
|
||||
package products
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// outfitCommands are the chat commands whose arguments are product IDs: putting products on and taking them off.
|
||||
var outfitCommands = map[string]bool{
|
||||
"*use": true, "*putOn": true, "*putOnOutfit": true, "*remove": true, "*takeOff": true,
|
||||
}
|
||||
|
||||
// bodyProduct is the avatar body every full outfit starts from; a *use list with it is a whole outfit (the client
|
||||
// re-sends its outfit that way every 30 s or so).
|
||||
const bodyProduct = 80
|
||||
|
||||
// strippedCommand is a chat line with community products taken out of its outfit command.
|
||||
type strippedCommand struct {
|
||||
text string // the line to send instead
|
||||
changed bool // products were taken out
|
||||
empty bool // nothing is left to send
|
||||
outfit bool // the line was a whole outfit (*use with the body)
|
||||
products []int64 // the community products it named
|
||||
}
|
||||
|
||||
// stripCommand takes products for which isCommunity is true out of an outfit command's arguments.
|
||||
func stripCommand(text string, isCommunity func(int64) bool) strippedCommand {
|
||||
fields := strings.Fields(text)
|
||||
if len(fields) == 0 || !outfitCommands[fields[0]] {
|
||||
return strippedCommand{text: text}
|
||||
}
|
||||
r := strippedCommand{text: text}
|
||||
kept := []string{fields[0]}
|
||||
for _, f := range fields[1:] {
|
||||
id, err := strconv.ParseInt(f, 10, 64)
|
||||
if err == nil && id == bodyProduct && fields[0] == "*use" {
|
||||
r.outfit = true
|
||||
}
|
||||
if err == nil && isCommunity(id) {
|
||||
r.products = append(r.products, id)
|
||||
continue
|
||||
}
|
||||
kept = append(kept, f)
|
||||
}
|
||||
if len(r.products) == 0 {
|
||||
return r
|
||||
}
|
||||
r.changed = true
|
||||
r.empty = len(kept) == 1
|
||||
r.text = strings.Join(kept, " ")
|
||||
return r
|
||||
}
|
||||
|
||||
// chatMessage is the JSON the client sends on a chat queue's "messages" mount.
|
||||
type chatMessage struct {
|
||||
fields map[string]json.RawMessage
|
||||
text string
|
||||
userID int64
|
||||
}
|
||||
|
||||
func parseChatMessage(b []byte) (*chatMessage, bool) {
|
||||
var fields map[string]json.RawMessage
|
||||
if json.Unmarshal(b, &fields) != nil {
|
||||
return nil, false
|
||||
}
|
||||
m := &chatMessage{fields: fields}
|
||||
if json.Unmarshal(fields["message"], &m.text) != nil {
|
||||
return nil, false
|
||||
}
|
||||
json.Unmarshal(fields["userId"], &m.userID)
|
||||
return m, true
|
||||
}
|
||||
|
||||
func (m *chatMessage) withText(text string) []byte {
|
||||
b, _ := json.Marshal(text)
|
||||
m.fields["message"] = b
|
||||
out, _ := json.Marshal(m.fields)
|
||||
return out
|
||||
}
|
||||
Reference in new issue
Block a user