Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vulcan-dev committed Jul 14, 2021
1 parent 1350d8d commit 6d31c03
Show file tree
Hide file tree
Showing 9 changed files with 365 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Downloads/
.dccache
.vscode
Binary file added Assets/Icon.ico
Binary file not shown.
Binary file added Assets/Icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# kissmp-installer
KissMP Installer for Windows
# Building #
1. Run `go build -o installer.exe .\main.go .\utilities.go`
> Note: You can change the build location. Replace **installer.exe** with **Build/installer.exe** (Assets and Run.ps1 must be copied over)
2. Run `go run .\main.go .\utilities.go` or `.\installer.exe`
5 changes: 5 additions & 0 deletions Run.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$p = Start-Process "installer.exe" -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode
$startExe = new-object System.Diagnostics.ProcessStartInfo -args PowerShell.exe
$startExe.verbs
10 changes: 10 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module main

go 1.16

require (
github.com/KnicKnic/go-powershell v0.0.10
github.com/akavel/rsrc v0.10.2 // indirect
github.com/antonfisher/nested-logrus-formatter v1.3.1
github.com/sirupsen/logrus v1.8.1
)
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
github.com/KnicKnic/go-powershell v0.0.10 h1:M/FfMm3TI55J+mBlK61+nG8M59XRjoQETDfN5Wpnyoo=
github.com/KnicKnic/go-powershell v0.0.10/go.mod h1:1NuEA+s0LRuwaus0jBS5CT5diK5nhds8LdJtYgC0I7U=
github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
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/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
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/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6 h1:ZJUmhYTp8GbGC0ViZRc2U+MIYQ8xx9MscsdXnclfIhw=
golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
227 changes: 227 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
package main

import (
"bufio"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"

nested "github.com/antonfisher/nested-logrus-formatter"
log "github.com/sirupsen/logrus"
)

type Git struct {
Version string `json:"tag_name"`
Assets []struct {
DownloadURL string `json:"browser_download_url"`
Name string `json:"name"`
}
}

const url = "https://api.github.com/repos/TheHellBox/KISS-multiplayer/releases/latest"

func main() {
/* Initialize Logger */
log.SetLevel(log.DebugLevel)
log.SetFormatter(&nested.Formatter{
HideKeys: true,
TimestampFormat: "2006-01-02 15:04:05",
TrimMessages: true,
})

log.Infoln("Installer made by Daniel W (Vitex#1248)")

if Update() {
Download()
} else {
response, err := http.Get(url); if err != nil {
log.Errorln(err)
}; defer response.Body.Close()

git := Git{}
if err = json.NewDecoder(response.Body).Decode(&git); err != nil {
log.Errorln(err)
os.Exit(1)
}

log.Infoln("Running with KissMP Version:", git.Version)

cmd := exec.Command(fmt.Sprintf("./Downloads/Extracted/%s/windows/kissmp-bridge.exe", git.Version))
cmdReader, err := cmd.StdoutPipe(); if err != nil {
log.Errorln("Error creating stdoutpipe.", err)
os.Exit(1)
}

scanner := bufio.NewScanner(cmdReader)
go func() {
for scanner.Scan() {
log.Infoln(scanner.Text(), "\n")
}
}()

if err = cmd.Start(); err != nil {
log.Errorln("Error starting bridge.", err)
os.Exit(1)
}

if err = cmd.Wait(); err != nil {
log.Errorln("Error waiting for cmd. (make sure this isn't running anywhere else)", err)
os.Exit(1)
}
}
}

func Update() bool {
utilities := Utilities{}
git := Git{}

return !utilities.Exists(fmt.Sprintf("./Downloads/Extracted/%s", git.Version))
}

