Skip to content

Commit

Permalink
Merge pull request #179 from yannismate/yannismate/feature/reply-support
Browse files Browse the repository at this point in the history
Added support for replies
  • Loading branch information
gempir authored May 1, 2022
2 parents 3ec8e32 + 966fd1e commit fde60d2
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 0 deletions.
16 changes: 16 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ type PrivateMessage struct {
Bits int
Action bool
FirstMessage bool
Reply *Reply
}

type Reply struct {
ParentMsgID string
ParentUserID string
ParentUserLogin string
ParentDisplayName string
ParentMsgBody string
}

// GetType implements the Message interface, and returns this message's type
Expand Down Expand Up @@ -561,6 +570,13 @@ func (c *Client) Say(channel, text string) {
c.send(fmt.Sprintf("PRIVMSG #%s :%s", channel, text))
}

// Reply to a message previously sent in the same channel using the twitch reply feature
func (c *Client) Reply(channel, parentMsgId string, text string) {
channel = strings.ToLower(channel)

c.send(fmt.Sprintf("@reply-parent-msg-id=%s PRIVMSG #%s :%s", parentMsgId, channel, text))
}

// Whisper write something in private to someone on twitch
// whispers are heavily spam protected
// so your message might get blocked because of this
Expand Down
33 changes: 33 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,39 @@ func TestCanSayMessage(t *testing.T) {
assertStringsEqual(t, "PRIVMSG #gempir :"+testMessage, received)
}

func TestCanReplyMessage(t *testing.T) {
t.Parallel()
testMessage := "Do not go gentle into that good night."
testParentMessageId := "b34ccfc7-4977-403a-8a94-33c6bac34fb8"

waitEnd := make(chan struct{})
var received string

host := startServer(t, nothingOnConnect, func(message string) {
if strings.HasPrefix(message, "@reply") {
received = message
close(waitEnd)
}
})

client := newTestClient(host)

client.OnConnect(func() {
client.Reply("gempir", testParentMessageId, testMessage)
})

go client.Connect()

// wait for server to receive message
select {
case <-waitEnd:
case <-time.After(time.Second * 3):
t.Fatal("no privmsg received")
}

assertStringsEqual(t, "@reply-parent-msg-id="+testParentMessageId+" PRIVMSG #gempir :"+testMessage, received)
}

func TestCanWhisperMessage(t *testing.T) {
t.Parallel()
testMessage := "Do not go gentle into that good night."
Expand Down
12 changes: 12 additions & 0 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@ func parseWhisperMessage(message *ircMessage) Message {
}

func parsePrivateMessage(message *ircMessage) Message {
var reply *Reply
if _, ok := message.Tags["reply-parent-msg-id"]; ok {
reply = &Reply{
ParentMsgID: message.Tags["reply-parent-msg-id"],
ParentUserID: message.Tags["reply-parent-user-id"],
ParentUserLogin: message.Tags["reply-parent-user-login"],
ParentDisplayName: message.Tags["reply-parent-display-name"],
ParentMsgBody: message.Tags["reply-parent-msg-body"],
}
}

privateMessage := PrivateMessage{
User: parseUser(message),

Expand All @@ -216,6 +227,7 @@ func parsePrivateMessage(message *ircMessage) Message {
RoomID: message.Tags["room-id"],
ID: message.Tags["id"],
Time: parseTime(message.Tags["tmi-sent-ts"]),
Reply: reply,
}

if len(message.Params) == 2 {
Expand Down
37 changes: 37 additions & 0 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,35 @@ func TestCanParsePRIVMSGMessage(t *testing.T) {
FirstMessage: false,
},
},
{
"Reply Message",
"@badges=premium/1;color=#DAA520;display-name=FletcherCodes;emotes=;flags=;id=6efffc70-27a1-4637-9111-44e5104bb7da;mod=0;reply-parent-msg-id=b34ccfc7-4977-403a-8a94-33c6bac34fb8;reply-parent-user-id=71601484;reply-parent-user-login=yannismate;reply-parent-display-name=Yannismate;reply-parent-msg-body=This\\smessage\\scontains\\sspecial\\schars\\s!\\:;room-id=408892348;subscriber=0;tmi-sent-ts=1551473087761;turbo=0;user-id=269899575;user-type= :[email protected] PRIVMSG #clippyassistant :Chew your food slower... it's healthier",
PrivateMessage{
User: User{
ID: "269899575",
Name: "fletchercodes",
DisplayName: "FletcherCodes",
Color: "#DAA520",
Badges: map[string]int{
"premium": 1,
},
},
Type: PRIVMSG,
RawType: "PRIVMSG",
Message: "Chew your food slower... it's healthier",
Channel: "clippyassistant",
RoomID: "408892348",
ID: "6efffc70-27a1-4637-9111-44e5104bb7da",
FirstMessage: false,
Reply: &Reply{
ParentMsgID: "b34ccfc7-4977-403a-8a94-33c6bac34fb8",
ParentUserID: "71601484",
ParentUserLogin: "yannismate",
ParentDisplayName: "Yannismate",
ParentMsgBody: "This message contains special chars !;",
},
},
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -226,6 +255,14 @@ func TestCanParsePRIVMSGMessage(t *testing.T) {
assertIntsEqual(t, len(tt.expectedMessage.Emotes), len(privateMessage.Emotes))
assertIntsEqual(t, tt.expectedMessage.Bits, privateMessage.Bits)
assertBoolEqual(t, tt.expectedMessage.FirstMessage, privateMessage.FirstMessage)

if tt.expectedMessage.Reply != nil {
assertStringsEqual(t, tt.expectedMessage.Reply.ParentMsgID, privateMessage.Reply.ParentMsgID)
assertStringsEqual(t, tt.expectedMessage.Reply.ParentUserID, privateMessage.Reply.ParentUserID)
assertStringsEqual(t, tt.expectedMessage.Reply.ParentUserLogin, privateMessage.Reply.ParentUserLogin)
assertStringsEqual(t, tt.expectedMessage.Reply.ParentDisplayName, privateMessage.Reply.ParentDisplayName)
assertStringsEqual(t, tt.expectedMessage.Reply.ParentMsgBody, privateMessage.Reply.ParentMsgBody)
}
})
}(tt)
}
Expand Down

0 comments on commit fde60d2

Please sign in to comment.