200 lines
5.2 KiB
Go
200 lines
5.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"os"
|
||
|
"time"
|
||
|
|
||
|
"golang.org/x/sys/windows/registry"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
|
||
|
ex, err := os.Executable()
|
||
|
if err != nil {
|
||
|
log.Fatalf("failed to get executable path: %v", err)
|
||
|
}
|
||
|
programFullPath := fmt.Sprintf("\"%s\"", ex)
|
||
|
|
||
|
ruTorrentURL, err := getRUTorrentURL()
|
||
|
if err != nil {
|
||
|
log.Fatalf("failed to get ruTorrent URL: %v", err)
|
||
|
}
|
||
|
|
||
|
if len(os.Args[1:]) < 1 {
|
||
|
err := registerProtocolHandler(programFullPath)
|
||
|
if err != nil {
|
||
|
log.Fatalf("failed to register protocol handler for magnet URLs: %v", err)
|
||
|
}
|
||
|
log.Printf("successfully set registry handler for magnet links")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
magnetLink := os.Args[1]
|
||
|
|
||
|
if len(magnetLink) > 7 {
|
||
|
if magnetLink[:7] != "magnet:" {
|
||
|
log.Fatalf("unexpected argument '%s', expected a magnet link", os.Args[1:])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
err = addRuTorrent(ruTorrentURL, magnetLink)
|
||
|
if err != nil {
|
||
|
log.Printf("failed to add magnet link to rutorrent: %v", err)
|
||
|
|
||
|
fmt.Println(ruTorrentURL)
|
||
|
fmt.Println(magnetLink)
|
||
|
time.Sleep(time.Minute)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func addRuTorrent(ruTorrentURL, magnetLink string) error {
|
||
|
|
||
|
addTorrentEndpoint := fmt.Sprintf("%s/php/addtorrent.php", ruTorrentURL)
|
||
|
|
||
|
/*
|
||
|
magnetLink, err := url.QueryUnescape(magnetLink)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to URL decode magnet link: %v", err)
|
||
|
}*/
|
||
|
|
||
|
form := url.Values{}
|
||
|
form.Add("url", magnetLink)
|
||
|
|
||
|
client := http.Client{}
|
||
|
|
||
|
resp, err := client.PostForm(addTorrentEndpoint, form)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to do POST request to '%s': %v", addTorrentEndpoint, err)
|
||
|
}
|
||
|
|
||
|
if resp.StatusCode != http.StatusOK {
|
||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||
|
defer resp.Body.Close()
|
||
|
fmt.Println(string(body))
|
||
|
return fmt.Errorf("unexpected HTTP status code '%d', expected '%d'", resp.StatusCode, http.StatusOK)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func getRUTorrentURL() (string, error) {
|
||
|
|
||
|
userConfigDir, err := os.UserConfigDir()
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to get user config dir: %v", err)
|
||
|
}
|
||
|
|
||
|
configDir := fmt.Sprintf("%s/dipole", userConfigDir)
|
||
|
configFile := fmt.Sprintf("%s/dipole.conf", configDir)
|
||
|
|
||
|
if _, err := os.Stat(configDir); os.IsNotExist(err) {
|
||
|
if err := os.Mkdir(configDir, 0700); err != nil {
|
||
|
return "", fmt.Errorf("failed to make config dir '%s': %v", configDir, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var ruTorrentURL string
|
||
|
if _, err := os.Stat(configFile); os.IsNotExist(err) {
|
||
|
// collect
|
||
|
fmt.Println("Enter your rutorrent instance URL: ")
|
||
|
_, err = fmt.Scanln(&ruTorrentURL)
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to scan line while collecting rutorrent URL: %v", err)
|
||
|
}
|
||
|
|
||
|
f, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to open config file '%s' for writing: %v", configFile, err)
|
||
|
}
|
||
|
|
||
|
_, err = f.Write([]byte(ruTorrentURL))
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to write ruTorrentURL to config file '%s': %v", configFile, err)
|
||
|
}
|
||
|
if err := f.Close(); err != nil {
|
||
|
return "", fmt.Errorf("failed to close config file '%s': %v", configFile, err)
|
||
|
}
|
||
|
} else {
|
||
|
f, err := os.Open(configFile)
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to open config file '%s': %v", configFile, err)
|
||
|
}
|
||
|
|
||
|
scanner := bufio.NewScanner(f)
|
||
|
for scanner.Scan() {
|
||
|
ruTorrentURL = scanner.Text()
|
||
|
}
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
return "", fmt.Errorf("failed to scan config file: %v", err)
|
||
|
}
|
||
|
|
||
|
if err := f.Close(); err != nil {
|
||
|
return "", fmt.Errorf("failed to close config file '%s': %v", configFile, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ruTorrentURL, err
|
||
|
}
|
||
|
|
||
|
func registerProtocolHandler(programFullPath string) error {
|
||
|
|
||
|
prefix := "SOFTWARE\\Classes\\"
|
||
|
urlScheme := "magnet"
|
||
|
basePath := prefix + urlScheme
|
||
|
permission := uint32(registry.QUERY_VALUE | registry.SET_VALUE)
|
||
|
baseKey := registry.CURRENT_USER
|
||
|
|
||
|
// create key
|
||
|
k, _, err := registry.CreateKey(baseKey, basePath, permission)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create base key: %v", err)
|
||
|
}
|
||
|
|
||
|
// set description
|
||
|
err = k.SetStringValue("", "Dipole Magnet Link Handler")
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to set description string value: %v", err)
|
||
|
}
|
||
|
err = k.SetStringValue("URL Protocol", "")
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to set description url protocol value: %v", err)
|
||
|
}
|
||
|
|
||
|
// set icon
|
||
|
k, _, err = registry.CreateKey(registry.CURRENT_USER, "lumiere\\DefaultIcon", registry.ALL_ACCESS)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to set icon key: %v", err)
|
||
|
}
|
||
|
err = k.SetStringValue("", programFullPath+",1")
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to set programFullPath value for icon: %v", err)
|
||
|
}
|
||
|
|
||
|
// create tree
|
||
|
_, _, err = registry.CreateKey(baseKey, basePath+"\\shell", permission)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create shell key: %v", err)
|
||
|
}
|
||
|
_, _, err = registry.CreateKey(baseKey, basePath+"\\shell\\open", permission)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create shell/open key: %v", err)
|
||
|
}
|
||
|
k, _, err = registry.CreateKey(baseKey, basePath+"\\shell\\open\\command", permission)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to create shell/open/command key: %v", err)
|
||
|
}
|
||
|
|
||
|
// set open command
|
||
|
err = k.SetStringValue("", programFullPath+" \"%1\"")
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to set programFullPath for open command: %v", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|