3
0

Add support for commands

This commit is contained in:
Denis Arh
2018-10-04 18:02:33 +02:00
parent 9b67f504f4
commit cbc83cb515
9 changed files with 187 additions and 0 deletions
+10
View File
@@ -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"`
}
)
+2
View File
@@ -19,4 +19,6 @@ type Payload struct {
*MessageDelete `json:"deleteMessage"`
*Users `json:"getUsers"`
*ExecCommand `json:"exec"`
}
+20
View File
@@ -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
}
+18
View File
@@ -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})
}
+2
View File
@@ -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
+77
View File
@@ -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)
}
+2
View File
@@ -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())})
}
+3
View File
@@ -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
+53
View File
@@ -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
}