Skip to content

Commit 96f6b27

Browse files
committed
Integration branch for PM and Formatting.
1 parent c84ad74 commit 96f6b27

File tree

7 files changed

+105
-26
lines changed

7 files changed

+105
-26
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ The config file is a yaml formatted file with the following fields:
6868

6969
| name | requires restart | default | optional | description |
7070
| ------------------- | ---------------- | ---------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
71+
| `discriminator` | Yes | | No | The network discriminator used for when PMing from Discord to IRC nick |
7172
| `avatar_url` | No | `https://ui-avatars.com/api/?name=${USERNAME}` | Yes | The URL for the API to use to tell Discord what Avatar to use for a User when the user's avatar cannot be found at Discord already. |
7273
| `discord_token` | Yes | | No | [The bot user token](https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token) |
7374
| `irc_server` | Yes | | No | IRC server address |

bridge/bridge.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ type Config struct {
2929
NickServIdentify string // string: "[account] password"
3030
PuppetUsername string // Username to connect to IRC with
3131

32+
DiscordFormat map[string]string // formatting for non-PRIVMSG relays from IRC to Discord
33+
IRCFormat string // format for messages relayed in simple mode
34+
3235
// NoTLS constrols whether to use TLS at all when connecting to the IRC server
3336
NoTLS bool
3437

bridge/discord.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func (d *discordBot) publishMessage(s *discordgo.Session, m *discordgo.Message,
140140
pmTarget := ""
141141
for _, channel := range d.State.PrivateChannels {
142142
if channel.ID == m.ChannelID {
143-
pmTarget, content = pmTargetFromContent(content)
143+
pmTarget, content = pmTargetFromContent(content, d.bridge.Config.Discriminator)
144144

145145
// if the target could not be deduced. tell them this.
146146
if pmTarget == "" {
@@ -445,7 +445,7 @@ func GetMemberNick(m *discordgo.Member) string {
445445
//
446446
// Returns empty string if the nick could not be deduced.
447447
// Also returns the content without the nick
448-
func pmTargetFromContent(content string) (nick, newContent string) {
448+
func pmTargetFromContent(content string, discriminator string) (nick, newContent string) {
449449
// Pull out substrings
450450
// "qais,come on, i need this!" gives []string{"qais", "come on, i need this!"}
451451
subs := strings.SplitN(content, ",", 2)
@@ -457,6 +457,19 @@ func pmTargetFromContent(content string) (nick, newContent string) {
457457
nick = subs[0]
458458
newContent = strings.TrimPrefix(subs[1], " ")
459459

460+
nickParts := strings.Split(nick, "@")
461+
462+
// we were given an invalid nick if we can't split it into 2 parts
463+
if len(nickParts) < 2 {
464+
return "", ""
465+
}
466+
467+
if nickParts[1] != discriminator {
468+
return "", ""
469+
}
470+
471+
nick = nickParts[0]
472+
460473
// check if name is a valid nick
461474
for _, c := range []byte(nick) {
462475
if !ircnick.IsNickChar(c) {

bridge/irc_connection.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func (i *ircConnection) introducePM(nick string) {
9191
i.pmNoticed = true
9292
_, err := d.ChannelMessageSend(
9393
i.pmDiscordChannel,
94-
fmt.Sprintf("To reply type: %s@%s, message", nick, i.manager.bridge.Config.Discriminator))
94+
fmt.Sprintf("To reply type: `%s@%s, your message here`", nick, i.manager.bridge.Config.Discriminator))
9595
if err != nil {
9696
log.Warnln("Could not send pmNotice", i.discord, err)
9797
return
@@ -117,7 +117,7 @@ func (i *ircConnection) OnPrivateMessage(e *irc.Event) {
117117

118118
i.introducePM(e.Nick)
119119

120-
msg := fmt.Sprintf("%s,%s - %s@%s: %s", e.Connection.Server, e.Source, e.Nick, e.Message())
120+
msg := i.manager.formatDiscordMessage("PM", e, e.Message(), "")
121121
_, err := d.ChannelMessageSend(i.pmDiscordChannel, msg)
122122
if err != nil {
123123
log.Warnln("Could not send PM", i.discord, err)

bridge/irc_listener.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,29 +95,28 @@ func (i *ircListener) OnJoinQuitCallback(event *irc.Event) {
9595
return
9696
}
9797

98-
who := event.Nick
99-
message := event.Nick
100-
id := " (" + event.User + "@" + event.Host + ") "
98+
message := ""
99+
content := ""
100+
target := ""
101+
manager := i.bridge.ircManager
101102

102103
switch event.Code {
103104
case "JOIN":
104-
message += " joined" + id
105+
message = manager.formatDiscordMessage(event.Code, event, "", "")
105106
case "PART":
106-
message += " left" + id
107107
if len(event.Arguments) > 1 {
108-
message += ": " + event.Arguments[1]
108+
content = event.Arguments[1]
109109
}
110+
message = manager.formatDiscordMessage(event.Code, event, content, "")
110111
case "QUIT":
111-
message += " quit" + id
112-
113-
reason := event.Nick
112+
content := event.Nick
114113
if len(event.Arguments) == 1 {
115-
reason = event.Arguments[0]
114+
content = event.Arguments[0]
116115
}
117-
message += "Quit: " + reason
116+
message = manager.formatDiscordMessage(event.Code, event, content, "")
118117
case "KICK":
119-
who = event.Arguments[1]
120-
message = event.Arguments[1] + " was kicked by " + event.Nick + ": " + event.Arguments[2]
118+
target, content = event.Arguments[1], event.Arguments[2]
119+
message = manager.formatDiscordMessage(event.Code, event, content, target)
121120
}
122121

123122
msg := IRCMessage{
@@ -132,10 +131,10 @@ func (i *ircListener) OnJoinQuitCallback(event *irc.Event) {
132131
channel := m.IRCChannel
133132
channelObj, ok := i.Connection.Channels[channel]
134133
if !ok {
135-
log.WithField("channel", channel).WithField("who", who).Warnln("Trying to process QUIT. Channel not found in irc listener cache.")
134+
log.WithField("channel", channel).WithField("who", event.Nick).Warnln("Trying to process QUIT. Channel not found in irc listener cache.")
136135
continue
137136
}
138-
if _, ok := channelObj.Users[who]; !ok {
137+
if _, ok := channelObj.Users[event.Nick]; !ok {
139138
continue
140139
}
141140
msg.IRCChannel = channel

bridge/irc_manager.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,15 @@ func (m *IRCManager) generateNickname(discord DiscordUser) string {
323323
return newNick
324324
}
325325

326+
func (m *IRCManager) formatIRCMessage(message *DiscordMessage, content string) string {
327+
msg := m.bridge.Config.IRCFormat
328+
length := len(message.Author.Username)
329+
msg = strings.ReplaceAll(msg, "${USER}", message.Author.Username[:1]+"\u200B"+message.Author.Username[1:length])
330+
msg = strings.ReplaceAll(msg, "${DISCRIMINATOR}", message.Author.Discriminator)
331+
msg = strings.ReplaceAll(msg, "${CONTENT}", content)
332+
return msg
333+
}
334+
326335
// SendMessage sends a broken down Discord Message to a particular IRC channel.
327336
func (m *IRCManager) SendMessage(channel string, msg *DiscordMessage) {
328337
con, ok := m.ircConnections[msg.Author.ID]
@@ -333,14 +342,16 @@ func (m *IRCManager) SendMessage(channel string, msg *DiscordMessage) {
333342

334343
// Person is appearing offline (or the bridge is running in Simple Mode)
335344
if !ok {
336-
length := len(msg.Author.Username)
345+
// length := len(msg.Author.Username)
337346
for _, line := range strings.Split(content, "\n") {
338-
m.bridge.ircListener.Privmsg(channel, fmt.Sprintf(
339-
"<%s#%s> %s",
340-
msg.Author.Username[:1]+"\u200B"+msg.Author.Username[1:length],
341-
msg.Author.Discriminator,
342-
line,
343-
))
347+
// m.bridge.ircListener.Privmsg(channel, fmt.Sprintf(
348+
// "<%s#%s> %s",
349+
// msg.Author.Username[:1]+"\u200B"+msg.Author.Username[1:length],
350+
// msg.Author.Discriminator,
351+
// line,
352+
// ))
353+
354+
m.bridge.ircListener.Privmsg(channel, m.formatIRCMessage(msg, line))
344355
}
345356
return
346357
}
@@ -369,6 +380,24 @@ func (m *IRCManager) SendMessage(channel string, msg *DiscordMessage) {
369380
}
370381
}
371382

383+
func (m *IRCManager) formatDiscordMessage(msgFormat string, e *irc.Event, content string, target string) string {
384+
msg := ""
385+
if format, ok := m.bridge.Config.DiscordFormat[strings.ToLower(msgFormat)]; ok && format != "" {
386+
msg = format
387+
msg = strings.ReplaceAll(msg, "${NICK}", e.Nick)
388+
msg = strings.ReplaceAll(msg, "${IDENT}", e.User)
389+
msg = strings.ReplaceAll(msg, "${HOST}", e.Host)
390+
msg = strings.ReplaceAll(msg, "${CONTENT}", content)
391+
msg = strings.ReplaceAll(msg, "${TARGET}", target)
392+
msg = strings.ReplaceAll(msg, "${SERVER}", e.Connection.Server)
393+
msg = strings.ReplaceAll(msg, "${DISCRIMINATOR}", m.bridge.Config.Discriminator)
394+
} // else {
395+
// should we warn?
396+
//}
397+
398+
return msg
399+
}
400+
372401
// RequestChannels finds all the Discord channels this user belongs to,
373402
// and then find pairings in the global pairings list
374403
// Currently just returns all participating IRC channels

main.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,15 @@ func main() {
8181
*insecure = viper.GetBool("insecure")
8282
}
8383
//
84+
discordFormat := viper.GetStringMapString("discord_format")
85+
discordFormat = setupDiscordFormat(discordFormat)
86+
//
8487
viper.SetDefault("avatar_url", "https://ui-avatars.com/api/?name=${USERNAME}")
8588
avatarURL := viper.GetString("avatar_url")
8689
//
90+
viper.SetDefault("irc_format", "<${USER}#${DISCRIMINATOR}> ${CONTENT}")
91+
ircFormat := viper.GetString("irc_format")
92+
//
8793
viper.SetDefault("irc_listener_name", "~d")
8894
ircUsername := viper.GetString("irc_listener_name") // Name for IRC-side bot, for listening to messages.
8995
// Name to Connect to IRC puppet account with
@@ -122,7 +128,9 @@ func main() {
122128
AvatarURL: avatarURL,
123129
Discriminator: discriminator,
124130
DiscordBotToken: discordBotToken,
131+
DiscordFormat: discordFormat,
125132
GuildID: guildID,
133+
IRCFormat: ircFormat,
126134
IRCListenerName: ircUsername,
127135
IRCServer: ircServer,
128136
IRCServerPass: ircPassword,
@@ -186,6 +194,10 @@ func main() {
186194
SetLogDebug(debug)
187195
}
188196

197+
discordFormat := viper.GetStringMapString("discord_format")
198+
dib.Config.DiscordFormat = setupDiscordFormat(discordFormat)
199+
dib.Config.IRCFormat = viper.GetString("irc_format")
200+
189201
chans := viper.GetStringMapString("channel_mappings")
190202
equalChans := reflect.DeepEqual(chans, channelMappings)
191203
if !equalChans {
@@ -211,6 +223,28 @@ func main() {
211223
dib.Close()
212224
}
213225

226+
func setupDiscordFormat(discordFormat map[string]string) map[string]string {
227+
// lowercase to match that YAML lowercases it
228+
discordFormatDefaults := map[string]string{
229+
<<<<<<< HEAD
230+
=======
231+
"pm": "${SERVER},${NICK}!${IDENT}@${HOST} - ${NICK}@${DISCRIMINATOR}: ${CONTENT}",
232+
>>>>>>> 8bc3ead (Fix case of events to match YAML lower case.)
233+
"join": "_${NICK} joined (${IDENT}@${HOST})_",
234+
"part": "_${NICK} left (${IDENT}@${HOST}) - ${CONTENT}_",
235+
"quit": "_${NICK} quit (${IDENT}@${HOST}) - Quit: ${CONTENT}_",
236+
"kick": "_${TARGET} was kicked by ${NICK} - ${CONTENT}_",
237+
}
238+
239+
for ev, format := range discordFormatDefaults {
240+
if df, ok := discordFormat[ev]; !ok || df == "" {
241+
discordFormat[ev] = format
242+
}
243+
}
244+
245+
return discordFormat
246+
}
247+
214248
func SetLogDebug(debug bool) {
215249
logger := log.StandardLogger()
216250
if debug {

0 commit comments

Comments
 (0)