chore: first commit
This commit is contained in:
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Build output
|
||||||
|
launcher.exe
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# OS
|
||||||
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
.DS_Store
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module a301_launcher
|
||||||
|
|
||||||
|
go 1.24.0
|
||||||
|
|
||||||
|
require golang.org/x/sys v0.41.0 // indirect
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
158
main.go
Normal file
158
main.go
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user