2ch/tst2
0
1package main2 3import (4 "fmt"5 "log"6 "net/http"7 "net/http/httputil"8 "net/url"9 "os"10 "os/exec"11 "path/filepath"12 "strings"13)14 15const indexHTML = `16<!DOCTYPE html>17<html lang="ru">18<head>19 <meta charset="UTF-8">20 <title>HF Seedbox</title>21 <style>22 body { margin: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; display: flex; flex-direction: column; height: 100vh; background-color: #1e1e1e; color: white; }23 .tabs { display: flex; background: #2d2d2d; box-shadow: 0 2px 5px rgba(0,0,0,0.5); z-index: 10; }24 .tab { flex: 1; padding: 15px; text-align: center; cursor: pointer; transition: background 0.2s; border-bottom: 3px solid transparent; }25 .tab:hover { background: #3d3d3d; }26 .tab.active { background: #3d3d3d; border-bottom: 3px solid #007acc; font-weight: bold; }27 iframe { flex: 1; border: none; width: 100%; height: 100%; background: #fff; }28 </style>29</head>30<body>31 <div class="tabs">32 <div class="tab active" onclick="switchTab('qb-ui', this)">qBittorrent</div>33 <div class="tab" onclick="switchTab('/fb/', this)">Filebrowser</div>34 </div>35 <iframe id="frame" src="/qb-ui"></iframe>36 37 <script>38 function switchTab(url, el) {39 document.getElementById('frame').src = url;40 document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));41 el.classList.add('active');42 }43 </script>44</body>45</html>46`47 48func writeQBConfig() {49 configDir := "/home/user/profile/qBittorrent/config"50 os.MkdirAll(configDir, 0755)51 52 configData := `[LegalNotice]53Accepted=true54 55[Preferences]56WebUI\Port=808257WebUI\LocalHostAuth=false58WebUI\AuthSubnetWhitelistEnabled=true59WebUI\AuthSubnetWhitelist=127.0.0.1/3260`61 err := os.WriteFile(filepath.Join(configDir, "qBittorrent.conf"), []byte(configData), 0644)62 if err != nil {63 log.Fatalf("Ошибка записи конфига qB: %v", err)64 }65}66 67func main() {68 // 1. Подготовка директорий и конфигов69 os.MkdirAll("/home/user/downloads", 0755)70 writeQBConfig()71 72 // 2. Запуск Filebrowser (на порту 8081)73 fbCmd := exec.Command("./filebrowser",74 "-a", "127.0.0.1",75 "-p", "8081",76 "-r", "/home/user/downloads",77 "--noauth",78 "-b", "/fb",79 "-d", "/home/user/filebrowser.db",80 )81 fbCmd.Stdout = os.Stdout82 fbCmd.Stderr = os.Stderr83 if err := fbCmd.Start(); err != nil {84 log.Fatalf("Не удалось запустить Filebrowser: %v", err)85 }86 fmt.Println("Filebrowser запущен на 127.0.0.1:8081")87 88 // 3. Запуск qBittorrent (на порту 8082)89 qbCmd := exec.Command("./qbittorrent-nox",90 "--webui-port=8082",91 "--profile=/home/user/profile",92 "--save-path=/home/user/downloads",93 )94 qbCmd.Stdout = os.Stdout95 qbCmd.Stderr = os.Stderr96 if err := qbCmd.Start(); err != nil {97 log.Fatalf("Не удалось запустить qBittorrent: %v", err)98 }99 fmt.Println("qBittorrent запущен на 127.0.0.1:8082")100 101 // 4. Настройка Reverse Proxy102 fbURL, _ := url.Parse("http://127.0.0.1:8081")103 qbURL, _ := url.Parse("http://127.0.0.1:8082")104 105 fbProxy := httputil.NewSingleHostReverseProxy(fbURL)106 qbProxy := httputil.NewSingleHostReverseProxy(qbURL)107 108 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {109 // Главная страница с вкладками110 if r.URL.Path == "/" {111 w.Header().Set("Content-Type", "text/html; charset=utf-8")112 w.Write([]byte(indexHTML))113 return114 }115 116 // Виртуальный путь для загрузки WebUI qBittorrent в iframe117 if r.URL.Path == "/qb-ui" {118 r.URL.Path = "/"119 qbProxy.ServeHTTP(w, r)120 return121 }122 123 // Запросы к Filebrowser124 if strings.HasPrefix(r.URL.Path, "/fb") {125 fbProxy.ServeHTTP(w, r)126 return127 }128 129 // Все остальные запросы (API, CSS, JS от qBittorrent) проксируются в qB130 qbProxy.ServeHTTP(w, r)131 })132 133 // 5. Запуск веб-сервера на порту 7860134 fmt.Println("Proxy сервер запущен на 0.0.0.0:7860")135 if err := http.ListenAndServe("0.0.0.0:7860", nil); err != nil {136 log.Fatalf("Ошибка запуска сервера: %v", err)137 }138}