1package bdiscord
2
3import (
4	"github.com/42wim/matterbridge/bridge/config"
5	"github.com/matterbridge/discordgo"
6)
7
8func (b *Bdiscord) messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) { //nolint:unparam
9	rmsg := config.Message{Account: b.Account, ID: m.ID, Event: config.EventMsgDelete, Text: config.EventMsgDelete}
10	rmsg.Channel = b.getChannelName(m.ChannelID)
11
12	b.Log.Debugf("<= Sending message from %s to gateway", b.Account)
13	b.Log.Debugf("<= Message is %#v", rmsg)
14	b.Remote <- rmsg
15}
16
17// TODO(qaisjp): if other bridges support bulk deletions, it could be fanned out centrally
18func (b *Bdiscord) messageDeleteBulk(s *discordgo.Session, m *discordgo.MessageDeleteBulk) { //nolint:unparam
19	for _, msgID := range m.Messages {
20		rmsg := config.Message{
21			Account: b.Account,
22			ID:      msgID,
23			Event:   config.EventMsgDelete,
24			Text:    config.EventMsgDelete,
25			Channel: b.getChannelName(m.ChannelID),
26		}
27
28		b.Log.Debugf("<= Sending message from %s to gateway", b.Account)
29		b.Log.Debugf("<= Message is %#v", rmsg)
30		b.Remote <- rmsg
31	}
32}
33
34func (b *Bdiscord) messageTyping(s *discordgo.Session, m *discordgo.TypingStart) {
35	if !b.GetBool("ShowUserTyping") {
36		return
37	}
38
39	// Ignore our own typing messages
40	if m.UserID == b.userID {
41		return
42	}
43
44	rmsg := config.Message{Account: b.Account, Event: config.EventUserTyping}
45	rmsg.Channel = b.getChannelName(m.ChannelID)
46	b.Remote <- rmsg
47}
48
49func (b *Bdiscord) messageUpdate(s *discordgo.Session, m *discordgo.MessageUpdate) { //nolint:unparam
50	if b.GetBool("EditDisable") {
51		return
52	}
53	// only when message is actually edited
54	if m.Message.EditedTimestamp != "" {
55		b.Log.Debugf("Sending edit message")
56		m.Content += b.GetString("EditSuffix")
57		msg := &discordgo.MessageCreate{
58			Message: m.Message,
59		}
60		b.messageCreate(s, msg)
61	}
62}
63
64func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { //nolint:unparam
65	var err error
66
67	// not relay our own messages
68	if m.Author.Username == b.nick {
69		return
70	}
71	// if using webhooks, do not relay if it's ours
72	if m.Author.Bot && b.transmitter.HasWebhook(m.Author.ID) {
73		return
74	}
75
76	// add the url of the attachments to content
77	if len(m.Attachments) > 0 {
78		for _, attach := range m.Attachments {
79			m.Content = m.Content + "\n" + attach.URL
80		}
81	}
82
83	rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", UserID: m.Author.ID, ID: m.ID}
84
85	if m.Content != "" {
86		b.Log.Debugf("== Receiving event %#v", m.Message)
87		m.Message.Content = b.replaceChannelMentions(m.Message.Content)
88		rmsg.Text, err = m.ContentWithMoreMentionsReplaced(b.c)
89		if err != nil {
90			b.Log.Errorf("ContentWithMoreMentionsReplaced failed: %s", err)
91			rmsg.Text = m.ContentWithMentionsReplaced()
92		}
93	}
94
95	// set channel name
96	rmsg.Channel = b.getChannelName(m.ChannelID)
97
98	fromWebhook := m.WebhookID != ""
99	if !fromWebhook && !b.GetBool("UseUserName") {
100		rmsg.Username = b.getNick(m.Author, m.GuildID)
101	} else {
102		rmsg.Username = m.Author.Username
103		if !fromWebhook && b.GetBool("UseDiscriminator") {
104			rmsg.Username += "#" + m.Author.Discriminator
105		}
106	}
107
108	// if we have embedded content add it to text
109	if b.GetBool("ShowEmbeds") && m.Message.Embeds != nil {
110		for _, embed := range m.Message.Embeds {
111			rmsg.Text += handleEmbed(embed)
112		}
113	}
114
115	// no empty messages
116	if rmsg.Text == "" {
117		return
118	}
119
120	// do we have a /me action
121	var ok bool
122	rmsg.Text, ok = b.replaceAction(rmsg.Text)
123	if ok {
124		rmsg.Event = config.EventUserAction
125	}
126
127	// Replace emotes
128	rmsg.Text = replaceEmotes(rmsg.Text)
129
130	// Add our parent id if it exists, and if it's not referring to a message in another channel
131	if ref := m.MessageReference; ref != nil && ref.ChannelID == m.ChannelID {
132		rmsg.ParentID = ref.MessageID
133	}
134
135	b.Log.Debugf("<= Sending message from %s on %s to gateway", m.Author.Username, b.Account)
136	b.Log.Debugf("<= Message is %#v", rmsg)
137	b.Remote <- rmsg
138}
139
140func (b *Bdiscord) memberUpdate(s *discordgo.Session, m *discordgo.GuildMemberUpdate) {
141	if m.Member == nil {
142		b.Log.Warnf("Received member update with no member information: %#v", m)
143	}
144
145	b.membersMutex.Lock()
146	defer b.membersMutex.Unlock()
147
148	if currMember, ok := b.userMemberMap[m.Member.User.ID]; ok {
149		b.Log.Debugf(
150			"%s: memberupdate: user %s (nick %s) changes nick to %s",
151			b.Account,
152			m.Member.User.Username,
153			b.userMemberMap[m.Member.User.ID].Nick,
154			m.Member.Nick,
155		)
156		delete(b.nickMemberMap, currMember.User.Username)
157		delete(b.nickMemberMap, currMember.Nick)
158		delete(b.userMemberMap, m.Member.User.ID)
159	}
160	b.userMemberMap[m.Member.User.ID] = m.Member
161	b.nickMemberMap[m.Member.User.Username] = m.Member
162	if m.Member.Nick != "" {
163		b.nickMemberMap[m.Member.Nick] = m.Member
164	}
165}
166
167func (b *Bdiscord) memberAdd(s *discordgo.Session, m *discordgo.GuildMemberAdd) {
168	if m.Member == nil {
169		b.Log.Warnf("Received member update with no member information: %#v", m)
170		return
171	}
172	username := m.Member.User.Username
173	if m.Member.Nick != "" {
174		username = m.Member.Nick
175	}
176
177	rmsg := config.Message{
178		Account:  b.Account,
179		Event:    config.EventJoinLeave,
180		Username: "system",
181		Text:     username + " joins",
182	}
183	b.Log.Debugf("<= Sending message from %s to gateway", b.Account)
184	b.Log.Debugf("<= Message is %#v", rmsg)
185	b.Remote <- rmsg
186}
187
188func (b *Bdiscord) memberRemove(s *discordgo.Session, m *discordgo.GuildMemberRemove) {
189	if m.Member == nil {
190		b.Log.Warnf("Received member update with no member information: %#v", m)
191		return
192	}
193	username := m.Member.User.Username
194	if m.Member.Nick != "" {
195		username = m.Member.Nick
196	}
197
198	rmsg := config.Message{
199		Account:  b.Account,
200		Event:    config.EventJoinLeave,
201		Username: "system",
202		Text:     username + " leaves",
203	}
204	b.Log.Debugf("<= Sending message from %s to gateway", b.Account)
205	b.Log.Debugf("<= Message is %#v", rmsg)
206	b.Remote <- rmsg
207}
208
209func handleEmbed(embed *discordgo.MessageEmbed) string {
210	var t []string
211	var result string
212
213	t = append(t, embed.Title)
214	t = append(t, embed.Description)
215	t = append(t, embed.URL)
216
217	i := 0
218	for _, e := range t {
219		if e == "" {
220			continue
221		}
222
223		i++
224		if i == 1 {
225			result += " embed: " + e
226			continue
227		}
228
229		result += " - " + e
230	}
231
232	if result != "" {
233		result += "\n"
234	}
235
236	return result
237}
238