Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
giwty committed Sep 8, 2019
1 parent 0c8bc6f commit ba273d5
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module switch/nsp/diff

go 1.12

require (
github.com/briandowns/spinner v1.6.1
github.com/go-openapi/strfmt v0.19.2 // indirect
github.com/jedib0t/go-pretty v4.3.0+incompatible
github.com/mattn/go-runewidth v0.0.2 // indirect
github.com/stretchr/testify v1.4.0 // indirect
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd // indirect
)
47 changes: 47 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/briandowns/spinner v1.6.1 h1:LBxHu5WLyVuVEtTD72xegiC7QJGx598LBpo3ywKTapA=
github.com/briandowns/spinner v1.6.1/go.mod h1://Zf9tMcxfRUA36V23M6YGEAv+kECGfvpnLTnb8n4XQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/strfmt v0.19.2 h1:clPGfBnJohokno0e+d7hs6Yocrzjlgz6EsQSDncCRnE=
github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
213 changes: 213 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package main

import (
"encoding/json"
"errors"
"flag"
"fmt"
"github.com/briandowns/spinner"
"github.com/jedib0t/go-pretty/table"
"io"
"io/ioutil"
"net/http"
"os"
"regexp"
"sort"
"strconv"
"strings"
"time"
)

const (
titles_json_uri = "https://raw.githubusercontent.com/blawar/titledb/master/titles.US.en.json"
versions_json_url = "https://raw.githubusercontent.com/blawar/titledb/master/versions.json"
)

var (
nspFolder = flag.String("f", "", "path to NSP folder")
s = spinner.New(spinner.CharSets[26], 100*time.Millisecond) // Build our new spinner
)

type title struct {
Id string `json:"id"`
Name string `json:"name,omitempty"`
Version json.Number `json:"version,omitempty"`
Region string `json:"region,omitempty"`
ReleaseDate int `json:"releaseDate,omitempty"`
Publisher string `json:"publisher,omitempty"`
IconUrl string `json:"iconUrl,omitempty"`
Screenshots []string `json:"screenshots,omitempty"`
BannerUrl string `json:"bannerUrl,omitempty"`
Description string `json:"description,omitempty"`
Size int `json:"size,omitempty"`
}

func main() {
flag.Parse()

if *nspFolder == "" {
flag.Usage()
os.Exit(1)
}

var titlesDb = map[string]title{}
err := loadOrDownloadFileFromUrl(titles_json_uri, "titlesDb.json", &titlesDb)
if err != nil {
fmt.Printf("unable to download file - %v\n%v", titles_json_uri, err)
return
}

var versionsDb = map[string]map[int]string{}
err = loadOrDownloadFileFromUrl(versions_json_url, "versionsDb.json", &versionsDb)
if err != nil {
fmt.Printf("unable to download file - %v\n%v", versions_json_url, err)
return
}

s.Restart()
fmt.Printf("\nScanning nsp folder ")
files, err := ioutil.ReadDir(*nspFolder)
if err != nil {
fmt.Printf("\nfailed scanning NSP folder\n %v", err)
return
}
s.Stop()
var localVersionsDb = map[string][]int{}
var skippedFiles = map[string]string{}

versionR := regexp.MustCompile(`\[[vV]?(?P<version>[0-9]{1,10})\]`)
titleIdR := regexp.MustCompile(`\[(?P<titleId>[A-Z,a-z,0-9]{16})\]`)
for _, file := range files {
if file.Name()[0:1] == "." || file.IsDir() {
continue
}

if !strings.HasSuffix(file.Name(), "nsp") {
skippedFiles[file.Name()] = "non NSP file"
continue
}

res := versionR.FindStringSubmatch(file.Name())
if len(res) != 2 {
skippedFiles[file.Name()] = "failed to parse name"
continue
}
verStr := res[1]
res = titleIdR.FindStringSubmatch(file.Name())
if len(res) != 2 {
skippedFiles[file.Name()] = "failed to parse name"
continue
}
if len(res) != 2 {
skippedFiles[file.Name()] = "failed to parse name"
continue
}
titleId := strings.ToLower(res[1])

if strings.HasSuffix(titleId, "800") {
titleId = titleId[0:len(titleId)-3] + "000"
}

ver, err := strconv.Atoi(verStr)
if err != nil {
skippedFiles[file.Name()] = "failed to parse version"
continue
}

localVersionsDb[titleId] = append(localVersionsDb[titleId], ver)
}

var numTobeUpdated int = 0

t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.SetStyle(table.StyleColoredBright)
t.AppendHeader(table.Row{"#", "Title","TitleId" ,"Current version", "Available Version", "Release date"})
//iterate over local files, and compare to remote versions
for titleId, _ := range localVersionsDb {

localVersions := localVersionsDb[titleId]
sort.Ints(localVersions)

var remoteVersions []int
for k, _ := range versionsDb[titleId] {
remoteVersions = append(remoteVersions, k)
}

if title, ok := titlesDb[strings.ToUpper(titleId[0:len(titleId)-3]+"800")]; ok {
ver, err := strconv.Atoi(title.Version.String())
if err == nil {
remoteVersions = append(remoteVersions, ver)
}
}
if len(remoteVersions) == 0 {
continue
}

var nspName string
if title, ok := titlesDb[strings.ToUpper(titleId)]; ok {
nspName = title.Name
ver, err := strconv.Atoi(title.Version.String())
if err == nil {
remoteVersions = append(remoteVersions, ver)
}
}

localVer := localVersions[len(localVersions)-1]
if localVersions[0] != 0 && !strings.Contains(strings.ToLower(nspName), "pack") {
//fmt.Printf("** game [%v][%v] missing base version\n",titleId,nspName)
continue
}
sort.Ints(remoteVersions)
remoteVer := remoteVersions[len(remoteVersions)-1]

if remoteVer > localVer {
var nspName string
if title, ok := titlesDb[strings.ToUpper(titleId)]; ok {
nspName = title.Name
}
numTobeUpdated++
t.AppendRow([]interface{}{numTobeUpdated, nspName,titleId, localVer, remoteVer, versionsDb[titleId][remoteVer]})
}
}
t.AppendFooter(table.Row{"", "", "", "","Total", numTobeUpdated})
if numTobeUpdated != 0{
fmt.Printf("\nFound available updates:\n\n")
t.Render()
}else{
fmt.Printf("\nAll NSP's are up to date!\n\n")
}


}

func loadOrDownloadFileFromUrl(url string, fileName string, target interface{}) error {

if _, err := os.Stat("./" + fileName); os.IsNotExist(err) {
file, err := os.Create("./" + fileName)
fmt.Printf("\nDownloading from - %v", url)
s.Start()
resp, err := http.Get(url)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return errors.New("got a non 200 response - " + resp.Status)
}
defer resp.Body.Close()

_, err = io.Copy(file, resp.Body)
if err != nil {
return err
}
}

fmt.Printf("\nLoading file - %v", fileName)
s.Start()
file, err := os.Open("./" + fileName)
err = json.NewDecoder(file).Decode(target)
if err != nil {
return err
}
return nil
}

0 comments on commit ba273d5

Please sign in to comment.