Skip to content

Quote original thread message if enough time has passed. #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
)

type slack struct {
Token string
Token string
ThreadQuoteIntervalSec int
}

// Config holds configuration data for Tanya
Expand Down
7 changes: 5 additions & 2 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@

[gateway.slack]
# Slack client token
token = ""
Token = ""
# Time in seconds since the last thread reply to trigger quoting of the original message
# Set to 0 to disable original message quoting entirely
ThreadQuoteIntervalSec = 0

# Multiple gateway sections can be specified for multiple workspaces
[[gateway]]
[gateway.irc]
ListenAddr = ":6668"

[gateway.slack]
token = ""
Token = ""
122 changes: 84 additions & 38 deletions gateway/message_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,42 +30,7 @@ func (sc *SlackClient) handleMessageEvent(incomingChan chan<- *SlackEvent, messa
return
}

var sender *SlackUser
if messageData.User != "" {
var err error
if sender, err = sc.ResolveUser(messageData.User); err != nil {
log.Printf("%s could not resolve user for message [%v]: %+v", sc.Tag(), err, messageData)
return
}
}

var target string
wasSenderSwapped := false
if messageData.Channel != "" {
if isDmChannel(messageData.Channel) {
target = sc.self.Nick

// If we sent this DM, then the sender needs to be faked to the other user
// because IRC clients can't display DMs done by others on your behalf
if sender == sc.self {
otherUser, err := sc.ResolveDMToUser(messageData.Channel)
if err != nil {
log.Printf("%s could not resolve DM user for message [%v]: %+v", sc.Tag(), err, messageData)
return
}

sender = otherUser
wasSenderSwapped = true
}
} else {
channel, err := sc.ResolveChannel(messageData.Channel)
if err != nil {
log.Printf("%s could not resolve channel for message [%v]: %+v", sc.Tag(), err, messageData)
return
}
target = channel.Name
}
}
sender, target, wasSenderSwapped := sc.resolveMessageEndpoints(&messageData.Msg)

switch messageData.SubType {
case "", "pinned_item", "thread_broadcast":
Expand Down Expand Up @@ -193,11 +158,92 @@ func (sc *SlackClient) handleMessageEvent(incomingChan chan<- *SlackEvent, messa
return

case "message_replied":
// As far as I can tell, this is only useful for updating the reply count of a message thread.
return
// Handle thread replies by maybe quoting the parent message if enough time has passed.
subMessage := messageData.SubMessage
if subMessage == nil {
log.Printf("%s message_replied with missing submessage: %+v SubMessage:%+v",
sc.Tag(), messageData, messageData.SubMessage)
return
}

if subMessage.Type != "message" {
log.Printf("%s message_replied with unexpected submessage type: %+v SubMessage:%+v",
sc.Tag(), messageData, messageData.SubMessage)
return
}

if !sc.shouldQuoteThreadParent(subMessage.ThreadTimestamp, messageData.Timestamp) {
return
}

sender, _, wasSenderSwapped = sc.resolveMessageEndpoints(subMessage)
if sender == nil || target == "" {
return
}

messageText := sc.ParseMessageText(subMessage.Text)
for _, attachment := range subMessage.Attachments {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're overwriting messageText each time, why don't we just grab the first or last attachment in subMessage.Attachments instead?

if messageText == "" {
messageText = sc.ParseMessageText(attachment.Fallback)
} else {
messageText = messageText + "\n" + sc.ParseMessageText(attachment.Fallback)
}
}

// >be me
messageText = "><" + sender.Nick + "> " + messageText

// If we had swapped senders earlier, make sure the message reflects this swap
if wasSenderSwapped {
messageText = "[" + sc.self.Nick + "] " + messageText
}

// Only quote the first line of a multi-line message.
messageEvents := messageTextToEvents(sender, target, messageText)
if len(messageEvents) > 0 {
incomingChan <- messageTextToEvents(sender, target, messageText)[0]
}

default:
log.Printf("%s unhandled message sub-type [%v]: %+v SubMessage:%+v",
sc.Tag(), messageData.SubType, messageData, messageData.SubMessage)
}
}

func (sc *SlackClient) resolveMessageEndpoints(messageData *slack.Msg) (sender *SlackUser, target string, wasSenderSwapped bool) {
if messageData.User != "" {
var err error
if sender, err = sc.ResolveUser(messageData.User); err != nil {
log.Printf("%s could not resolve user for message [%v]: %+v", sc.Tag(), err, messageData)
return
}
}

if messageData.Channel != "" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to un-nest the conditional here and do what you did above?

if messageData.Channel == "" {
    return
}

and then do the rest of the logic?

if isDmChannel(messageData.Channel) {
target = sc.self.Nick

// If we sent this DM, then the sender needs to be faked to the other user
// because IRC clients can't display DMs done by others on your behalf
if sender == sc.self {
otherUser, err := sc.ResolveDMToUser(messageData.Channel)
if err != nil {
log.Printf("%s could not resolve DM user for message [%v]: %+v", sc.Tag(), err, messageData)
return
}

sender = otherUser
wasSenderSwapped = true
}
} else {
channel, err := sc.ResolveChannel(messageData.Channel)
if err != nil {
log.Printf("%s could not resolve channel for message [%v]: %+v", sc.Tag(), err, messageData)
return
}
target = channel.Name
}
}

return
}
6 changes: 3 additions & 3 deletions gateway/message_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func TestSlackClient_ParseMessageText(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sc := NewSlackClient()
sc := NewSlackClient(0)
sc.channelInfo = tt.fields.channelInfo
sc.userInfo = tt.fields.userInfo

Expand Down Expand Up @@ -122,7 +122,7 @@ func TestSlackClient_ParseMessageTextWithOptions(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sc := NewSlackClient()
sc := NewSlackClient(0)
sc.channelInfo = tt.fields.channelInfo
sc.userInfo = tt.fields.userInfo

Expand Down Expand Up @@ -207,7 +207,7 @@ func TestSlackClient_UnparseMessageText(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sc := NewSlackClient()
sc := NewSlackClient(0)
sc.channelInfo = tt.fields.channelInfo
sc.userInfo = tt.fields.userInfo
sc.regenerateReverseMappings()
Expand Down
Loading