Initial commit
@ -1,6 +1,2 @@
|
|||||||
# Stream Deck Go Plugin
|
# Mac HTTP Proxy Control
|
||||||
|
|
||||||
|
|
||||||
find everywhere with {{{NAME}}} and replace it with appropriate values
|
|
||||||
do the manifest
|
|
||||||
write code
|
|
||||||
|
10
src/Makefile
@ -1,7 +1,7 @@
|
|||||||
INSTALLDIR = ~/Library/Application\ Support/com.elgato.StreamDeck/Plugins/com.dlprows.{{{NAME}}}.sdPlugin
|
INSTALLDIR = ~/Library/Application\ Support/com.elgato.StreamDeck/Plugins/com.dlprows.httpproxy.sdPlugin
|
||||||
#BUILDDIR = build
|
#BUILDDIR = build
|
||||||
#RELEASEDIR = release
|
#RELEASEDIR = release
|
||||||
#SDPLUGINDIR = "./com.dlprows.{{{NAME}}}.sdPlugin"
|
#SDPLUGINDIR = "./com.dlprows.httpproxycontrol.sdPlugin"
|
||||||
|
|
||||||
update:
|
update:
|
||||||
killall Stream\ Deck || true
|
killall Stream\ Deck || true
|
||||||
@ -9,9 +9,9 @@ update:
|
|||||||
open -a Elgato\ Stream\ Deck
|
open -a Elgato\ Stream\ Deck
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -o com.dlprows.{{{NAME}}}.sdPlugin
|
go build -o com.dlprows.httpproxy.sdPlugin
|
||||||
rm com.dlprows.{{{NAME}}}.streamDeckPlugin
|
rm com.dlprows.httpproxy.streamDeckPlugin || true
|
||||||
./DistributionTool -b -i com.dlprows.{{{NAME}}}.sdPlugin -o .
|
./DistributionTool -b -i com.dlprows.httpproxy.sdPlugin -o .
|
||||||
|
|
||||||
|
|
||||||
#.PHONY: test install build logs
|
#.PHONY: test install build logs
|
||||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
53
src/com.dlprows.httpproxy.sdPlugin/manifest.json
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"Actions": [
|
||||||
|
{
|
||||||
|
"UUID": "com.dlprows.httpproxy.action",
|
||||||
|
"Name": "System Proxy",
|
||||||
|
"Tooltip": "Turn on/off system proxy",
|
||||||
|
"Icon": "Images/icon",
|
||||||
|
"States": [
|
||||||
|
{
|
||||||
|
"Image": "Images/pluginAction",
|
||||||
|
"TitleAlignment": "middle",
|
||||||
|
"FontSize": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Image": "Images/pluginAction",
|
||||||
|
"TitleAlignment": "middle",
|
||||||
|
"FontSize": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Image": "Images/pluginAction",
|
||||||
|
"TitleAlignment": "middle",
|
||||||
|
"FontSize": "12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Image": "Images/pluginAction",
|
||||||
|
"TitleAlignment": "middle",
|
||||||
|
"FontSize": "12"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Controllers": [ "Keypad" ],
|
||||||
|
"SupportedInMultiActions": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Author": "dlprows",
|
||||||
|
"Name": "Http Proxy Control",
|
||||||
|
"Description": "Turn on and off HTTP(S) proxy settings in mac os",
|
||||||
|
"URL": "https://encyclopediaofdaniel.com",
|
||||||
|
"Version": "1.0",
|
||||||
|
"CodePath": "httpproxycontrol",
|
||||||
|
"Category": "Networking [dlprows]",
|
||||||
|
"Icon": "Images/pluginIcon",
|
||||||
|
"CategoryIcon": "Images/categoryIcon",
|
||||||
|
"OS": [
|
||||||
|
{
|
||||||
|
"Platform": "mac",
|
||||||
|
"MinimumVersion": "13.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SDKVersion": 2,
|
||||||
|
"Software": {
|
||||||
|
"MinimumVersion": "6.0"
|
||||||
|
}
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"Actions": [
|
|
||||||
{
|
|
||||||
"UUID": "com.dlprows.{{{NAME}}}.dialaction",
|
|
||||||
"Name": "Volume",
|
|
||||||
"Tooltip": "Control system volume",
|
|
||||||
"Icon": "Images/icon",
|
|
||||||
"States": [
|
|
||||||
{
|
|
||||||
"Image": "Images/pluginAction",
|
|
||||||
"TitleAlignment": "middle",
|
|
||||||
"FontSize": "12"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Controllers": [ "Encoder" ],
|
|
||||||
"Encoder": {
|
|
||||||
"background": "backgroundImage",
|
|
||||||
"Icon": "Images/actionIcon",
|
|
||||||
"layout": "$B1",
|
|
||||||
"StackColor": "#AABBCC",
|
|
||||||
"TriggerDescription": {
|
|
||||||
"Rotate": "System Volume",
|
|
||||||
"Push": "Mute",
|
|
||||||
"Touch": "Mute"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"SupportedInMultiActions": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Author": "dlprows",
|
|
||||||
"Name": "{{{NAME}}}",
|
|
||||||
"Description": "Control volume on mac",
|
|
||||||
"URL": "https://encyclopediaofdaniel.com",
|
|
||||||
"Version": "1.0",
|
|
||||||
"CodePath": "{{{NAME}}}",
|
|
||||||
"Category": "Volume Control [dlprows]",
|
|
||||||
"Icon": "Images/pluginIcon",
|
|
||||||
"CategoryIcon": "Images/categoryIcon",
|
|
||||||
"OS": [
|
|
||||||
{
|
|
||||||
"Platform": "mac",
|
|
||||||
"MinimumVersion": "13.0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"SDKVersion": 2,
|
|
||||||
"Software": {
|
|
||||||
"MinimumVersion": "6.0"
|
|
||||||
}
|
|
||||||
}
|
|
10
src/go.mod
@ -1,7 +1,9 @@
|
|||||||
module macvolumecontrol
|
module httpproxycontrol
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk v1.0.1
|
require (
|
||||||
|
code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk v1.0.1 // indirect
|
||||||
require github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/b4b4r07/go-pipe v0.0.0-20191010045404-84b446f57366 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk v1.0.1 h1:2IoDJrWt6Bp5IcXTtqjdygDo3Ruh5VHsS9R5MjI2WWQ=
|
code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk v1.0.1 h1:2IoDJrWt6Bp5IcXTtqjdygDo3Ruh5VHsS9R5MjI2WWQ=
|
||||||
code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk v1.0.1/go.mod h1:SaMt3PIkPtNwkgrcLpD89GK/7tLaUkcEvOZaHUC66+4=
|
code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk v1.0.1/go.mod h1:SaMt3PIkPtNwkgrcLpD89GK/7tLaUkcEvOZaHUC66+4=
|
||||||
|
github.com/b4b4r07/go-pipe v0.0.0-20191010045404-84b446f57366 h1:FVAkDbBxovi2ID0vaxY7vCGvdKASt9r0TGPM1u4YQyg=
|
||||||
|
github.com/b4b4r07/go-pipe v0.0.0-20191010045404-84b446f57366/go.mod h1:1ymsiQNa3qebVEEVtuIdhtAXRfjO4qFCFq1bBUOT2HE=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/samwho/streamdeck v0.0.0-20190725183037-2b866fdcb4a6 h1:ocHB+wIjLCdideequ8l8dUem6DxHf/A4Mmo0TRxBf1U=
|
|
||||||
github.com/samwho/streamdeck v0.0.0-20190725183037-2b866fdcb4a6/go.mod h1:OjeKL1Q8xRGm1zHGmtu9JeQUFNOXXXIcSZvCNzRP3GM=
|
|
||||||
|
144
src/main.go
@ -2,21 +2,17 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"macvolumecontrol/logging"
|
"httpproxycontrol/logging"
|
||||||
"macvolumecontrol/volume"
|
"httpproxycontrol/networking"
|
||||||
|
|
||||||
"code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk"
|
"code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk"
|
||||||
sdcontext "code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk/context"
|
sdcontext "code.encyclopediaofdaniel.com/dlprows/streamdeck-sdk/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _currentSettings *volume.VolumeSettings = &volume.VolumeSettings{}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logging.Enable()
|
logging.Enable()
|
||||||
log.Println("Starting plugin")
|
log.Println("Starting plugin")
|
||||||
@ -38,64 +34,26 @@ func main() {
|
|||||||
|
|
||||||
func setup(client *streamdeck.Client) {
|
func setup(client *streamdeck.Client) {
|
||||||
log.Println("Registering actions")
|
log.Println("Registering actions")
|
||||||
action := client.Action("com.dlprows.macvolumecontrol.dialaction")
|
action := client.Action("com.dlprows.httpproxy.action")
|
||||||
|
|
||||||
contexts := make(map[string]struct{})
|
contexts := make(map[string]struct{})
|
||||||
|
|
||||||
action.RegisterHandler(streamdeck.DialRotate, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
action.RegisterHandler(streamdeck.KeyDown, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
||||||
log.Println("dial rotate")
|
log.Println("Key Down")
|
||||||
|
|
||||||
p := streamdeck.DialRotatePayload[any]{}
|
toggleVpn()
|
||||||
|
|
||||||
if err := json.Unmarshal(event.Payload, &p); err != nil {
|
client.SetState(ctx, getState())
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//volume.ChangeVolumeWithKeyboard(p.Ticks)
|
return nil
|
||||||
newSettings, err := volume.ChangeVolume(p.Ticks)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return setFeedbackIfNeeded(ctx, client, newSettings)
|
|
||||||
})
|
|
||||||
|
|
||||||
action.RegisterHandler(streamdeck.DialDown, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
|
||||||
log.Println("dial down")
|
|
||||||
|
|
||||||
newSettings, err := volume.ToggleMute()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return setFeedbackIfNeeded(ctx, client, newSettings)
|
|
||||||
})
|
|
||||||
|
|
||||||
action.RegisterHandler(streamdeck.TouchTap, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
|
||||||
log.Println("touch tap")
|
|
||||||
|
|
||||||
newSettings, err := volume.ToggleMute()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return setFeedbackIfNeeded(ctx, client, newSettings)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
action.RegisterHandler(streamdeck.WillAppear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
action.RegisterHandler(streamdeck.WillAppear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
||||||
log.Println("Will Appear")
|
log.Println("Will Appear")
|
||||||
contexts[event.Context] = struct{}{}
|
contexts[event.Context] = struct{}{}
|
||||||
|
|
||||||
newSettings, err := volume.GetVolumeSettings()
|
client.SetState(ctx, getState())
|
||||||
|
return nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return setFeedback(ctx, client, newSettings)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
action.RegisterHandler(streamdeck.WillDisappear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
action.RegisterHandler(streamdeck.WillDisappear, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) error {
|
||||||
@ -106,12 +64,7 @@ func setup(client *streamdeck.Client) {
|
|||||||
|
|
||||||
//start background thread to keep the display up to date if changed outside the stream deck
|
//start background thread to keep the display up to date if changed outside the stream deck
|
||||||
go func() {
|
go func() {
|
||||||
for range time.Tick(time.Second * 1) {
|
for range time.Tick(time.Second * 10) {
|
||||||
newSettings, err := volume.GetVolumeSettings()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for ctxStr := range contexts {
|
for ctxStr := range contexts {
|
||||||
//for each context
|
//for each context
|
||||||
@ -119,55 +72,60 @@ func setup(client *streamdeck.Client) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = sdcontext.WithContext(ctx, ctxStr)
|
ctx = sdcontext.WithContext(ctx, ctxStr)
|
||||||
|
|
||||||
setFeedback(ctx, client, newSettings)
|
client.SetState(ctx, getState())
|
||||||
}
|
}
|
||||||
_currentSettings = newSettings
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFeedback(ctx context.Context, client *streamdeck.Client, newSettings *volume.VolumeSettings) error {
|
func toggleVpn() error {
|
||||||
|
/*
|
||||||
|
if on, turn off
|
||||||
|
if off, turn on
|
||||||
|
if broken, turn off
|
||||||
|
*/
|
||||||
|
activeDevice, err := networking.GetActiveDevice()
|
||||||
|
|
||||||
payload := FeedbackPayload{}
|
if err != nil {
|
||||||
|
return err
|
||||||
opacity := 1.0
|
|
||||||
|
|
||||||
if newSettings.OutputMuted {
|
|
||||||
opacity = 0.5
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.Value = ValueWithOpacity[string]{
|
enabled, err := networking.IsProxyEnabled(activeDevice)
|
||||||
fmt.Sprintf("%d%%", newSettings.OutputVolume),
|
|
||||||
opacity,
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.Indicator = ValueWithOpacity[int]{
|
networking.SetProxyServer(activeDevice, "192.168.41.101", "8888")
|
||||||
newSettings.OutputVolume,
|
networking.SetProxyState(activeDevice, !enabled)
|
||||||
opacity,
|
|
||||||
}
|
|
||||||
|
|
||||||
payload.Icon = ValueWithOpacity[any]{nil, opacity}
|
|
||||||
|
|
||||||
return client.SetFeedback(ctx, payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setFeedbackIfNeeded(ctx context.Context, client *streamdeck.Client, newSettings *volume.VolumeSettings) error {
|
|
||||||
|
|
||||||
if _currentSettings.OutputVolume == newSettings.OutputVolume && _currentSettings.OutputMuted == newSettings.OutputMuted {
|
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getState() int {
|
||||||
|
/*
|
||||||
|
0 for no network
|
||||||
|
1 for proxy off
|
||||||
|
2 for proxy on
|
||||||
|
3 for busted
|
||||||
|
*/
|
||||||
|
activeDevice, err := networking.GetActiveDevice()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 3
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentSettings = newSettings
|
if activeDevice == "" {
|
||||||
return setFeedback(ctx, client, newSettings)
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type FeedbackPayload struct {
|
proxyEnabled, err := networking.IsProxyEnabled(activeDevice)
|
||||||
Value ValueWithOpacity[string] `json:"value"`
|
|
||||||
Indicator ValueWithOpacity[int] `json:"indicator"`
|
|
||||||
Icon ValueWithOpacity[any] `json:"icon"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ValueWithOpacity[T any] struct {
|
if err != nil {
|
||||||
Value T `json:"value,omitempty"`
|
return 3
|
||||||
Opacity float64 `json:"opacity"`
|
}
|
||||||
|
if proxyEnabled {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
108
src/networking/networking.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package networking
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetActiveDevice() (string, error) {
|
||||||
|
|
||||||
|
output, err := exec.Command("networksetup", "-listnetworkserviceorder").Output()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range strings.Split(strings.TrimSuffix(string(output), "\n"), "\n") {
|
||||||
|
|
||||||
|
if !strings.Contains(line, "Device:") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//(Hardware Port: Thunderbolt Ethernet Slot 2, Device: en8)
|
||||||
|
split := strings.Split(line, ",")
|
||||||
|
name := strings.Split(split[0], ":")[1]
|
||||||
|
name = strings.TrimPrefix(name, " ")
|
||||||
|
|
||||||
|
device := strings.Split(split[1], ":")[1]
|
||||||
|
device = device[1 : len(device)-1]
|
||||||
|
|
||||||
|
active := isDeviceActive(device)
|
||||||
|
|
||||||
|
if active {
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDeviceActive(device string) bool {
|
||||||
|
|
||||||
|
output, _ := exec.Command("ifconfig", device).Output()
|
||||||
|
|
||||||
|
for _, line := range strings.Split(strings.TrimSuffix(string(output), "\n"), "\n") {
|
||||||
|
|
||||||
|
if strings.Contains(line, "status: active") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsProxyEnabled(deviceName string) (bool, error) {
|
||||||
|
output, err := exec.Command("networksetup", "-getwebproxy", deviceName).Output()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
webEnabled := strings.Contains(string(output), "Enabled: Yes\n")
|
||||||
|
|
||||||
|
output, err = exec.Command("networksetup", "-getsecurewebproxy", deviceName).Output()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
secureEnabled := strings.Contains(string(output), "Enabled: Yes\n")
|
||||||
|
|
||||||
|
//todo: if they're not equal, its some sort of error case
|
||||||
|
return webEnabled && secureEnabled, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetProxyState(deviceName string, on bool) error {
|
||||||
|
onOff := "on"
|
||||||
|
if !on {
|
||||||
|
onOff = "off"
|
||||||
|
}
|
||||||
|
|
||||||
|
err := exec.Command("networksetup", "-setwebproxystate", deviceName, onOff).Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = exec.Command("networksetup", "-setsecurewebproxystate", deviceName, onOff).Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetProxyServer(deviceName string, host string, port string) error {
|
||||||
|
err := exec.Command("networksetup", "-setwebproxy", deviceName, host, port).Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = exec.Command("networksetup", "-setsecurewebproxy", deviceName, host, port).Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|