diff options
| author | citrons <citrons@mondecitronne.com> | 2025-01-26 01:56:53 -0600 |
|---|---|---|
| committer | citrons <citrons@mondecitronne.com> | 2025-01-26 01:56:53 -0600 |
| commit | 10b8a79389e7073f6bd65695c3d05c77b825bc33 (patch) | |
| tree | b7e6dbd84b5b2c960ab8aafc1f99c3950d679e44 /server/channel/command.go | |
initial commit
Diffstat (limited to 'server/channel/command.go')
| -rw-r--r-- | server/channel/command.go | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/server/channel/command.go b/server/channel/command.go new file mode 100644 index 0000000..94cf38f --- /dev/null +++ b/server/channel/command.go @@ -0,0 +1,253 @@ +package channel + +import ( + "citrons.xyz/talk/server/session" + "citrons.xyz/talk/server/user" + "citrons.xyz/talk/proto" +) + +func (c *Channel) SendRequest(r session.Request) { + switch r.Cmd.Kind { + + case "p": + if len(r.Cmd.Args) != 1 { + r.ReplyInvalid() + return + } + m := r.Cmd.Args[0] + switch m.Kind { + case "m": + for k, _ := range m.Fields { + switch k { + case "": + default: + r.ReplyInvalid() + return + } + } + default: + r.ReplyInvalid() + return + } + + if !c.members[r.From.UserId].Put { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + + m.Fields["f"] = r.From.UserId + err := c.Put(m) + if err != nil { + r.Reply(err.Cmd()) + return + } + r.Reply(proto.NewCmd("p", c.id, m)) + + case "s": + r.From.Subscribe(&c.Stream) + r.Reply(proto.NewCmd("i", "", c.GetInfo())) + + case "u": + r.From.Unsubscribe(&c.Stream) + r.Reply(proto.NewCmd("ok", "")) + + case "join": + u := c.store.world.GetObject(r.From.UserId).(*user.User) + err := c.Join(u) + if err != nil { + r.Reply(err.Cmd()) + } else { + r.Reply(proto.NewCmd("ok", "")) + } + + case "leave": + u := c.store.world.GetObject(r.From.UserId).(*user.User) + err := c.Leave(u) + if err != nil { + r.Reply(err.Cmd()) + } else { + r.Reply(proto.NewCmd("ok", "")) + } + + case "delete": + if !c.members[r.From.UserId].Op { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + c.Delete() + + case "update": + if len(r.Cmd.Args) != 1 { + r.ReplyInvalid() + return + } + upd := r.Cmd.Args[0] + if upd.Kind != "channel" { + r.ReplyInvalid() + return + } + name := c.name + for k, v := range upd.Fields { + switch k { + case "": + name = v + default: + r.ReplyInvalid() + return + } + } + + if !c.members[r.From.UserId].Update { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + if name != c.name { + err := c.Rename(name) + if err != nil { + r.Reply(err.Cmd()) + return + } + } + c.Stream.Event(r.Cmd) + r.Reply(proto.NewCmd("ok", "")) + + case "list": + if !c.members[r.From.UserId].Yes { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + cmd := proto.NewCmd("list", c.Id()) + for m, _ := range c.Members() { + u := c.store.world.GetObject(m).(*user.User) + cmd.Args = append(cmd.Args, u.GetInfo()) + } + r.Reply(cmd) + + case "history": + if len(r.Cmd.Args) != 1 { + r.ReplyInvalid() + return + } + h := r.Cmd.Args[0] + var min int + var max int + switch h.Kind { + case "latest": + max = len(c.messages) + min = max - 20 + case "before", "around", "at": + var id string + for k, v := range h.Fields { + switch k { + case "": + id = v + default: + r.ReplyInvalid() + return + } + } + i, ok := c.byId[id] + if !ok { + r.Reply(proto.Fail{"bad-target", "", nil}.Cmd()) + return + } + switch h.Kind { + case "before": + max = i + min = max - 20 + case "around": + min = i - 9 + max = i + 11 + case "at": + min = i + max = i + 1 + } + default: + r.ReplyInvalid() + return + } + if min < 0 { + min = 0 + } + if max > len(c.messages) { + max = len(c.messages) + } + + p := c.members[r.From.UserId] + if !p.History || !p.See { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + cmd := proto.NewCmd("history", c.id) + cmd.Args = c.messages[min:max] + r.Reply(cmd) + + case "membership": + if len(r.Cmd.Args) != 1 { + r.ReplyInvalid() + return + } + m := r.Cmd.Args[0] + if m.Kind != "u" { + r.ReplyInvalid() + return + } + + if !c.members[r.From.UserId].Yes { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + + if !c.members[m.Id].Yes { + r.Reply(proto.Fail{ + "not-in-channel", "", map[string]string {"": m.Id}, + }.Cmd()) + return + } + i := c.members[m.Id].GetInfo() + i.Fields[""] = m.Id + r.Reply(proto.NewCmd("i", "", i)) + + case "config": + if len(r.Cmd.Args) != 1 { + r.ReplyInvalid() + return + } + o := r.Cmd.Args[0] + switch o.Kind { + case "membership": + id := o.Fields[""] + if id == "" { + r.ReplyInvalid() + return + } + new, err := c.members[id].Change(o) + if err != nil { + r.Reply(err.Cmd()) + return + } + + if !c.members[r.From.UserId].Op { + r.Reply(proto.Fail{"forbidden", "", nil}.Cmd()) + return + } + if !c.members[id].Yes { + r.Reply(proto.Fail{ + "not-in-channel", "", map[string]string {"": id}, + }.Cmd()) + return + } + c.members[id] = new + c.Put(o) + + i := new.GetInfo() + i.Fields[""] = id + r.Reply(proto.NewCmd("i", "", i)) + default: + r.ReplyInvalid() + } + + default: + r.ReplyInvalid() + } +} |
