Files
a301_launcher/main.go
2026-02-24 20:52:16 +09:00

159 lines
3.6 KiB
Go

package main
import (
"fmt"
"net/url"
"os"
"os/exec"
"path/filepath"
"strings"
"golang.org/x/sys/windows/registry"
)
const (
protocolName = "a301"
gameExeName = "A301.exe"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("사용법:")
fmt.Println(" launcher.exe install 프로토콜 등록")
fmt.Println(" launcher.exe uninstall 프로토콜 제거")
fmt.Println(" launcher.exe a301://... 게임 실행")
os.Exit(1)
}
arg := os.Args[1]
switch {
case arg == "install":
if err := install(); err != nil {
fmt.Fprintf(os.Stderr, "설치 실패: %v\n", err)
os.Exit(1)
}
fmt.Println("a301:// 프로토콜이 등록되었습니다.")
case arg == "uninstall":
if err := uninstall(); err != nil {
fmt.Fprintf(os.Stderr, "제거 실패: %v\n", err)
os.Exit(1)
}
fmt.Println("a301:// 프로토콜이 제거되었습니다.")
case strings.HasPrefix(arg, protocolName+"://"):
if err := handleURI(arg); err != nil {
fmt.Fprintf(os.Stderr, "실행 실패: %v\n", err)
os.Exit(1)
}
default:
fmt.Fprintf(os.Stderr, "알 수 없는 명령: %s\n", arg)
os.Exit(1)
}
}
func launcherPath() (string, error) {
exe, err := os.Executable()
if err != nil {
return "", err
}
return filepath.Abs(exe)
}
func install() error {
exePath, err := launcherPath()
if err != nil {
return fmt.Errorf("실행 파일 경로를 찾을 수 없습니다: %w", err)
}
// HKCU\Software\Classes\a301
key, _, err := registry.CreateKey(
registry.CURRENT_USER,
`Software\Classes\`+protocolName,
registry.SET_VALUE,
)
if err != nil {
return fmt.Errorf("레지스트리 키 생성 실패: %w", err)
}
defer key.Close()
if err := key.SetStringValue("", "URL:A301 Protocol"); err != nil {
return err
}
if err := key.SetStringValue("URL Protocol", ""); err != nil {
return err
}
// shell\open\command
cmdKey, _, err := registry.CreateKey(
registry.CURRENT_USER,
`Software\Classes\`+protocolName+`\shell\open\command`,
registry.SET_VALUE,
)
if err != nil {
return fmt.Errorf("command 키 생성 실패: %w", err)
}
defer cmdKey.Close()
cmdValue := fmt.Sprintf(`"%s" "%%1"`, exePath)
if err := cmdKey.SetStringValue("", cmdValue); err != nil {
return err
}
return nil
}
func uninstall() error {
err := registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell\open\command`)
if err != nil && err != registry.ErrNotExist {
return err
}
err = registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell\open`)
if err != nil && err != registry.ErrNotExist {
return err
}
err = registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell`)
if err != nil && err != registry.ErrNotExist {
return err
}
err = registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName)
if err != nil && err != registry.ErrNotExist {
return err
}
return nil
}
func handleURI(rawURI string) error {
parsed, err := url.Parse(rawURI)
if err != nil {
return fmt.Errorf("URI 파싱 실패: %w", err)
}
token := parsed.Query().Get("token")
if token == "" {
return fmt.Errorf("토큰이 없습니다")
}
exePath, err := launcherPath()
if err != nil {
return err
}
gameDir := filepath.Dir(exePath)
gamePath := filepath.Join(gameDir, gameExeName)
if _, err := os.Stat(gamePath); os.IsNotExist(err) {
return fmt.Errorf("게임 파일을 찾을 수 없습니다: %s", gamePath)
}
cmd := exec.Command(gamePath, "-token", token)
cmd.Dir = gameDir
if err := cmd.Start(); err != nil {
return fmt.Errorf("게임 실행 실패: %w", err)
}
fmt.Printf("게임이 실행되었습니다 (PID: %d)\n", cmd.Process.Pid)
return nil
}