Skip to content

Commit

Permalink
pm handler, moving around data
Browse files Browse the repository at this point in the history
  • Loading branch information
voloshink committed Nov 19, 2017
1 parent 1e1b25c commit 8d8167e
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 34 deletions.
24 changes: 21 additions & 3 deletions eventHandlers.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
package dggchat

type handlers struct {
msgHandler func(*Message)
errHandler func(string)
msgHandler func(Message)
errHandler func(string)
joinHandler func(RoomAction)
quitHandler func(RoomAction)
pmHandler func(PrivateMessage)
}

// AddMessageHandler adds a function that will be called every time a message is received
func (s *Session) AddMessageHandler(fn func(*Message)) {
func (s *Session) AddMessageHandler(fn func(Message)) {
s.handlers.msgHandler = fn
}

// AddErrorHandler adds a function that will be called every time an error message is received
func (s *Session) AddErrorHandler(fn func(string)) {
s.handlers.errHandler = fn
}

// AddJoinHandler adds a function that will be called every time a user join the chat
func (s *Session) AddJoinHandler(fn func(RoomAction)) {
s.handlers.joinHandler = fn
}

// AddQuitHandler adds a function that will be called every time a user quits the chat
func (s *Session) AddQuitHandler(fn func(RoomAction)) {
s.handlers.quitHandler = fn
}

// AddPMHandler adds a function that will be called every time a private message is received
func (s *Session) AddPMHandler(fn func(PrivateMessage)) {
s.handlers.pmHandler = fn
}
37 changes: 30 additions & 7 deletions messageStructs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dggchat

import (
"strings"
"time"
)

Expand Down Expand Up @@ -45,10 +46,9 @@ const (
type (
// Message reprents a normal dgg chat message
Message struct {
Sender string
Sender User
Timestamp time.Time
Message string
Features Features
}

message struct {
Expand All @@ -69,23 +69,46 @@ type (
Features []string `json:"features"`
}

// RoomAction represents a user joining or quitting the chat
RoomAction struct {
User User
Timestamp time.Time
}

roomAction struct {
Nick string `json:"nick"`
Features []string `json:"features"`
Timestamp int64 `json:"timestamp"`
}

// Features contains a list of different user features
Features []string
// PrivateMessage represents a received private message from a user
PrivateMessage struct {
User User
Message string
Timestamp time.Time
ID int
}

privateMessage struct {
MessageID int `json:"messageid"`
Timestamp int64 `json:"timestamp"`
Nick string `json:"nick"`
Data string `json:"data"`
}
)

// HasFeature returns true if a feature is in the features list
func (f Features) HasFeature(s string) bool {
for _, feature := range f {
// HasFeature returns true if user has given feature
func (u *User) HasFeature(s string) bool {
for _, feature := range u.Features {
if feature == s {
return true
}
}

return false
}

// IsAction returns true if the message was an action (/me)
func (m *Message) IsAction() bool {
return strings.HasPrefix(m.Message, "/me ")
}
66 changes: 54 additions & 12 deletions parsers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,85 @@ package dggchat

import (
"encoding/json"
"strings"
"time"
)

func parseMessage(s string) (*Message, error) {
func parseMessage(s string) (Message, error) {
var m message
err := json.Unmarshal([]byte(s), &m)
if err != nil {
return nil, err
return Message{}, err
}

message := &Message{
Sender: m.Nick,
Timestamp: time.Unix(m.Timestamp/1000, 0),
user := User{
Nick: m.Nick,
Features: m.Features,
}

message := Message{
Sender: user,
Timestamp: unixToTime(m.Timestamp),
Message: m.Data,
Features: m.Features,
}

return message, nil
}

func parseNames(s string) (*namesMessage, error) {
func parseNames(s string) (namesMessage, error) {
var nm namesMessage
err := json.Unmarshal([]byte(s), &nm)
if err != nil {
return nil, err
return namesMessage{}, err
}

return &nm, nil
return nm, nil
}

func parseRoomAction(s string) (*roomAction, error) {
func parseRoomAction(s string) (RoomAction, error) {
var ra roomAction

err := json.Unmarshal([]byte(s), &ra)
if err != nil {
return nil, err
return RoomAction{}, err
}

roomAction := RoomAction{
User: User{
Nick: ra.Nick,
Features: ra.Features,
},
Timestamp: unixToTime(ra.Timestamp),
}

return roomAction, nil
}

func parseErrorMessage(s string) string {
return strings.Replace(s, `"`, "", -1)
}

func parsePrivateMessage(s string) (PrivateMessage, error) {
var pm privateMessage

err := json.Unmarshal([]byte(s), &pm)
if err != nil {
return PrivateMessage{}, err
}

return &ra, nil
privateMessage := PrivateMessage{
User: User{
Nick: pm.Nick,
Features: make([]string, 0),
},
ID: pm.MessageID,
Message: pm.Data,
Timestamp: unixToTime(pm.Timestamp),
}

return privateMessage, nil
}

func unixToTime(stamp int64) time.Time {
return time.Unix(stamp/1000, 0)
}
85 changes: 73 additions & 12 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type Session struct {
// on a websocket that is already open
var ErrAlreadyOpen = errors.New("web socket is already open")

// ErrReadOnly is thrown when attempting to send messages using a read-only session
var ErrReadOnly = errors.New("session is read-only")

var wsURL = url.URL{Scheme: "wss", Host: "www.destiny.gg", Path: "/ws"}

// Open opens a websocket connection to destinygg chat
Expand Down Expand Up @@ -97,25 +100,47 @@ func (s *Session) listen(ws *websocket.Conn, listening <-chan bool) {

switch mType {
case "MSG":
if s.handlers.msgHandler == nil {
continue
}

m, err := parseMessage(mContent)
if err != nil {
continue
}

if s.handlers.msgHandler != nil {
s.handlers.msgHandler(m)
}
s.handlers.msgHandler(m)
case "MUTE":
case "UNMUTE":
case "BAN":
case "UNBAN":
case "SUBONLY":
// case "PING":
// case "PONG":
case "BROADCAST":
case "PRIVMSG":
if s.handlers.pmHandler == nil {
continue
}

pm, err := parsePrivateMessage(mContent)
if err != nil {
continue
}

u, found := s.GetUser(pm.User.Nick)
if found {
pm.User = u
}

s.handlers.pmHandler(pm)
case "PRIVMSGSENT":
case "PING":
case "PONG":
case "ERR":
errMessage := strings.Replace(mContent, `"`, "", -1)
if s.handlers.errHandler == nil {
continue
}

errMessage := parseErrorMessage(mContent)
s.handlers.errHandler(errMessage)
case "NAMES":
n, err := parseNames(mContent)
Expand All @@ -131,19 +156,22 @@ func (s *Session) listen(ws *websocket.Conn, listening <-chan bool) {
continue
}

user := User{
Nick: ra.Nick,
Features: ra.Features,
}
s.state.addUser(ra.User)

s.state.addUser(user)
if s.handlers.joinHandler != nil {
s.handlers.joinHandler(ra)
}
case "QUIT":
ra, err := parseRoomAction(mContent)
if err != nil {
continue
}

s.state.removeUser(ra.Nick)
s.state.removeUser(ra.User.Nick)

if s.handlers.quitHandler != nil {
s.handlers.quitHandler(ra)
}
}

select {
Expand Down Expand Up @@ -187,3 +215,36 @@ func (s *Session) GetUser(name string) (User, bool) {

return User{}, false
}

// SendMessage sends the given string as a message to chat
// Note: a return error of nil does not guarantee successful delivery
// Monitor for error events to ensure the message was sent with no errors
func (s *Session) SendMessage(message string) error {
if s.readOnly {
return ErrReadOnly
}
m := fmt.Sprintf(`MSG {"data":"%s"}`, message)
err := s.ws.WriteMessage(websocket.TextMessage, []byte(m))
return err
}

// SendAction calls the SendMessage method but also adds
// "/me" in front of the message to make it a chat action
// same caveat with the returned error value applies
func (s *Session) SendAction(message string) error {
err := s.SendMessage(fmt.Sprintf("/me %s", message))
return err
}

// SendPrivateMessage sends the given user a private message
// Note: a return error of nil does not guarantee successful delivery
// Monitor for error events to ensure the message was sent with no errors
func (s *Session) SendPrivateMessage(nick string, message string) error {
if s.readOnly {
return ErrReadOnly
}

m := fmt.Sprintf(`PRIVMSG {"data":"%s", "nick":"%s"}`, message, nick)
err := s.ws.WriteMessage(websocket.TextMessage, []byte(m))
return err
}

0 comments on commit 8d8167e

Please sign in to comment.