work/main.go

245 lines
5.8 KiB
Go

package main
import (
"fmt"
"io"
"log"
"net"
"os"
"os/exec"
"strings"
"time"
"github.com/charmbracelet/huh"
"github.com/spf13/viper"
"golang.org/x/crypto/ssh"
)
type Config struct {
SSHUser string `mapstructure:"SSH_USER"`
SSHHost string `mapstructure:"SSH_HOST"`
VardaUser string `mapstructure:"VARDA_USER"`
VardaHost string `mapstructure:"VARDA_HOST"`
LouHost string `mapstructure:"LOU_HOST"`
LouUser string `mapstructure:"LOU_USER"`
LouMac string `mapstructure:"LOU_MAC"`
RDPUser string `mapstructure:"RDP_USER"`
RDPPassword string `mapstructure:"RDP_PASSWORD"`
LouIP string `mapstructure:"LOU_IP"`
SSHPort int `mapstructure:"SSH_PORT"`
}
var cfg Config
func init() {
log.Println("Loading Config File")
viper.SetConfigFile("work-config.toml")
viper.SetConfigType("toml")
viper.AddConfigPath(".")
viper.AutomaticEnv()
err := viper.ReadInConfig()
if err != nil {
log.Printf("error loading config file: %v", err)
}
allSettings := viper.AllSettings()
log.Printf("All loaded settings: %+v", allSettings)
err = viper.UnmarshalKey("default", &cfg)
if err != nil {
log.Printf("unable to decode into struct: %v", err)
}
}
func main() {
// err := LoadConfig()
// if err != nil {
// log.Printf("error: %v", err)
// }
var choice string
form := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("What would you like to do?").
Options(
huh.NewOption("Start", "Start"),
huh.NewOption("Stop Work", "stop Work"),
huh.NewOption("Show Week Summary", "show week summary"),
huh.NewOption("Show Month Summary", "show month summary"),
huh.NewOption("Start Break", "start break"),
huh.NewOption("Stop Break", "stop break"),
huh.NewOption("Export Timetable", "export"),
huh.NewOption("Wake Lou", "wake lou"),
huh.NewOption("Connect to Varda", "connect to varda"),
huh.NewOption("Connect to Lou", "connect to lou"),
huh.NewOption("Start RDP Connection", "start rdp connection"),
).
Value(&choice),
),
)
err := form.Run()
if err != nil {
fmt.Println("Error:", err)
return
}
switch choice {
case "Start":
connect()
// startSequence()
case "stop Work":
runCommand("timew", "stop", "work")
case "start break":
runCommand("timew", "stop", "work")
runCommand("timew", "start", "break")
case "stop break":
runCommand("timew", "stop", "break")
runCommand("timew", "start", "work")
case "show week summary":
runCommand("timew", "summary", ":week", "work")
case "show month summary":
runCommand("timew", "summary", ":month", "work")
case "wake lou":
wakeLou()
case "connect to varda":
connectToVarda()
case "connect to lou":
connectToLou()
case "start rdp connection":
startRDPConnection()
case "export":
fmt.Println("Exporting Work times")
}
}
func connect() {
runCommand("timew", "start", "work")
wakeLou()
sshClient, err := ssh.Dial("tcp", cfg.SSHHost+":"+fmt.Sprintf("%v", cfg.SSHPort), makeSSHClient())
if err != nil {
log.Fatal("Failed to dial: ", err)
}
defer sshClient.Close()
session, err := sshClient.NewSession()
if err != nil {
log.Fatal("Failed to create session: ", err)
}
defer session.Close()
go forwardPort(sshClient, "2048", cfg.LouIP, "22")
go forwardPort(sshClient, "6000", cfg.LouIP, "3389")
connectToLou()
}
func forwardPort(sshConn *ssh.Client, localPort, remoteHost, remotePort string) {
listener, err := net.Listen("tcp", "127.0.0.1:"+localPort)
if err != nil {
log.Printf("Fehler beim Öffnen des lokalen Ports %s: %v", localPort, err)
return
}
defer listener.Close()
for {
localConn, err := listener.Accept()
if err != nil {
log.Printf("Fehler beim Akzeptieren der Verbindung: %v", err)
continue
}
remoteConn, err := sshConn.Dial("tcp", remoteHost+":"+remotePort)
if err != nil {
log.Printf("Fehler beim Verbinden zum Remote-Host %s:%s: %v", remoteHost, remotePort, err)
localConn.Close()
continue
}
go copyConn(localConn, remoteConn)
go copyConn(remoteConn, localConn)
}
}
func copyConn(dst, src net.Conn) {
defer dst.Close()
defer src.Close()
io.Copy(dst, src)
}
func makeSSHClient() *ssh.ClientConfig {
keypath := os.ExpandEnv("$HOME/.ssh/hegenberg")
keyBytes, err := os.ReadFile(keypath)
if err != nil {
log.Fatalf("Failed to read private key: %s", err)
}
key, err := ssh.ParsePrivateKeyWithPassphrase(keyBytes, []byte(cfg.RDPPassword))
if err != nil {
log.Fatalf("Failed to parse private key: %s", err)
}
return &ssh.ClientConfig{
User: cfg.SSHUser,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(key),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 5 * time.Second,
}
}
func runCommand(name string, args ...string) {
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
err := cmd.Run()
if err != nil {
fmt.Println("Error:", err)
}
}
func startSequence() {
runCommand("timew", "start", "work")
wakeLou()
connectToVarda()
}
func wakeLou() {
sshCommand := fmt.Sprintf("ssh -tt -p %s %s@%s ssh -tt %s@%s \"wakeonlan %s && exit\"",
fmt.Sprintf("%v", cfg.SSHPort),
cfg.SSHUser,
cfg.SSHHost,
cfg.VardaUser,
cfg.VardaHost,
cfg.LouMac)
args := strings.Split(sshCommand, " ")
log.Println(args)
runCommand("ssh", args[1:]...)
}
func connectToVarda() {
sshCommand := fmt.Sprintf("ssh -tt -L 2048:%s:22 %s@%s",
cfg.LouHost,
cfg.SSHUser,
cfg.SSHHost)
args := strings.Split(sshCommand, " ")
runCommand("ssh", args[1:]...)
}
func connectToLou() {
sshCommand := fmt.Sprintf("ssh -tt -L 6000:%s:3389 -p 2048 %s@127.0.0.1",
cfg.LouHost,
cfg.SSHUser)
args := strings.Split(sshCommand, " ")
runCommand("ssh", args[1:]...)
}
func startRDPConnection() {
rdpCommand := fmt.Sprintf("xfreerdp /u:%s /p:%s /v:127.0.0.1:6000 /size:3000x1350",
cfg.RDPUser,
cfg.RDPPassword)
runCommand("bash", "-c", rdpCommand)
}