Skip to content

Commit

Permalink
Finish installer and uninstaller code for Windows, move vars around a…
Browse files Browse the repository at this point in the history
… bit (webserver port var initialized in vars, not sdkapp)

Former-commit-id: 02902de
  • Loading branch information
kercre123 committed Nov 13, 2023
1 parent a0ebb94 commit 6c56239
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 46 deletions.
25 changes: 21 additions & 4 deletions chipper/cmd/windows/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"

"github.com/getlantern/systray"
"github.com/kercre123/chipper/pkg/logger"
"github.com/kercre123/chipper/pkg/vars"
"github.com/kercre123/chipper/pkg/wirepod/sdkapp"
botsetup "github.com/kercre123/chipper/pkg/wirepod/setup"
stt "github.com/kercre123/chipper/pkg/wirepod/stt/vosk"
"github.com/ncruces/zenity"
"golang.org/x/sys/windows/registry"
)

// this directory contains code which compiled a single program for end users. gui elements are implemented.
Expand All @@ -25,7 +26,7 @@ var mBoxSuccess = `Wire-pod has started successfully! It is now running in the b
var mBoxIcon = "./icons/start-up-full.png"

func getNeedsSetupMsg() string {
return `Wire-pod is now running in the background. You must set it up by heading to http://` + botsetup.GetOutboundIP().String() + `:` + sdkapp.WebPort + ` in a browser.`
return `Wire-pod is now running in the background. You must set it up by heading to http://` + botsetup.GetOutboundIP().String() + `:` + vars.WebPort + ` in a browser.`
}

func main() {
Expand All @@ -47,7 +48,23 @@ func main() {
os.Exit(1)
}
}
os.WriteFile(conf+"/runningPID", []byte(strconv.Itoa(os.Getpid())), 0777)
os.WriteFile(conf+"\\runningPID", []byte(strconv.Itoa(os.Getpid())), 0777)
os.WriteFile(filepath.Join(os.TempDir(), "/wirepodrunningPID"), []byte(strconv.Itoa(os.Getpid())), 0777)

keyPath := `Software\Microsoft\Windows\CurrentVersion\Uninstall\wire-pod`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, keyPath, registry.QUERY_VALUE)
if err != nil {
ErrMsg(fmt.Errorf("error opening key from the registry: " + err.Error()))
}
val, _, err := k.GetStringValue("InstallPath")
if err != nil {
ErrMsg(fmt.Errorf("error getting value from the registry: " + err.Error()))
}
err = os.Chdir(filepath.Join(val, "chipper"))
fmt.Println("Working directory: " + val)
if err != nil {
ErrMsg(fmt.Errorf("error setting directory to " + val))
}
systray.Run(onReady, onExit)
}

Expand Down Expand Up @@ -94,7 +111,7 @@ func onReady() {
)
ExitProgram(0)
case <-mBrowse.ClickedCh:
go openBrowser("http://" + botsetup.GetOutboundIP().String() + ":" + sdkapp.WebPort)
go openBrowser("http://" + botsetup.GetOutboundIP().String() + ":" + vars.WebPort)
}
}
}()
Expand Down
17 changes: 8 additions & 9 deletions chipper/cmd/windows/win-initwirepod.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/kercre123/chipper/pkg/vars"
wpweb "github.com/kercre123/chipper/pkg/wirepod/config-ws"
wp "github.com/kercre123/chipper/pkg/wirepod/preqs"
"github.com/kercre123/chipper/pkg/wirepod/sdkapp"
sdkWeb "github.com/kercre123/chipper/pkg/wirepod/sdkapp"
botsetup "github.com/kercre123/chipper/pkg/wirepod/setup"
"github.com/ncruces/zenity"
Expand All @@ -41,7 +40,7 @@ var voiceProcessor *wp.Server

var epodIsPosting bool

var NotSetUp string = "Wire-pod is not setup. Use the webserver at port " + sdkapp.WebPort + " to set up wire-pod."
var NotSetUp string = "Wire-pod is not setup. Use the webserver at port " + vars.WebPort + " to set up wire-pod."

