Add puzzle parser and config
This commit is contained in:
parent
f40cf00f7a
commit
9355d3703b
@ -1,10 +1,11 @@
|
|||||||
package exts
|
package exts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"djpianalto.com/goff/djpianalto.com/goff/utils"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dustinpianalto/disgoman"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"djpianalto.com/goff/djpianalto.com/goff/utils"
|
||||||
|
"github.com/dustinpianalto/disgoman"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Guild management commands
|
// Guild management commands
|
||||||
@ -203,3 +204,87 @@ func addGuildCommand(ctx disgoman.Context, args []string) {
|
|||||||
_, _ = ctx.Send("This guild has been added.")
|
_, _ = ctx.Send("This guild has been added.")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func puzzleChannel(ctx disgoman.Context, args []string) {
|
||||||
|
var idString string
|
||||||
|
if len(args) > 0 {
|
||||||
|
idString = args[0]
|
||||||
|
if strings.HasPrefix(idString, "<#") && strings.HasSuffix(idString, ">") {
|
||||||
|
idString = idString[2 : len(idString)-1]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
idString = ""
|
||||||
|
}
|
||||||
|
fmt.Println(idString)
|
||||||
|
if idString == "" {
|
||||||
|
_, err := utils.Database.Exec("UPDATE guilds SET puzzle_channel='' WHERE id=$1;", ctx.Guild.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ErrorChannel <- disgoman.CommandError{
|
||||||
|
Context: ctx,
|
||||||
|
Message: "Error Updating Database",
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = ctx.Send("Puzzle Channel Updated.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
channel, err := ctx.Session.State.Channel(idString)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ErrorChannel <- disgoman.CommandError{
|
||||||
|
Context: ctx,
|
||||||
|
Message: "Can't find that channel.",
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if channel.GuildID != ctx.Guild.ID {
|
||||||
|
ctx.ErrorChannel <- disgoman.CommandError{
|
||||||
|
Context: ctx,
|
||||||
|
Message: "The channel passed is not in this guild.",
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = utils.Database.Exec("UPDATE guilds SET puzzle_channel=$1 WHERE id=$2;", idString, ctx.Guild.ID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ErrorChannel <- disgoman.CommandError{
|
||||||
|
Context: ctx,
|
||||||
|
Message: "Error Updating Database",
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = ctx.Send("Puzzle Channel Updated.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPuzzleChannel(ctx disgoman.Context, _ []string) {
|
||||||
|
var channelID string
|
||||||
|
row := utils.Database.QueryRow("SELECT puzzle_channel FROM guilds where id=$1", ctx.Guild.ID)
|
||||||
|
err := row.Scan(&channelID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
ctx.ErrorChannel <- disgoman.CommandError{
|
||||||
|
Context: ctx,
|
||||||
|
Message: "Error getting data from the database.",
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if channelID == "" {
|
||||||
|
_, _ = ctx.Send("The puzzle channel is not set.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
channel, err := ctx.Session.State.GuildChannel(ctx.Guild.ID, channelID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
ctx.ErrorChannel <- disgoman.CommandError{
|
||||||
|
Context: ctx,
|
||||||
|
Message: "I got the channel ID but it does not appear to be a valid channel in this guild.",
|
||||||
|
Error: err,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = ctx.Send(fmt.Sprintf("The puzzle channel is currently %s", channel.Mention()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -186,4 +186,22 @@ func AddCommandHandlers(h *disgoman.CommandManager) {
|
|||||||
RequiredPermissions: 0,
|
RequiredPermissions: 0,
|
||||||
Invoke: deinterleave,
|
Invoke: deinterleave,
|
||||||
})
|
})
|
||||||
|
_ = h.AddCommand(&disgoman.Command{
|
||||||
|
Name: "set-puzzle-channel",
|
||||||
|
Aliases: []string{"spc"},
|
||||||
|
Description: "Set the channel puzzle messages will be sent to.",
|
||||||
|
OwnerOnly: false,
|
||||||
|
Hidden: false,
|
||||||
|
RequiredPermissions: disgoman.PermissionManageServer,
|
||||||
|
Invoke: puzzleChannel,
|
||||||
|
})
|
||||||
|
_ = h.AddCommand(&disgoman.Command{
|
||||||
|
Name: "get-puzzle-channel",
|
||||||
|
Aliases: []string{"gpc"},
|
||||||
|
Description: "Gets the channel puzzle messages will be sent to.",
|
||||||
|
OwnerOnly: false,
|
||||||
|
Hidden: false,
|
||||||
|
RequiredPermissions: disgoman.PermissionManageServer,
|
||||||
|
Invoke: getPuzzleChannel,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,7 @@ func main() {
|
|||||||
// Start the task handler in a goroutine
|
// Start the task handler in a goroutine
|
||||||
go utils.ProcessTasks(dg, 1)
|
go utils.ProcessTasks(dg, 1)
|
||||||
|
|
||||||
go utils.RecieveEmail()
|
go utils.RecieveEmail(dg)
|
||||||
|
|
||||||
fmt.Println("The Bot is now running.")
|
fmt.Println("The Bot is now running.")
|
||||||
sc := make(chan os.Signal, 1)
|
sc := make(chan os.Signal, 1)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
@ -90,6 +91,28 @@ func InitializeDatabase() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
_, err = Database.Query(`CREATE TABLE IF NOT EXISTS postfixes(
|
||||||
|
id serial primary key,
|
||||||
|
name varchar(100) not null,
|
||||||
|
time timestamp not null default NOW())`)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
_, err = Database.Exec(`CREATE TABLE IF NOT EXISTS puzzles(
|
||||||
|
id serial primary key,
|
||||||
|
text text not null,
|
||||||
|
time timestamp not null
|
||||||
|
)`)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
_, err = Database.Exec(`CREATE TABLE IF NOT EXISTS x_guilds_puzzles(
|
||||||
|
id serial primary key,
|
||||||
|
guild_id varchar(30) not null references guilds(id),
|
||||||
|
puzzle_id int not null references puzzles(id),
|
||||||
|
message_id varchar(30) not null
|
||||||
|
)`)
|
||||||
|
RunPostfixes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadTestData() {
|
func LoadTestData() {
|
||||||
|
|||||||
@ -2,24 +2,32 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
imap "github.com/emersion/go-imap"
|
imap "github.com/emersion/go-imap"
|
||||||
"github.com/emersion/go-imap/client"
|
"github.com/emersion/go-imap/client"
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
emailUsername = os.Getenv("GOFF_EMAIL_USERNAME")
|
emailUsername = os.Getenv("GOFF_EMAIL_USERNAME")
|
||||||
emailPassword = os.Getenv("GOFF_EMAIL_PASSWORD")
|
emailPassword = os.Getenv("GOFF_EMAIL_PASSWORD")
|
||||||
|
puzzleAddress = mail.Address{
|
||||||
|
Name: "Daily Coding Problem",
|
||||||
|
Address: "founders@dailycodingproblem.com",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var EmailClient client.Client
|
var EmailClient client.Client
|
||||||
|
|
||||||
func RecieveEmail() {
|
func RecieveEmail(dg *discordgo.Session) {
|
||||||
for {
|
for {
|
||||||
log.Println("Connecting to Email server.")
|
log.Println("Connecting to Email server.")
|
||||||
|
|
||||||
@ -33,7 +41,6 @@ func RecieveEmail() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Println("Connected to Email server.")
|
log.Println("Connected to Email server.")
|
||||||
defer EmailClient.Logout()
|
|
||||||
|
|
||||||
mbox, err := EmailClient.Select("INBOX", false)
|
mbox, err := EmailClient.Select("INBOX", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -64,6 +71,8 @@ func RecieveEmail() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for msg := range messages {
|
for msg := range messages {
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
log.Println("No New Messages")
|
log.Println("No New Messages")
|
||||||
@ -74,46 +83,50 @@ func RecieveEmail() {
|
|||||||
log.Println("Server didn't send a message body")
|
log.Println("Server didn't send a message body")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mr, err := mail.CreateReader(r)
|
wg.Add(1)
|
||||||
if err != nil {
|
go processEmail(r, dg, &wg)
|
||||||
log.Println(err)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
header := mr.Header
|
wg.Wait()
|
||||||
if date, err := header.Date(); err == nil {
|
|
||||||
log.Println("Date:", date)
|
|
||||||
}
|
|
||||||
if from, err := header.AddressList("From"); err == nil {
|
|
||||||
log.Println("From:", from)
|
|
||||||
}
|
|
||||||
if to, err := header.AddressList("To"); err == nil {
|
|
||||||
log.Println("To:", to)
|
|
||||||
}
|
|
||||||
if subject, err := header.Subject(); err == nil {
|
|
||||||
log.Println("Subject:", subject)
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
p, err := mr.NextPart()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
} else if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch h := p.Header.(type) {
|
EmailClient.Logout()
|
||||||
case *mail.InlineHeader:
|
|
||||||
// This is the message's text (can be plain-text or HTML)
|
|
||||||
b, _ := ioutil.ReadAll(p.Body)
|
|
||||||
log.Printf("Got text: %v\n", string(b))
|
|
||||||
case *mail.AttachmentHeader:
|
|
||||||
// This is an attachment
|
|
||||||
filename, _ := h.Filename()
|
|
||||||
log.Printf("Got attachment: %v\n", filename)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(300 * time.Second)
|
time.Sleep(300 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processEmail(r io.Reader, dg *discordgo.Session, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
mr, err := mail.CreateReader(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
header := mr.Header
|
||||||
|
from, err := header.AddressList("From")
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
subject, err := header.Subject()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println(from)
|
||||||
|
log.Println(subject)
|
||||||
|
if addressIn(from, puzzleAddress) &&
|
||||||
|
strings.Contains(subject, "Daily Coding Problem:") {
|
||||||
|
log.Println("Processing Puzzle")
|
||||||
|
ProcessPuzzleEmail(mr, dg)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func addressIn(s []*mail.Address, a mail.Address) bool {
|
||||||
|
for _, item := range s {
|
||||||
|
if item.String() == a.String() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
77
djpianalto.com/goff/utils/postfixes.go
Normal file
77
djpianalto.com/goff/utils/postfixes.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
type postfix struct {
|
||||||
|
Name string
|
||||||
|
Invoke func(bool) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var postfixes = []postfix{
|
||||||
|
postfix{
|
||||||
|
Name: "1_Update_Guild_for_Puzzle",
|
||||||
|
Invoke: updateGuildForPuzzle,
|
||||||
|
},
|
||||||
|
postfix{
|
||||||
|
Name: "1_Update_X_Guild_Prefixes_to_add_ID",
|
||||||
|
Invoke: updateXGuildPrefixesToAddID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunPostfixes() {
|
||||||
|
for _, postfix := range postfixes {
|
||||||
|
queryString := "SELECT * from postfixes where name = $1"
|
||||||
|
rows, err := Database.Query(queryString, postfix.Name)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if rows.Next() {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
err := postfix.Invoke(false)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err = Database.Exec("INSERT INTO postfixes (name) VALUES ($1)", postfix.Name)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateGuildForPuzzle(revert bool) error {
|
||||||
|
var queryString string
|
||||||
|
if !revert {
|
||||||
|
queryString = `ALTER TABLE guilds
|
||||||
|
ADD COLUMN puzzle_channel varchar(30) not null default ''`
|
||||||
|
} else {
|
||||||
|
queryString = `ALTER TABLE guilds
|
||||||
|
DROP COLUMN puzzleChat`
|
||||||
|
}
|
||||||
|
_, err := Database.Exec(queryString)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateXGuildPrefixesToAddID(revert bool) error {
|
||||||
|
var queryString string
|
||||||
|
if !revert {
|
||||||
|
queryString = `ALTER TABLE x_guilds_prefixes
|
||||||
|
ADD COLUMN id serial primary key`
|
||||||
|
} else {
|
||||||
|
queryString = `ALTER TABLE x_guilds_prefixes
|
||||||
|
DROP COLUMN id`
|
||||||
|
}
|
||||||
|
_, err := Database.Exec(queryString)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
93
djpianalto.com/goff/utils/puzzles.go
Normal file
93
djpianalto.com/goff/utils/puzzles.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/emersion/go-message/mail"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ProcessPuzzleEmail(mr *mail.Reader, dg *discordgo.Session) {
|
||||||
|
var body []byte
|
||||||
|
for {
|
||||||
|
p, err := mr.NextPart()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch h := p.Header.(type) {
|
||||||
|
case *mail.InlineHeader:
|
||||||
|
// This is the message's text (can be plain-text or HTML)
|
||||||
|
if t, _, _ := h.ContentType(); t == "text/plain" {
|
||||||
|
body, _ = ioutil.ReadAll(p.Body)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(body) > 0 {
|
||||||
|
s := string(body)
|
||||||
|
puzzle := strings.Split(s, "----------")[0]
|
||||||
|
date, err := mr.Header.Date()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e := discordgo.MessageEmbed{
|
||||||
|
Title: "Daily Coding Problem",
|
||||||
|
URL: "https://dailycodingproblem.com/",
|
||||||
|
Description: "```" + puzzle + "```",
|
||||||
|
Timestamp: date.Format(time.RFC3339),
|
||||||
|
Footer: &discordgo.MessageEmbedFooter{
|
||||||
|
Text: "Daily Coding Problem",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var guilds []Guild
|
||||||
|
queryString := `SELECT id, puzzle_channel from guilds`
|
||||||
|
rows, err := Database.Query(queryString)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
var guild Guild
|
||||||
|
err := rows.Scan(&guild.ID, &guild.PuzzleChannel)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
guilds = append(guilds, guild)
|
||||||
|
}
|
||||||
|
var puzzleID int64
|
||||||
|
queryString = "INSERT INTO puzzles (text, time) VALUES ($1, $2) RETURNING id"
|
||||||
|
err = Database.QueryRow(queryString, puzzle, date).Scan(&puzzleID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, g := range guilds {
|
||||||
|
if g.PuzzleChannel == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msg := discordgo.MessageSend{
|
||||||
|
Embed: &e,
|
||||||
|
}
|
||||||
|
m, err := dg.ChannelMessageSendComplex(g.PuzzleChannel, &msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
queryString = "INSERT INTO x_guilds_puzzles (guild_id, puzzle_id, message_id) VALUES ($1, $2, $3)"
|
||||||
|
_, err = Database.Exec(queryString, g.ID, puzzleID, m.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
10
djpianalto.com/goff/utils/types.go
Normal file
10
djpianalto.com/goff/utils/types.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
type Guild struct {
|
||||||
|
ID string
|
||||||
|
WelcomeMessage string
|
||||||
|
GoodbyeMessage string
|
||||||
|
LoggingChannel string
|
||||||
|
WelcomeChannel string
|
||||||
|
PuzzleChannel string
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@ -5,6 +5,8 @@ go 1.14
|
|||||||
require (
|
require (
|
||||||
github.com/bwmarrin/discordgo v0.20.3-0.20200525154655-ca64123b05de
|
github.com/bwmarrin/discordgo v0.20.3-0.20200525154655-ca64123b05de
|
||||||
github.com/dustinpianalto/disgoman v0.0.10
|
github.com/dustinpianalto/disgoman v0.0.10
|
||||||
|
github.com/emersion/go-imap v1.0.5
|
||||||
|
github.com/emersion/go-message v0.12.0
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||||
github.com/lib/pq v1.3.0
|
github.com/lib/pq v1.3.0
|
||||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254
|
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254
|
||||||
|
|||||||
14
go.sum
14
go.sum
@ -9,12 +9,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dustinpianalto/disgoman v0.0.10 h1:UzmvMpOi4peF59tXGaNfVU+ePHs1hILa6gQbjxjWQ9g=
|
github.com/dustinpianalto/disgoman v0.0.10 h1:UzmvMpOi4peF59tXGaNfVU+ePHs1hILa6gQbjxjWQ9g=
|
||||||
github.com/dustinpianalto/disgoman v0.0.10/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
|
github.com/dustinpianalto/disgoman v0.0.10/go.mod h1:v3FM6n+4dH9XlvO+IDx6MN3DUnGq6YVDBvy1A1k202g=
|
||||||
|
github.com/emersion/go-imap v1.0.5 h1:8xg/d2wo2BBP3AEP5AOaM/6i8887RGyVW2st/IVHWUw=
|
||||||
|
github.com/emersion/go-imap v1.0.5/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
|
||||||
|
github.com/emersion/go-message v0.11.1/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY=
|
||||||
|
github.com/emersion/go-message v0.12.0 h1:mZnv35eZ6lB6EftTQBgYXspOH0FQdhpFhSUhA9i6/Zg=
|
||||||
|
github.com/emersion/go-message v0.12.0/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b h1:uhWtEWBHgop1rqEk2klKaxPAkVDCXexai6hSuRQ7Nvs=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||||
|
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe h1:40SWqY0zE3qCi6ZrtTf5OUdNm5lDnGnjRSq9GgmeTrg=
|
||||||
|
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/martinlindhe/base36 v1.0.0 h1:eYsumTah144C0A8P1T/AVSUk5ZoLnhfYFM3OGQxB52A=
|
||||||
|
github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
|
||||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254 h1:JYoQR67E1vv1WGoeW8DkdFs7vrIEe/5wP+qJItd5tUE=
|
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254 h1:JYoQR67E1vv1WGoeW8DkdFs7vrIEe/5wP+qJItd5tUE=
|
||||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
|
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
@ -26,3 +37,6 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA=
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user