Skip to content

Instantly share code, notes, and snippets.

@jonas747
Created January 26, 2017 01:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonas747/0538fcdd5449f2b86b7ed07752458e1c to your computer and use it in GitHub Desktop.
Save jonas747/0538fcdd5449f2b86b7ed07752458e1c to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"flag"
"fmt"
"github.com/PuerkitoBio/goquery"
"github.com/jonas747/discordgo"
"io"
"io/ioutil"
"log"
"net/http"
"os/exec"
"strconv"
"strings"
"time"
"unicode"
)
const (
ScriptStartsWith = "webpackJsonp("
)
var (
DToken string
DCHannel string
DMention string
DG *discordgo.Session
)
func init() {
flag.StringVar(&DToken, "t", "", "Discord token for notifications")
flag.StringVar(&DCHannel, "c", "", "Discord channel for notifications")
flag.StringVar(&DMention, "m", "", "Mention")
flag.Parse()
}
func main() {
if DToken == "" || DCHannel == "" {
log.Println("No discord token or channel specified, no notifications will be provided")
} else {
d, err := discordgo.New(DToken)
if err != nil {
log.Fatal("Failed initializing discordgo session: ", err)
}
DG = d
log.Println("Discord notifications enabled")
}
runLoop()
}
func runLoop() {
for {
source, err := grabScript()
if err != nil {
log.Println("GRAB Error: ", err)
time.Sleep(time.Minute)
continue
}
// ioutil.WriteFile("source.js", []byte(source), 0755)
newVersion, err := findVersion(source)
if err != nil {
log.Println("Couldnt find version: ", err)
time.Sleep(time.Minute)
continue
}
currentVersion := getCurrentVersion()
if newVersion <= currentVersion {
log.Println("No new version")
time.Sleep(time.Minute)
continue
}
log.Printf("New version! %d -> %d", currentVersion, newVersion)
git, err := updateVersion(source, newVersion)
if err != nil {
log.Fatal("Failed updating: ", err)
} else {
notify(currentVersion, newVersion, git)
}
log.Println("Update finished")
time.Sleep(time.Minute)
}
}
func getCurrentVersion() int {
content, err := ioutil.ReadFile("current_appversion")
if err != nil {
log.Println("Failed reading current version file: ", err)
return 0
}
v, err := strconv.ParseInt(strings.TrimSpace(string(content)), 10, 32)
if err != nil {
log.Println("Failed reading current version: ", err)
}
return int(v)
}
func saveVersion(version int) error {
return ioutil.WriteFile("current_appversion", []byte(fmt.Sprint(version)), 0755)
}
func grabScript() (string, error) {
doc, err := goquery.NewDocument("https://canary.discordapp.com/login")
if err != nil {
return "", err
}
result := ""
doc.Find("script").Each(func(i int, s *goquery.Selection) {
src, found := s.Attr("src")
if !found {
return
}
resp, err := http.Get("https://canary.discordapp.com" + src)
if err != nil {
return
}
defer resp.Body.Close()
buf := make([]byte, len(ScriptStartsWith))
_, err = resp.Body.Read(buf)
if err != nil {
return
}
if string(buf) != ScriptStartsWith {
//log.Println(string(buf), "does not match", ScriptStartsWith)
return
}
if result != "" {
panic("Multiple matched scripts")
}
last, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("Failed reading body")
return
}
result = string(buf) + string(last)
})
if result == "" {
return "", errors.New("Couldn't find script")
}
return result, nil
}
const (
VersionMatch = ".appVersion="
)
func findVersion(source string) (int, error) {
index := strings.Index(source, VersionMatch)
if index == -1 {
return 0, errors.New("Couldn't find version in source")
}
offset := index + len(VersionMatch)
view := source[offset+1 : offset+50]
buf := ""
for _, r := range view {
if !unicode.IsNumber(r) {
break
}
buf += string(r)
}
ver, err := strconv.ParseInt(buf, 10, 32)
if err != nil {
return 0, errors.New("Failed parsing version number " + buf)
}
return int(ver), nil
}
// Returns the git summary and an error
func updateVersion(source string, version int) (string, error) {
log.Println("Updating")
err := writeSource(source)
if err != nil {
return "", err
}
err = saveVersion(version)
if err != nil {
return "", err
}
output, err := commitVersion(version)
log.Println("Git: " + output)
if err != nil {
return "", err
}
return output, nil
}
func writeSource(source string) error {
cmd := exec.Command("js-beautify", "-i", "-o", "discord.js")
inPipe, err := cmd.StdinPipe()
if err != nil {
return err
}
err = cmd.Start()
if err != nil {
return err
}
io.WriteString(inPipe, source)
inPipe.Close()
out, err := cmd.Output()
if len(out) > 1 {
log.Println("JSB: ", string(out))
}
return cmd.Wait()
}
func commitVersion(version int) (string, error) {
cmd := exec.Command("git", "commit", "-m", fmt.Sprintf("auto v%d", version), "discord.js", "current_appversion")
out, err := cmd.Output()
if err != nil {
return "", err
}
return string(out), nil
}
func notify(old, newV int, git string) {
msg := fmt.Sprintf("New discord version pulled (%d -> %d) %s\n```\n%s\n```", old, newV, DMention, git)
_, err := DG.ChannelMessageSend(DCHannel, msg)
if err != nil {
log.Println("Failed sending notification in discord: ", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment