Skip to content

Instantly share code, notes, and snippets.

@miyoyo
Created June 29, 2018 20:33
Show Gist options
  • Save miyoyo/dce9b568d28e7d588b7dd2b3c82b6d48 to your computer and use it in GitHub Desktop.
Save miyoyo/dce9b568d28e7d588b7dd2b3c82b6d48 to your computer and use it in GitHub Desktop.
Flutter doc explorer bot
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"os/signal"
"regexp"
"syscall"
"github.com/bwmarrin/discordgo"
"github.com/jasonlvhit/gocron"
"github.com/sahilm/fuzzy"
)
type index []struct {
Name string `json:"name"`
QualifiedName string `json:"qualifiedName"`
Href string `json:"href"`
Type string `json:"type"`
OverriddenDepth int `json:"overriddenDepth"`
EnclosedBy struct {
Name string `json:"name"`
Type string `json:"type"`
} `json:"enclosedBy,omitempty"`
}
var searchStrings []string
var searchIndex index
func main() {
directPattern := regexp.MustCompile("!\\[(.*?)\\]")
searchPattern := regexp.MustCompile("\\?\\[(.*?)\\]")
bot, err := discordgo.New("Bot TOKEN")
if err != nil {
panic(err.Error())
}
bot.AddHandler(func(s *discordgo.Session, h *discordgo.MessageCreate) {
fmt.Println(h.Content)
if h.Author.ID == s.State.User.ID {
return
}
if len(h.Content) >= 21 {
if h.Content[:21] == "<@462299661995343882>" { //Bot source
bot.ChannelMessageSendEmbed(h.ChannelID, &discordgo.MessageEmbed{
Title: "ℹ️ Help",
Description: "⚠️ These commands can be within a message, and there can be multiple per messages",
Fields: []*discordgo.MessageEmbedField{
&discordgo.MessageEmbedField{
Name: "![query]",
Value: "Gives a direct link to the first result, and suggests 2 others related to 'query'",
},
&discordgo.MessageEmbedField{
Name: "?[query]",
Value: "Shows the 10 first search results about 'query'",
},
},
Footer: &discordgo.MessageEmbedFooter{
Text: "Source: https://gist.github.com/miyoyo/e2e790646408bb67bda0ab2ce81f1632",
},
})
}
}
for _, value := range directPattern.FindAllStringSubmatch(h.Content, -1) {
matches := fuzzy.Find(value[1], searchStrings)
if len(matches) == 0 {
s.ChannelMessageSendEmbed(h.ChannelID, &discordgo.MessageEmbed{
Title: "Direct reference - " + value[1],
Description: "Not found.",
Color: 0xEE0000,
})
} else {
selected := matches[0]
if len(matches) > 1 && searchIndex[matches[0].Index].Type != "class" {
if searchIndex[matches[1].Index].Type == "class" {
selected = matches[1]
}
}
s.ChannelMessageSend(h.ChannelID, "https://docs.flutter.io/flutter/"+searchIndex[selected.Index].Href)
}
}
for _, value := range searchPattern.FindAllStringSubmatch(h.Content, -1) {
matches := fuzzy.Find(value[1], searchStrings)
fmt.Println(value[1])
embeds := []*discordgo.MessageEmbedField{}
setSize := 5
if len(matches) < setSize {
setSize = len(matches)
}
for _, result := range matches[:setSize] {
embeds = append(embeds, &discordgo.MessageEmbedField{
Name: searchIndex[result.Index].Type + " " + searchIndex[result.Index].Name + " - " + searchIndex[result.Index].EnclosedBy.Name,
Value: "https://docs.flutter.io/flutter/" + searchIndex[result.Index].Href,
})
}
if len(embeds) == 0 {
s.ChannelMessageSendEmbed(h.ChannelID, &discordgo.MessageEmbed{
Title: "Search results - " + value[1],
Description: "Not found.",
Color: 0xEE0000,
})
} else {
s.ChannelMessageSendEmbed(h.ChannelID, &discordgo.MessageEmbed{
Title: "Search results - " + value[1],
Fields: embeds,
})
}
}
})
if bot.Open() != nil {
panic("could not open bot: " + err.Error())
}
updateIndex(bot)
go func(bot *discordgo.Session) {
gocron.Every(1).Day().Do(updateIndex, bot)
gocron.Every(30).Minutes().Do(func() { bot.UpdateStatus(0, "mention me for help.") })
<-gocron.Start()
}(bot)
fmt.Println("FlutterDoc is now running. Press CTRL-C to exit.")
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
<-sc
bot.Close()
}
func updateIndex(bot *discordgo.Session) {
bot.UpdateStatusComplex(discordgo.UpdateStatusData{
Status: "idle",
AFK: true,
Game: &discordgo.Game{
Name: "updating search...",
},
})
out, err := http.Get("https://docs.flutter.io/flutter/index.json")
if err != nil {
bot.ChannelMessageSend("446257816345378827", "Failed to update index: %s"+err.Error()) //Debug channel
return
}
buf := new(bytes.Buffer)
buf.ReadFrom(out.Body)
json.Unmarshal(buf.Bytes(), &searchIndex)
searchStrings = nil
for _, value := range searchIndex {
searchStrings = append(searchStrings, value.QualifiedName)
}
fmt.Println(searchIndex)
bot.UpdateStatus(0, "mention me for help.")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment