PIN verification, notifications, multiple notif providers
Discord, Email & Telegram can be enabled, although email is always enabled right now (will fix). Also apparently markdown hyperlinks don't work in Discord, eventually will implement something to convert them to embeds.
This commit is contained in:
+114
-42
@@ -7,22 +7,17 @@ import (
|
||||
dg "github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type DiscordToken struct {
|
||||
Token string
|
||||
ChannelID string
|
||||
UserID string
|
||||
Username string
|
||||
}
|
||||
|
||||
type DiscordDaemon struct {
|
||||
Stopped bool
|
||||
ShutdownChannel chan string
|
||||
bot *dg.Session
|
||||
username string
|
||||
tokens map[string]DiscordToken // map of user IDs to tokens.
|
||||
verifiedTokens []DiscordToken
|
||||
languages map[string]string // Store of languages for user IDs. Added to on first interaction, and loaded from app.storage.discord on start.
|
||||
app *appContext
|
||||
Stopped bool
|
||||
ShutdownChannel chan string
|
||||
bot *dg.Session
|
||||
username string
|
||||
tokens []string
|
||||
verifiedTokens map[string]DiscordUser // Map of tokens to discord users.
|
||||
channelID, channelName string
|
||||
serverChannelName string
|
||||
users map[string]DiscordUser // Map of user IDs to users. Added to on first interaction, and loaded from app.storage.discord on start.
|
||||
app *appContext
|
||||
}
|
||||
|
||||
func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
|
||||
@@ -38,28 +33,39 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
|
||||
Stopped: false,
|
||||
ShutdownChannel: make(chan string),
|
||||
bot: bot,
|
||||
tokens: map[string]DiscordToken{},
|
||||
verifiedTokens: []DiscordToken{},
|
||||
languages: map[string]string{},
|
||||
tokens: []string{},
|
||||
verifiedTokens: map[string]DiscordUser{},
|
||||
users: map[string]DiscordUser{},
|
||||
app: app,
|
||||
}
|
||||
for _, user := range app.storage.discord {
|
||||
if user.Lang != "" {
|
||||
dd.languages[user.ID] = user.Lang
|
||||
}
|
||||
dd.users[user.ID] = user
|
||||
}
|
||||
return dd, nil
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) NewAuthToken(channelID, userID, username string) DiscordToken {
|
||||
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
||||
func (d *DiscordDaemon) NewAuthToken() string {
|
||||
pin := genAuthToken()
|
||||
token := DiscordToken{
|
||||
Token: pin,
|
||||
ChannelID: channelID,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
d.tokens = append(d.tokens, pin)
|
||||
return pin
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) NewUnknownUser(channelID, userID, discrim, username string) DiscordUser {
|
||||
user := DiscordUser{
|
||||
ChannelID: channelID,
|
||||
ID: userID,
|
||||
Username: username,
|
||||
Discriminator: discrim,
|
||||
}
|
||||
return token
|
||||
return user
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) MustGetUser(channelID, userID, discrim, username string) DiscordUser {
|
||||
if user, ok := d.users[userID]; ok {
|
||||
return user
|
||||
}
|
||||
return d.NewUnknownUser(channelID, userID, discrim, username)
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) run() {
|
||||
@@ -70,6 +76,15 @@ func (d *DiscordDaemon) run() {
|
||||
return
|
||||
}
|
||||
d.username = d.bot.State.User.Username
|
||||
// Choose the last guild (server), for now we don't really support multiple anyway
|
||||
guild, err := d.bot.Guild(d.bot.State.Guilds[len(d.bot.State.Guilds)-1].ID)
|
||||
if err != nil {
|
||||
d.app.err.Printf("Discord: Failed to get guild: %v", err)
|
||||
}
|
||||
d.serverChannelName = guild.Name
|
||||
if channel := d.app.config.Section("discord").Key("channel").String(); channel != "" {
|
||||
d.channelName = channel
|
||||
}
|
||||
defer d.bot.Close()
|
||||
<-d.ShutdownChannel
|
||||
d.ShutdownChannel <- "Down"
|
||||
@@ -84,6 +99,22 @@ func (d *DiscordDaemon) Shutdown() {
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) {
|
||||
if m.GuildID != "" && d.channelName != "" {
|
||||
if d.channelID == "" {
|
||||
channel, err := s.Channel(m.ChannelID)
|
||||
if err != nil {
|
||||
d.app.err.Printf("Discord: Couldn't get channel, will monitor all: %v", err)
|
||||
d.channelName = ""
|
||||
}
|
||||
if channel.Name == d.channelName {
|
||||
d.channelID = channel.ID
|
||||
}
|
||||
}
|
||||
if d.channelID != m.ChannelID {
|
||||
d.app.debug.Printf("Discord: Ignoring message as not in specified channel")
|
||||
return
|
||||
}
|
||||
}
|
||||
if m.Author.ID == s.State.User.ID {
|
||||
return
|
||||
}
|
||||
@@ -92,11 +123,13 @@ func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) {
|
||||
return
|
||||
}
|
||||
lang := d.app.storage.lang.chosenTelegramLang
|
||||
if storedLang, ok := d.languages[m.Author.ID]; ok {
|
||||
lang = storedLang
|
||||
if user, ok := d.users[m.Author.ID]; ok {
|
||||
if _, ok := d.app.storage.lang.Telegram[user.Lang]; ok {
|
||||
lang = user.Lang
|
||||
}
|
||||
}
|
||||
switch msg := sects[0]; msg {
|
||||
case d.app.config.Section("telegram").Key("start_command").MustString("!start"):
|
||||
case d.app.config.Section("discord").Key("start_command").MustString("!start"):
|
||||
d.commandStart(s, m, lang)
|
||||
case "!lang":
|
||||
d.commandLang(s, m, sects, lang)
|
||||
@@ -111,8 +144,8 @@ func (d *DiscordDaemon) commandStart(s *dg.Session, m *dg.MessageCreate, lang st
|
||||
d.app.err.Printf("Discord: Failed to create private channel with \"%s\": %v", m.Author.Username, err)
|
||||
return
|
||||
}
|
||||
token := d.NewAuthToken(channel.ID, m.Author.ID, m.Author.Username)
|
||||
d.tokens[m.Author.ID] = token
|
||||
user := d.MustGetUser(channel.ID, m.Author.ID, m.Author.Discriminator, m.Author.Username)
|
||||
d.users[m.Author.ID] = user
|
||||
content := d.app.storage.lang.Telegram[lang].Strings.get("startMessage") + "\n"
|
||||
content += d.app.storage.lang.Telegram[lang].Strings.template("languageMessage", tmpl{"command": "!lang"})
|
||||
_, err = s.ChannelMessageSend(channel.ID, content)
|
||||
@@ -139,7 +172,7 @@ func (d *DiscordDaemon) commandLang(s *dg.Session, m *dg.MessageCreate, sects []
|
||||
return
|
||||
}
|
||||
if _, ok := d.app.storage.lang.Telegram[sects[1]]; ok {
|
||||
d.languages[m.Author.ID] = sects[1]
|
||||
var user DiscordUser
|
||||
for jfID, user := range d.app.storage.discord {
|
||||
if user.ID == m.Author.ID {
|
||||
user.Lang = sects[1]
|
||||
@@ -150,30 +183,69 @@ func (d *DiscordDaemon) commandLang(s *dg.Session, m *dg.MessageCreate, sects []
|
||||
break
|
||||
}
|
||||
}
|
||||
d.users[m.Author.ID] = user
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) commandPIN(s *dg.Session, m *dg.MessageCreate, sects []string, lang string) {
|
||||
token, ok := d.tokens[m.Author.ID]
|
||||
if !ok || token.Token != sects[0] {
|
||||
_, err := s.ChannelMessageSendReply(
|
||||
if _, ok := d.users[m.Author.ID]; ok {
|
||||
channel, err := s.Channel(m.ChannelID)
|
||||
if err != nil {
|
||||
d.app.err.Printf("Discord: Failed to get channel: %v", err)
|
||||
return
|
||||
}
|
||||
if channel.Type != dg.ChannelTypeDM {
|
||||
d.app.debug.Println("Discord: Ignoring message as not a DM")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
d.app.debug.Println("Discord: Ignoring message as user was not found")
|
||||
return
|
||||
}
|
||||
tokenIndex := -1
|
||||
for i, token := range d.tokens {
|
||||
if sects[0] == token {
|
||||
tokenIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if tokenIndex == -1 {
|
||||
_, err := s.ChannelMessageSend(
|
||||
m.ChannelID,
|
||||
d.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"),
|
||||
m.Reference(),
|
||||
)
|
||||
if err != nil {
|
||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
_, err := s.ChannelMessageSendReply(
|
||||
_, err := s.ChannelMessageSend(
|
||||
m.ChannelID,
|
||||
d.app.storage.lang.Telegram[lang].Strings.get("pinSuccess"),
|
||||
m.Reference(),
|
||||
)
|
||||
if err != nil {
|
||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
||||
}
|
||||
d.verifiedTokens = append(d.verifiedTokens, token)
|
||||
delete(d.tokens, m.Author.ID)
|
||||
d.verifiedTokens[sects[0]] = d.users[m.Author.ID]
|
||||
d.tokens[len(d.tokens)-1], d.tokens[tokenIndex] = d.tokens[tokenIndex], d.tokens[len(d.tokens)-1]
|
||||
d.tokens = d.tokens[:len(d.tokens)-1]
|
||||
}
|
||||
|
||||
func (d *DiscordDaemon) Send(message *Message, channelID ...string) error {
|
||||
for _, id := range channelID {
|
||||
msg := ""
|
||||
if message.Markdown == "" {
|
||||
msg = message.Text
|
||||
} else {
|
||||
msg = message.Markdown
|
||||
}
|
||||
_, err := d.bot.ChannelMessageSend(
|
||||
id,
|
||||
msg,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user