func Download() {
req, err := http.NewRequest("GET", url, nil); if err != nil {
log.Errorln(err)
};

req.Header = http.Header{
"Host": []string{"api.github.com"},
"Content-Type": []string{"application/json"},
"User-Agent": []string{"PostmanRuntime/7.28.0"},
"Authorization": []string{"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"},
}

client := &http.Client{}
response, err := client.Do(req); if err != nil {
log.Errorln(err)
os.Exit(1)
}

git := Git{}
if err = json.NewDecoder(response.Body).Decode(&git); err != nil {
log.Errorln(err)
os.Exit(1)
}

filename := git.Assets[0].Name

log.Infoln("New version available:", git.Version)

/* Download File */
utilities := Utilities{}

if _, err := os.Stat(fmt.Sprintf("./Downloads/%s", filename)); err != nil {
err := utilities.DownloadFile(git.Assets[0].DownloadURL, fmt.Sprintf("./Downloads/%s", filename)); if err != nil {
if strings.Contains(err.Error(), "path specified") {
if err = os.MkdirAll(filepath.Dir("./Downloads/"), os.ModePerm); err != nil {
log.Errorln("Failed creating Downloads directory")
}
}

err = utilities.DownloadFile(git.Assets[0].DownloadURL, fmt.Sprintf("./Downloads/%s", filename)); if err != nil {
log.Errorln("Failed downloading file.", err)
}

log.Infoln("Downloaded", filename)
}
}

/* Extract Mod */
f := filename[:strings.IndexByte(filename, '.')]
f = strings.ReplaceAll(f, ".", "_")

utilities.Unzip(fmt.Sprintf("./Downloads/%s", filename), "./Downloads/Extracted/")
if err := os.Rename(fmt.Sprintf("./Downloads/Extracted/%s", f), fmt.Sprintf("./Downloads/Extracted/%s", git.Version)); err != nil {
log.Errorln("Error renaming dir.", err)
}

/* Remove mod download */
if utilities.Exists(fmt.Sprintf("./Downloads/%s", filename)) {
os.Remove(fmt.Sprintf("./Downloads/%s", filename))
}

var gameDirectory string = ""

if utilities.Exists(fmt.Sprintf("%s\\BeamNG.drive", os.Getenv("LocalAppData"))) {
gameDirectory = fmt.Sprintf("%s\\BeamNG.drive", os.Getenv("LocalAppData"))
log.Infoln("Game Directory Found:", gameDirectory)
}

/* Move the mod */
tempMod, err := os.Open(fmt.Sprintf("./Downloads/Extracted/%s/KISSMultiplayer.zip", git.Version)); if err != nil {
log.Errorln("Failed moving mod.", err)
os.Exit(1)
}; defer tempMod.Close()

items, _ := ioutil.ReadDir(gameDirectory)
var latestVersionStr string = "0"
var latestVersion float64 = 0
for _, item := range items {
ver, _ := strconv.ParseFloat(item.Name(), 64)
if ver > latestVersion {
latestVersionStr = fmt.Sprintf("%.2f", ver)
}
}

destination, err := os.Create(fmt.Sprintf("%s\\%s\\mods\\KISSMultiplayer.zip", gameDirectory, latestVersionStr)); if err != nil {
log.Errorln("Failed opening mods directory.", err)
os.Exit(1)
}; defer destination.Close()

_, err = io.Copy(destination, tempMod); if err != nil {
log.Errorln("Failed copying mods.", err)
os.Exit(1)
}

// echo oLink.TargetPath = "%%myPath%%/Downloads/Extracted/%s/windows/kissmp-bridge.exe" >> CreateShortcut.vbs

dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
log.Fatal(err)
}

batchFile := fmt.Sprintf(`
set "myPath=%%~dp0"
echo Set oWS = WScript.CreateObject("WScript.Shell") > CreateShortcut.vbs
echo sLinkFile = "%%AppData%%\\Microsoft\Windows\Start Menu\Programs\KissMP Bridge.lnk" >> CreateShortcut.vbs
echo Set oLink = oWS.CreateShortcut(sLinkFile) >> CreateShortcut.vbs
echo oLink.WorkingDirectory = "%s/" >> CreateShortcut.vbs
echo oLink.TargetPath = "powershell.exe" >> CreateShortcut.vbs
echo oLink.Arguments = "-ExecutionPolicy bypass %s/Run.ps1" >> CreateShortcut.vbs
echo oLink.Description = "KissMP Bridge" >> CreateShortcut.vbs
echo oLink.IconLocation = "%s/Assets/Icon.ico" >> CreateShortcut.vbs
echo oLink.Save >> CreateShortcut.vbs
cscript CreateShortcut.vbs
del CreateShortcut.vbs
`, dir, dir, dir)

file, err := os.OpenFile(fmt.Sprintf("%s\\shortcut_%s.bat", dir, git.Version), os.O_RDWR | os.O_CREATE | os.O_TRUNC, 0755); if err != nil {
log.Errorln(err)
os.Exit(1)
}

_, err = file.Write([]byte(batchFile)); if err != nil {
log.Errorln(err)
os.Exit(1)
}; file.Close()

cmd := exec.Command(fmt.Sprintf("%s\\shortcut_%s.bat", dir, git.Version))
_, err = cmd.Output(); if err != nil {
log.Errorln(err.Error())
os.Exit(1)
}

os.Remove(fmt.Sprintf("./shortcut_%s.bat", git.Version))

log.Infoln(fmt.Sprintf("KissMP %s Successfully Installed", git.Version))
}

func Uninstall() {

}
96 changes: 96 additions & 0 deletions utilities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"archive/zip"
"io"
"net/http"
"os"
"path/filepath"
)

type Utilities struct{}

func (utilities *Utilities) DownloadFile(url string, path string) error {
response, err := http.Get(url); if err != nil {
return err
}; defer response.Body.Close()

/* Create the File */
out, err := os.Create(path); if err != nil {
return err
}; defer out.Close()

_, err = io.Copy(out, response.Body)

return err
}

func (utilities *Utilities) Unzip(path string, dest string) ([]string, error) {
var filenames[] string

reader, err := zip.OpenReader(path); if err != nil {
return filenames, err
}; defer reader.Close()

for _, file := range reader.File {
filePath := filepath.Join(dest, file.Name)

filenames = append(filenames, filePath)
if file.FileInfo().IsDir() {
os.MkdirAll(filePath, os.ModePerm)
continue
}

if err = os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return filenames, err
}

outFile, err := os.OpenFile(filePath, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, file.Mode()); if err != nil {
return filenames, err
}

rc, err := file.Open(); if err != nil {
return filenames, err
}

_, err = io.Copy(outFile, rc)

outFile.Close()
rc.Close()

if err != nil {
return filenames, err
}
}

return filenames, err
}

func (utilities *Utilities) DeleteDirectory(dir string) error {
d, err := os.Open(dir)
if err != nil {
return err
}
defer d.Close()
names, err := d.Readdirnames(-1)
if err != nil {
return err
}
for _, name := range names {
err = os.RemoveAll(filepath.Join(dir, name))
if err != nil {
return err
}
}
return nil
}

func (utilities *Utilities) Exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}

return true
}

0 comments on commit 6d31c03

Please sign in to comment.