Add support for commands
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package incoming
|
||||
|
||||
type (
|
||||
ExecCommand struct {
|
||||
ChannelID string `json:"channelId"`
|
||||
Command string `json:"command"`
|
||||
Params map[string]string `json:"params"`
|
||||
Input string `json:"input"`
|
||||
}
|
||||
)
|
||||
@@ -19,4 +19,6 @@ type Payload struct {
|
||||
*MessageDelete `json:"deleteMessage"`
|
||||
|
||||
*Users `json:"getUsers"`
|
||||
|
||||
*ExecCommand `json:"exec"`
|
||||
}
|
||||
|
||||
@@ -115,3 +115,23 @@ func Attachment(in *sam.Attachment) *outgoing.Attachment {
|
||||
UpdatedAt: in.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func Command(cmd *sam.Command) *outgoing.Command {
|
||||
if cmd == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &outgoing.Command{
|
||||
Name: cmd.Name,
|
||||
Description: cmd.Description,
|
||||
}
|
||||
}
|
||||
|
||||
func Commands(cc sam.CommandSet) *outgoing.CommandSet {
|
||||
out := make([]*outgoing.Command, len(cc))
|
||||
for k, m := range cc {
|
||||
out[k] = Command(m)
|
||||
}
|
||||
retval := outgoing.CommandSet(out)
|
||||
return &retval
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package outgoing
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type (
|
||||
Command struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
CommandSet []*Command
|
||||
)
|
||||
|
||||
func (p *CommandSet) EncodeMessage() ([]byte, error) {
|
||||
return json.Marshal(Payload{CommandSet: p})
|
||||
}
|
||||
@@ -18,6 +18,8 @@ type (
|
||||
|
||||
*User `json:"user,omitempty"`
|
||||
*UserSet `json:"users,omitempty"`
|
||||
|
||||
*CommandSet `json:"commands,omitempty"`
|
||||
}
|
||||
|
||||
// This is same-same but different as using the json.Marshaler
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
Command struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Params CommandParamSet `db:"params" json:"params"`
|
||||
Description string `db:"description" json:"description"`
|
||||
}
|
||||
|
||||
CommandParam struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Type string `db:"type" json:"type"`
|
||||
Required bool `db:"required" json:"required"`
|
||||
}
|
||||
|
||||
CommandSet []*Command
|
||||
CommandParamSet []*CommandParam
|
||||
)
|
||||
|
||||
var (
|
||||
Preset CommandSet // @todo move this to someplace safe
|
||||
)
|
||||
|
||||
func init() {
|
||||
Preset = CommandSet{
|
||||
&Command{
|
||||
Name: "echo",
|
||||
Description: "It does exactly what it says on the tin"},
|
||||
&Command{
|
||||
Name: "shrug",
|
||||
Description: "It does exactly what it says on the tin"},
|
||||
}
|
||||
}
|
||||
|
||||
func (cc CommandSet) Walk(w func(*Command) error) (err error) {
|
||||
for i := range cc {
|
||||
if err = w(cc[i]); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (pp CommandParamSet) Walk(w func(*CommandParam) error) (err error) {
|
||||
for i := range pp {
|
||||
if err = w(pp[i]); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (pp *CommandParamSet) Scan(value interface{}) error {
|
||||
switch value.(type) {
|
||||
case nil:
|
||||
*pp = CommandParamSet{}
|
||||
case []uint8:
|
||||
if err := json.Unmarshal(value.([]byte), pp); err != nil {
|
||||
return errors.Wrapf(err, "Can not scan '%v' into CommandParamSet", value)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pp CommandParamSet) Value() (driver.Value, error) {
|
||||
return json.Marshal(pp)
|
||||
}
|
||||
@@ -87,6 +87,8 @@ func (sess *Session) connected() {
|
||||
})
|
||||
}
|
||||
|
||||
sess.sendReply(payload.Commands(types.Preset))
|
||||
|
||||
// Tell everyone that user has connected
|
||||
sess.sendToAll(&outgoing.Connected{UserID: payload.Uint64toa(sess.user.Identity())})
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ func (s *Session) dispatch(raw []byte) error {
|
||||
|
||||
case p.Users != nil:
|
||||
return s.userList(ctx, p.Users)
|
||||
|
||||
case p.ExecCommand != nil:
|
||||
return s.execCommand(ctx, p.ExecCommand)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/titpetric/factory"
|
||||
|
||||
"github.com/crusttech/crust/internal/payload"
|
||||
"github.com/crusttech/crust/internal/payload/incoming"
|
||||
"github.com/crusttech/crust/internal/payload/outgoing"
|
||||
"github.com/crusttech/crust/sam/types"
|
||||
)
|
||||
|
||||
func (s *Session) execCommand(ctx context.Context, c *incoming.ExecCommand) error {
|
||||
// @todo: check access / can we join this channel (should be done by service layer)
|
||||
|
||||
log.Printf("Received command '%s(%v)", c.Command, c.Params)
|
||||
|
||||
switch c.Command {
|
||||
case "echo":
|
||||
if c.Input != "" {
|
||||
user, err := s.svc.user.With(ctx).FindByID(s.user.Identity())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.sendReply(&outgoing.Message{
|
||||
ID: payload.Uint64toa(factory.Sonyflake.NextID()),
|
||||
User: payload.User(user),
|
||||
CreatedAt: time.Now(),
|
||||
Type: "hallucination",
|
||||
ChannelID: c.ChannelID,
|
||||
Message: c.Input})
|
||||
}
|
||||
|
||||
case "shrug":
|
||||
msg := &types.Message{
|
||||
ChannelID: payload.ParseUInt64(c.ChannelID),
|
||||
Message: "¯\\_(ツ)_/¯",
|
||||
}
|
||||
|
||||
if c.Input != "" {
|
||||
msg.Message = c.Input + " " + msg.Message
|
||||
}
|
||||
_, err := s.svc.msg.With(ctx).Create(msg)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user