Created
June 29, 2018 20:33
-
-
Save miyoyo/dce9b568d28e7d588b7dd2b3c82b6d48 to your computer and use it in GitHub Desktop.
Flutter doc explorer bot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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