grim/wasdead

Proper URL is now used for stuff
draft
2019-03-20, Ruin
662c3c77eb5a
Proper URL is now used for stuff
package main
import (
"errors"
"flag"
"fmt"
"log"
"net/url"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/bwmarrin/discordgo"
"github.com/nicklaw5/helix"
"github.com/prologic/bitcask"
)
var (
DiscordToken string
TwitchToken string
DatabasePath string
TwitchClient *helix.Client
logger *log.Logger
startTime time.Time
database *bitcask.Bitcask
)
func init() {
logger = log.New(os.Stderr, " ", log.Ldate|log.Ltime)
startTime = time.Now()
flag.StringVar(&DiscordToken, "t", "", "Discord Bot Token")
flag.StringVar(&TwitchToken, "tcid", "", "Twitch Client ID")
flag.StringVar(&DatabasePath, "db", "./db", "Database Path")
flag.Parse()
}
func logDebug(v ...interface{}) {
logger.SetPrefix("DEBUG ")
logger.Println(v...)
}
func logInfo(v ...interface{}) {
logger.SetPrefix("INFO ")
logger.Println(v...)
}
func logError(v ...interface{}) {
logger.SetPrefix("ERROR ")
logger.Println(v...)
}
func logPanic(v ...interface{}) {
logger.SetPrefix("PANIC ")
logger.Panicln(v...)
}
func main() {
if len(DiscordToken) <= 0 || len(TwitchToken) <= 0 {
logPanic("Discord Token and Twitch Client ID must be set")
}
logDebug("Discord Token:", DiscordToken)
logDebug("Twitch Token:", TwitchToken)
database, _ = bitcask.Open(DatabasePath)
defer database.Close()
client, err := helix.NewClient(&helix.Options{
ClientID: TwitchToken,
})
if err != nil {
logPanic(err)
}
TwitchClient = client
dg, err := discordgo.New("Bot " + strings.TrimSpace(DiscordToken))
if err != nil {
fmt.Println("error creating Discord session,", err)
return
}
dg.AddHandler(presenceUpdate)
dg.AddHandler(messageCreate)
err = dg.Open()
if err != nil {
log.Panic(err)
return
}
fmt.Println("Bot 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
dg.Close()
}
func presenceUpdate(sess *discordgo.Session, evt *discordgo.PresenceUpdate) {
logDebug("PRESENSE UPDATE user-ID:", evt.User.ID)
if evt.Game != nil {
logDebug(fmt.Sprintf("PRESENSE UPDATE game: %#v", evt.Game))
if evt.Game.Type == discordgo.GameTypeStreaming {
pURL, _ := url.Parse(evt.Game.URL)
channel := getguild2channel(evt.GuildID)
if channel != "" {
err := processPresenceUpdate(sess, channel, strings.TrimLeft(pURL.Path, "/"), evt.Game.URL)
if err != nil {
logError(err)
}
}
}
}
}
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.ID == s.State.User.ID {
return
}
commandItems := strings.Split(m.Content, " ")
if strings.EqualFold(commandItems[0], "!uptime") {
duration := time.Now().Sub(startTime)
channel := getguild2channel(m.GuildID)
if channel != "" {
if channel != m.ChannelID {
return
}
err := sendMessage(s, channel, fmt.Sprintf(
"Uptime is: **%02d:%02d:%02d** (since **%s**)",
int(duration.Hours()),
int(duration.Minutes())%60,
int(duration.Seconds())%60,
startTime.Format(time.Stamp)))
logError(err)
}
}
if strings.EqualFold(commandItems[0], "!isLive") {
if len(commandItems) == 1 {
return
}
channel := getguild2channel(m.GuildID)
if channel != "" {
if channel != m.ChannelID {
return
}
err := processPresenceUpdate(s, channel, commandItems[1], "https://twitch.com/"+commandItems[1])
if err != nil {
logError(err)
}
}
}
if strings.EqualFold(commandItems[0], "!init") {
sendMessage(s, m.ChannelID, "All set up to talk in this channel!")
setguild2channel(m.GuildID, m.ChannelID)
}
}
func sendMessage(sess *discordgo.Session, channelid, message string) error {
logInfo("SENDING MESSAGE:", message)
_, err := sess.ChannelMessageSend(channelid, message)
return err
}
func processPresenceUpdate(s *discordgo.Session, channelid, twitchName, url string) error {
resp, err := TwitchClient.GetUsers(&helix.UsersParams{
Logins: []string{twitchName},
})
if err != nil {
return err
}
/*
TODO: Use twitch stream info to maybe get that channels info
data, _ := TwitchClient.GetStreamsMetadata(&helix.StreamsMetadataParams {
UserLogins: []string{commandItems[1]}
})
*/
if len(resp.Data.Users) <= 0 {
return errors.New("user was not found")
}
user := resp.Data.Users[0]
f := make([]*discordgo.MessageEmbedField, 0)
f = append(f, &discordgo.MessageEmbedField{
Name: "Description",
Value: user.Description,
})
_, err = s.ChannelMessageSendEmbed(channelid, &discordgo.MessageEmbed{
Image: &discordgo.MessageEmbedImage{
URL: user.OfflineImageURL,
},
Author: &discordgo.MessageEmbedAuthor{
URL: url,
Name: user.DisplayName + " is now live",
},
Thumbnail: &discordgo.MessageEmbedThumbnail{
URL: user.ProfileImageURL,
},
Fields: f,
})
return err
}
func fileExist(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
func getguild2channel(guild string) string {
data, err := database.Get(guild)
if err != nil {
return ""
}
return string(data)
}
func setguild2channel(guild, channel string) {
database.Put(guild, []byte(channel))
}