initial commit

This commit is contained in:
Steven Polley 2023-04-22 18:00:41 -06:00
parent ebf6ac96f5
commit 527cbebfce
5 changed files with 219 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
dipole.exe
dipole

View File

@ -1,3 +1,13 @@
# dipole
A magnet link handler for rutorrent
A magnet link handler for rutorrent.
Download your linux ISO's with style.
### Usage
Run the executable manually once, it will register itself as the handler for magnet links. If you move the exectuable, you will need to run it again to reregister its new path. It will also prompt you for the URL of your rutorrent instance.
If you need to change the URL of the rutorrent instance, delete the folder located at %appdata%\dipole, then run it again.
Then, click on magnet links in your web browser and they will automatically be added to your rutorrent instance.

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module deadbeef.codes/steven/dipole
go 1.20
require golang.org/x/sys v0.7.0

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

199
main.go Normal file
View File

@ -0,0 +1,199 @@
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
}