func NeedsSetupMsg() {
go func() {
Expand All @@ -53,7 +52,7 @@ func NeedsSetupMsg() {
)
if err != nil {
if err == zenity.ErrExtraButton {
openBrowser("http://" + botsetup.GetOutboundIP().String() + ":" + sdkapp.WebPort)
openBrowser("http://" + botsetup.GetOutboundIP().String() + ":" + vars.WebPort)
}
}
}()
Expand Down Expand Up @@ -129,20 +128,20 @@ func BeginWirepodSpecific(sttInitFunc func() error, sttHandlerFunc interface{},
func StartFromProgramInit(sttInitFunc func() error, sttHandlerFunc interface{}, voiceProcessorName string) {
err := BeginWirepodSpecific(sttInitFunc, sttHandlerFunc, voiceProcessorName)
if err != nil {
logger.Println("Wire-pod is not setup. Use the webserver at port " + sdkapp.WebPort + " to set up wire-pod.")
logger.Println("Wire-pod is not setup. Use the webserver at port " + vars.WebPort + " to set up wire-pod.")
vars.APIConfig.PastInitialSetup = false
vars.WriteConfigToDisk()
NeedsSetupMsg()
systray.SetTooltip("wire-pod must be set up at http://" + botsetup.GetOutboundIP().String() + ":" + sdkapp.WebPort)
systray.SetTooltip("wire-pod must be set up at http://" + botsetup.GetOutboundIP().String() + ":" + vars.WebPort)
} else if !vars.APIConfig.PastInitialSetup {
logger.Println("Wire-pod is not setup. Use the webserver at port " + sdkapp.WebPort + " to set up wire-pod.")
logger.Println("Wire-pod is not setup. Use the webserver at port " + vars.WebPort + " to set up wire-pod.")
NeedsSetupMsg()
systray.SetTooltip("wire-pod must be set up at http://" + botsetup.GetOutboundIP().String() + ":" + sdkapp.WebPort)
systray.SetTooltip("wire-pod must be set up at http://" + botsetup.GetOutboundIP().String() + ":" + vars.WebPort)
} else if vars.APIConfig.STT.Service == "vosk" && vars.APIConfig.STT.Language == "" {
logger.Println("\033[33m\033[1mLanguage value is blank, but STT service is Vosk. Reinitiating setup process.\033[0m")
logger.Println("Wire-pod is not setup. Use the webserver at port " + sdkapp.WebPort + " to set up wire-pod.")
logger.Println("Wire-pod is not setup. Use the webserver at port " + vars.WebPort + " to set up wire-pod.")
NeedsSetupMsg()
systray.SetTooltip("wire-pod must be set up at http://" + botsetup.GetOutboundIP().String() + ":" + sdkapp.WebPort)
systray.SetTooltip("wire-pod must be set up at http://" + botsetup.GetOutboundIP().String() + ":" + vars.WebPort)
vars.APIConfig.PastInitialSetup = false
} else {
go StartChipper(true)
Expand Down
7 changes: 7 additions & 0 deletions chipper/cmd/wire-pod-installer/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,18 @@ func InstallWirePod(is InstallSettings) error {
UpdateInstallStatus("Updating registry...")

UpdateRegistry(is)
if is.RunAtStartup {
RunPodAtStartup(is)
}

UpdateInstallBar(90)

UpdateInstallStatus("Creating shortcut...")
CreateShortcut(is)

UpdateInstallStatus("Creating firewall rules...")
AllowThroughFirewall(is)

UpdateInstallStatus("Done!")

UpdateInstallBar(100)
Expand Down
28 changes: 20 additions & 8 deletions chipper/cmd/wire-pod-installer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
"embed"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
Expand All @@ -20,6 +23,8 @@ var iconData embed.FS

var amd64podURL string = "https://github.com/kercre123/wire-pod/releases/latest/download/wire-pod-win-amd64.zip"

//var amd64podURL string = "http://192.168.1.2:82/wire-pod-win-amd64.zip"

var DefaultInstallationDirectory string = "C:\\Program Files\\wire-pod"

var icon *fyne.StaticResource
Expand Down Expand Up @@ -55,7 +60,14 @@ func GetStatusChan() chan string {
return installerStatusUpdate
}

func PostInstall(myApp fyne.App) {
func ExecuteDetached(program string) error {
cmd := exec.Command(program)
// Start the program in a new process group to make it detached
cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP}
return cmd.Start()
}

func PostInstall(myApp fyne.App, is InstallSettings) {
var shouldStartPod bool = true
window := myApp.NewWindow("wire-pod installer")
window.Resize(fyne.Size{Width: 600, Height: 100})
Expand All @@ -74,7 +86,8 @@ func PostInstall(myApp fyne.App) {

exitButton := widget.NewButton("Exit", func() {
if shouldStartPod {
fmt.Println("Would start wire-pod here")
window.Hide()
ExecuteDetached(filepath.Join(is.Where, "chipper/chipper.exe"))
}
os.Exit(0)
})
Expand Down Expand Up @@ -120,7 +133,7 @@ func DoInstall(myApp fyne.App, is InstallSettings) {
}()
InstallWirePod(is)
window.Hide()
PostInstall(myApp)
PostInstall(myApp, is)
}

func GetPreferences(myApp fyne.App) {
Expand All @@ -129,12 +142,9 @@ func GetPreferences(myApp fyne.App) {
window.SetIcon(icon)
window.Resize(fyne.Size{Width: 600, Height: 200})
window.CenterOnScreen()
launchOnStartup := widget.NewCheck("Launch on startup?", func(checked bool) {
launchOnStartup := widget.NewCheck("Automatically launch wire-pod after login?", func(checked bool) {
is.RunAtStartup = checked
})
autoUpdate := widget.NewCheck("Auto-update?", func(checked bool) {
is.AutoUpdate = checked
})

installDir := widget.NewEntry()
installDir.SetText(DefaultInstallationDirectory)
Expand Down Expand Up @@ -168,7 +178,6 @@ func GetPreferences(myApp fyne.App) {
Text: "This program will install wire-pod with the following settings.",
}),
launchOnStartup,
autoUpdate,
widget.NewSeparator(),
widget.NewRichText(&widget.TextSegment{
Text: "Installation Directory",
Expand Down Expand Up @@ -199,6 +208,9 @@ func StopWirePodIfRunning() {
}

func ValidateInstallDirectory(dir string) bool {
if dir == "C:\\Program Files" || dir == "C:\\Program Files\\" {
return false
}
var dirWithoutLast string
splitDir := strings.Split(dir, "\\")
dirWithoutLast = splitDir[0]
Expand Down
40 changes: 40 additions & 0 deletions chipper/cmd/wire-pod-installer/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"fmt"
"log"
"os/exec"
"path/filepath"

"golang.org/x/sys/windows/registry"
Expand Down Expand Up @@ -35,5 +37,43 @@ func UpdateRegistry(is InstallSettings) {
k.SetStringValue("Publisher", publisher)
k.SetStringValue("UninstallString", uninstallString)
k.SetStringValue("InstallLocation", installLocation)
k.SetStringValue("InstallPath", is.Where)
fmt.Println("Registry entries successfully created")
}

func RunPodAtStartup(is InstallSettings) {
key, _ := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.SET_VALUE)
key.SetStringValue("wire-pod", filepath.Join(is.Where, "\\chipper\\chipper.exe"))
}

func AllowThroughFirewall(is InstallSettings) {
cmdStr := fmt.Sprintf("netsh advfirewall firewall add rule name=\"wire-pod\" dir=in action=allow program=\"%s\\chipper\\chipper.exe\" enable=yes", is.Where)
fmt.Println("Executing command:", cmdStr)
cmd := exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
"name=wire-pod",
"dir=in",
"action=allow",
"profile=any",
"program="+is.Where+"\\chipper\\chipper.exe",
"enable=yes")

out, err := cmd.Output()
if err != nil {
fmt.Println(string(out))
log.Fatalf("Failed to execute command in: %s", err)
}
cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
"name=wire-pod",
"dir=out",
"action=allow",
"profile=any",
"program="+is.Where+"\\chipper\\chipper.exe",
"enable=yes")

err = cmd.Run()
if err != nil {
log.Fatalf("Failed to execute command out: %s", err)
}

log.Println("Firewall rule added successfully.")
}
43 changes: 36 additions & 7 deletions chipper/cmd/wire-pod-installer/uninstall/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import (
)

func StopWirePodIfRunning() {
confDir, _ := os.UserConfigDir()
podDir := confDir + "/wire-pod"
podPid, err := os.ReadFile(podDir + "/runningPID")
podPid, err := os.ReadFile(filepath.Join(os.TempDir(), "/wirepodrunningPID"))
if err == nil {
pid, _ := strconv.Atoi(string(podPid))
// doesn't work on unix, but should on Windows
Expand All @@ -29,15 +27,46 @@ func StopWirePodIfRunning() {

func main() {
StopWirePodIfRunning()
wd, _ := os.Getwd()
os.RemoveAll(filepath.Join(wd, "chipper"))
os.RemoveAll(filepath.Join(wd, "vector-cloud"))
err := zenity.Question(
"Would you like to remove application data, like saved bot settings or API preferences?",
zenity.ExtraButton("No"),
)
if err == nil {
conf, _ := os.UserConfigDir()
os.RemoveAll(filepath.Join(conf, "wire-pod"))
}
keyPath := `Software\Microsoft\Windows\CurrentVersion\Uninstall\wire-pod`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, keyPath, registry.QUERY_VALUE)
if err != nil {
fmt.Println(err)
return
}
val, _, err := k.GetStringValue("InstallPath")
if err != nil {
fmt.Println(err)
return
}

k.Close()
registry.DeleteKey(registry.LOCAL_MACHINE, keyPath)

DontRunPodAtStartup()

fmt.Println(val)

os.RemoveAll(filepath.Join(val, "chipper"))
os.RemoveAll(filepath.Join(val, "vector-cloud"))
os.Remove("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\wire-pod.lnk")
zenity.Info(
"wire-pod has been successfully uninstalled.",
"wire-pod has successfully been uninstalled.",
zenity.InfoIcon,
zenity.Title("wire-pod uninstaller"),
)
os.RemoveAll(val)
os.Exit(0)
}

func DontRunPodAtStartup() {
key, _ := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.SET_VALUE)
key.DeleteValue("wire-pod")
}
13 changes: 13 additions & 0 deletions chipper/pkg/vars/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ var (
Certs = "../certs"
)

var WebPort string = "8080"

// /home/name/.anki_vector/
var SDKIniPath string
var BotJdocs []botjdoc
Expand Down Expand Up @@ -136,6 +138,17 @@ func Init() {
os.Mkdir(Certs, 0777)
}

if os.Getenv("WEBSERVER_PORT") != "" {
if _, err := strconv.Atoi(os.Getenv("WEBSERVER_PORT")); err == nil {
WebPort = os.Getenv("WEBSERVER_PORT")
} else {
logger.Println("WEBSERVER_PORT contains letters, using default of 8080")
WebPort = "8080"
}
} else {
WebPort = "8080"
}

// figure out user SDK path, containing sdk_config.ini
// has to be done like this because wire-pod is running as root
// path should be /home/name/wire-pod/chipper
Expand Down
9 changes: 4 additions & 5 deletions chipper/pkg/wirepod/config-ws/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/kercre123/chipper/pkg/vars"
"github.com/kercre123/chipper/pkg/wirepod/localization"
processreqs "github.com/kercre123/chipper/pkg/wirepod/preqs"
"github.com/kercre123/chipper/pkg/wirepod/sdkapp"
botsetup "github.com/kercre123/chipper/pkg/wirepod/setup"
"github.com/ncruces/zenity"
)
Expand Down Expand Up @@ -333,12 +332,12 @@ func StartWebServer() {
http.HandleFunc("/session-certs/", certHandler)
webRoot := http.FileServer(http.Dir("./webroot"))
http.Handle("/", webRoot)
fmt.Printf("Starting webserver at port " + sdkapp.WebPort + " (http://localhost:" + sdkapp.WebPort + ")\n")
if err := http.ListenAndServe(":"+sdkapp.WebPort, nil); err != nil {
logger.Println("Error binding to " + sdkapp.WebPort + ": " + err.Error())
fmt.Printf("Starting webserver at port " + vars.WebPort + " (http://localhost:" + vars.WebPort + ")\n")
if err := http.ListenAndServe(":"+vars.WebPort, nil); err != nil {
logger.Println("Error binding to " + vars.WebPort + ": " + err.Error())
if vars.Packaged {
zenity.Error(
"FATAL: Wire-pod was unable to bind to port "+sdkapp.WebPort+". Another process is likely using it. Exiting.",
"FATAL: Wire-pod was unable to bind to port "+vars.WebPort+". Another process is likely using it. Exiting.",
zenity.ErrorIcon,
zenity.Title("wire-pod"),
)
Expand Down
Loading

0 comments on commit 6c56239

Please sign in to comment.