package main import ( "context" "fmt" "log" "net/http" "git.xeserv.us/xena/vyvanse/bot" "github.com/Xe/ln" "github.com/bwmarrin/discordgo" _ "github.com/joho/godotenv/autoload" "github.com/namsral/flag" xkcd "github.com/nishanths/go-xkcd" opentracing "github.com/opentracing/opentracing-go" otlog "github.com/opentracing/opentracing-go/log" zipkin "github.com/openzipkin/zipkin-go-opentracing" "github.com/robfig/cron" ) var lastXKCD int var ( pesterChannel = flag.String("upload-channel", "", "Discord channel ID to upload and announce new XKCD items to") token = flag.String("token", "", "discord bot token") zipkinURL = flag.String("zipkin-url", "", "URL for Zipkin traces") ) func main() { flag.Parse() xk := xkcd.NewClient() dg, err := discordgo.New("Bot " + *token) if err != nil { log.Fatal(err) } c := cron.New() comic, err := xk.Latest() if err != nil { log.Fatal(err) } lastXKCD = comic.Number c.AddFunc("@daily", func() { sp, ctx := opentracing.StartSpanFromContext(context.Background(), "daily.xkcd.fetch") comic, err := xk.Latest() if err != nil { log.Println(err) return } if comic.Number > lastXKCD { sp.LogFields(otlog.String("image.url", comic.ImageURL), otlog.String("target", *pesterChannel)) req, err := http.NewRequest(http.MethodGet, comic.ImageURL, nil) if err != nil { ln.Error(ctx, err, ln.F{"action": "make request"}) sp.LogFields(otlog.Error(err)) return } resp, err := http.DefaultClient.Do(req) if err != nil { ln.Error(ctx, err, ln.F{"action": "http get", "url": comic.ImageURL}) sp.LogFields(otlog.Error(err)) return } fname := fmt.Sprintf("%d - %s.png", comic.Number, comic.Title) msg := fmt.Sprintf("New XKCD comic uploaded: %d - %s\n\n*%s*", comic.Number, comic.Title, comic.Alt) _, err = dg.ChannelFileSendWithMessage(*pesterChannel, msg, fname, resp.Body) if err != nil { ln.Error(ctx, err, ln.F{"action": "send xkcd upload", "to": *pesterChannel}) sp.LogFields(otlog.Error(err)) return } lastXKCD = comic.Number } }) c.Start() if *zipkinURL != "" { collector, err := zipkin.NewHTTPCollector(*zipkinURL) if err != nil { ln.FatalErr(context.Background(), err) } tracer, err := zipkin.NewTracer( zipkin.NewRecorder(collector, false, "vyvanse:5000", "vyvanse")) if err != nil { ln.FatalErr(context.Background(), err) } opentracing.SetGlobalTracer(tracer) } cs := bot.NewCommandSet() cs.Prefix = ">" cs.AddCmd("hipster", "generates hipster-sounding text", bot.NoPermissions, hipster) cs.AddCmd("printerfact", "facts about printers", bot.NoPermissions, printerFact) cs.AddCmd("dice", "roll the dice", bot.NoPermissions, roll) cs.AddCmd("splattus", "splatoon 2 map rotation status", bot.NoPermissions, spla2nMaps) dg.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) { err := cs.Run(s, m.Message) if err != nil { ln.Error(context.Background(), err, ln.F{"action": "run commandSet on message"}) } }) // Open the websocket and begin listening. err = dg.Open() if err != nil { fmt.Println("error opening connection,", err) return } fmt.Println("Bot is now running. Press CTRL-C to exit.") // Simple way to keep program running until CTRL-C is pressed. <-make(chan struct{}) return }