mirror of
https://github.com/putyy/res-downloader.git
synced 2026-01-12 14:14:55 +08:00
416 lines
9.8 KiB
Go
416 lines
9.8 KiB
Go
package core
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"res-downloader/core/shared"
|
|
sysRuntime "runtime"
|
|
"strings"
|
|
|
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
|
)
|
|
|
|
type respData map[string]interface{}
|
|
|
|
type ResponseData struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data"`
|
|
}
|
|
|
|
type HttpServer struct{}
|
|
|
|
func initHttpServer() *HttpServer {
|
|
if httpServerOnce == nil {
|
|
httpServerOnce = &HttpServer{}
|
|
}
|
|
return httpServerOnce
|
|
}
|
|
|
|
func (h *HttpServer) run() {
|
|
listener, err := net.Listen("tcp", globalConfig.Host+":"+globalConfig.Port)
|
|
if err != nil {
|
|
globalLogger.Err(err)
|
|
log.Fatalf("Service cannot start: %v", err)
|
|
}
|
|
fmt.Println("Service started, listening http://" + globalConfig.Host + ":" + globalConfig.Port)
|
|
if err1 := http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Host == "127.0.0.1:"+globalConfig.Port && HandleApi(w, r) {
|
|
|
|
} else {
|
|
proxyOnce.Proxy.ServeHTTP(w, r) // 代理
|
|
}
|
|
})); err1 != nil {
|
|
globalLogger.Err(err1)
|
|
fmt.Printf("Service startup exception: %v", err1)
|
|
}
|
|
}
|
|
|
|
func (h *HttpServer) downCert(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/x-x509-ca-data")
|
|
w.Header().Set("Content-Disposition", "attachment;filename=res-downloader-public.crt")
|
|
w.Header().Set("Content-Transfer-Encoding", "binary")
|
|
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(appOnce.PublicCrt)))
|
|
w.WriteHeader(http.StatusOK)
|
|
io.Copy(w, io.NopCloser(bytes.NewReader(appOnce.PublicCrt)))
|
|
}
|
|
|
|
func (h *HttpServer) preview(w http.ResponseWriter, r *http.Request) {
|
|
realURL := r.URL.Query().Get("url")
|
|
if realURL == "" {
|
|
http.Error(w, "Missing 'url' parameter", http.StatusBadRequest)
|
|
return
|
|
}
|
|
realURL, _ = url.QueryUnescape(realURL)
|
|
parsedURL, err := url.Parse(realURL)
|
|
if err != nil {
|
|
http.Error(w, "Invalid URL", http.StatusBadRequest)
|
|
return
|
|
}
|
|
request, err := http.NewRequest("GET", parsedURL.String(), nil)
|
|
if err != nil {
|
|
http.Error(w, "Failed to fetch the resource", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if rangeHeader := r.Header.Get("Range"); rangeHeader != "" {
|
|
request.Header.Set("Range", rangeHeader)
|
|
}
|
|
|
|
//request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36")
|
|
//request.Header.Set("Referer", parsedURL.Scheme+"://"+parsedURL.Host+"/")
|
|
resp, err := http.DefaultClient.Do(request)
|
|
if err != nil {
|
|
http.Error(w, "Failed to fetch the resource", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
|
|
w.WriteHeader(resp.StatusCode)
|
|
|
|
if contentRange := resp.Header.Get("Content-Range"); contentRange != "" {
|
|
w.Header().Set("Content-Range", contentRange)
|
|
}
|
|
|
|
_, err = io.Copy(w, resp.Body)
|
|
if err != nil {
|
|
http.Error(w, "Failed to serve the resource", http.StatusInternalServerError)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (h *HttpServer) send(t string, data interface{}) {
|
|
jsonData, err := json.Marshal(map[string]interface{}{
|
|
"type": t,
|
|
"data": data,
|
|
})
|
|
if err != nil {
|
|
fmt.Println("Error converting map to JSON:", err)
|
|
return
|
|
}
|
|
runtime.EventsEmit(appOnce.ctx, "event", string(jsonData))
|
|
}
|
|
|
|
func (h *HttpServer) writeJson(w http.ResponseWriter, data *ResponseData) {
|
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
w.WriteHeader(200)
|
|
err := json.NewEncoder(w).Encode(data)
|
|
if err != nil {
|
|
globalLogger.Err(err)
|
|
}
|
|
}
|
|
|
|
func (h *HttpServer) error(w http.ResponseWriter, args ...interface{}) {
|
|
message := "ok"
|
|
var data interface{}
|
|
|
|
if len(args) > 0 {
|
|
message = args[0].(string)
|
|
}
|
|
if len(args) > 1 {
|
|
data = args[1]
|
|
}
|
|
h.writeJson(w, h.buildResp(0, message, data))
|
|
}
|
|
|
|
func (h *HttpServer) success(w http.ResponseWriter, args ...interface{}) {
|
|
message := "ok"
|
|
var data interface{}
|
|
|
|
if len(args) > 0 {
|
|
data = args[0]
|
|
}
|
|
|
|
if len(args) > 1 {
|
|
message = args[1].(string)
|
|
}
|
|
h.writeJson(w, h.buildResp(1, message, data))
|
|
}
|
|
|
|
func (h *HttpServer) buildResp(code int, message string, data interface{}) *ResponseData {
|
|
return &ResponseData{
|
|
Code: code,
|
|
Message: message,
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
func (h *HttpServer) openDirectoryDialog(w http.ResponseWriter, r *http.Request) {
|
|
folder, err := runtime.OpenDirectoryDialog(appOnce.ctx, runtime.OpenDialogOptions{
|
|
DefaultDirectory: "",
|
|
Title: "Select a folder",
|
|
})
|
|
if err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
h.success(w, respData{
|
|
"folder": folder,
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) openFileDialog(w http.ResponseWriter, r *http.Request) {
|
|
filePath, err := runtime.OpenFileDialog(appOnce.ctx, runtime.OpenDialogOptions{
|
|
Filters: []runtime.FileFilter{
|
|
{
|
|
DisplayName: "Videos (*.mov;*.mp4)",
|
|
Pattern: "*.mp4",
|
|
},
|
|
},
|
|
Title: "Select a file",
|
|
})
|
|
if err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
h.success(w, respData{
|
|
"file": filePath,
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) openFolder(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
FilePath string `json:"filePath"`
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&data)
|
|
if err == nil && data.FilePath == "" {
|
|
return
|
|
}
|
|
|
|
filePath := data.FilePath
|
|
var cmd *exec.Cmd
|
|
|
|
switch sysRuntime.GOOS {
|
|
case "darwin":
|
|
cmd = exec.Command("open", "-R", filePath)
|
|
case "windows":
|
|
cmd = exec.Command("explorer", "/select,", filePath)
|
|
case "linux":
|
|
cmd = exec.Command("nautilus", filePath)
|
|
if err := cmd.Start(); err != nil {
|
|
cmd = exec.Command("thunar", filePath)
|
|
if err := cmd.Start(); err != nil {
|
|
cmd = exec.Command("dolphin", filePath)
|
|
if err := cmd.Start(); err != nil {
|
|
cmd = exec.Command("pcmanfm", filePath)
|
|
if err := cmd.Start(); err != nil {
|
|
globalLogger.Err(err)
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
h.error(w, "unsupported platform")
|
|
return
|
|
}
|
|
|
|
err = cmd.Start()
|
|
if err != nil {
|
|
globalLogger.Err(err)
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) install(w http.ResponseWriter, r *http.Request) {
|
|
if appOnce.isInstall() {
|
|
h.success(w, respData{
|
|
"isPass": systemOnce.Password == "",
|
|
})
|
|
return
|
|
}
|
|
|
|
out, err := appOnce.installCert()
|
|
if err != nil {
|
|
h.error(w, err.Error()+"\n"+out, respData{
|
|
"isPass": systemOnce.Password == "",
|
|
})
|
|
return
|
|
}
|
|
|
|
h.success(w, respData{
|
|
"isPass": systemOnce.Password == "",
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) setSystemPassword(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
Password string `json:"password"`
|
|
IsCache bool `json:"isCache"`
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&data)
|
|
if err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
systemOnce.SetPassword(data.Password, data.IsCache)
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) openSystemProxy(w http.ResponseWriter, r *http.Request) {
|
|
err := appOnce.OpenSystemProxy()
|
|
if err != nil {
|
|
h.error(w, err.Error(), respData{
|
|
"value": appOnce.IsProxy,
|
|
})
|
|
return
|
|
}
|
|
h.success(w, respData{
|
|
"value": appOnce.IsProxy,
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) unsetSystemProxy(w http.ResponseWriter, r *http.Request) {
|
|
err := appOnce.UnsetSystemProxy()
|
|
if err != nil {
|
|
h.error(w, err.Error(), respData{
|
|
"value": appOnce.IsProxy,
|
|
})
|
|
return
|
|
}
|
|
h.success(w, respData{
|
|
"value": appOnce.IsProxy,
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) isProxy(w http.ResponseWriter, r *http.Request) {
|
|
h.success(w, respData{
|
|
"value": appOnce.IsProxy,
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) appInfo(w http.ResponseWriter, r *http.Request) {
|
|
h.success(w, appOnce)
|
|
}
|
|
|
|
func (h *HttpServer) getConfig(w http.ResponseWriter, r *http.Request) {
|
|
h.success(w, globalConfig)
|
|
}
|
|
|
|
func (h *HttpServer) setConfig(w http.ResponseWriter, r *http.Request) {
|
|
var data Config
|
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
globalConfig.setConfig(data)
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) setType(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
Type string `json:"type"`
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&data)
|
|
if err == nil {
|
|
if data.Type != "" {
|
|
resourceOnce.setResType(strings.Split(data.Type, ","))
|
|
} else {
|
|
resourceOnce.setResType([]string{})
|
|
}
|
|
}
|
|
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) clear(w http.ResponseWriter, r *http.Request) {
|
|
resourceOnce.clear()
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) delete(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
Sign string `json:"sign"`
|
|
}
|
|
err := json.NewDecoder(r.Body).Decode(&data)
|
|
if err == nil && data.Sign != "" {
|
|
resourceOnce.delete(data.Sign)
|
|
}
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) download(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
MediaInfo
|
|
DecodeStr string `json:"decodeStr"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
resourceOnce.download(data.MediaInfo, data.DecodeStr)
|
|
h.success(w)
|
|
}
|
|
|
|
func (h *HttpServer) wxFileDecode(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
MediaInfo
|
|
Filename string `json:"filename"`
|
|
DecodeStr string `json:"decodeStr"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
savePath, err := resourceOnce.wxFileDecode(data.MediaInfo, data.Filename, data.DecodeStr)
|
|
if err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
h.success(w, respData{
|
|
"save_path": savePath,
|
|
})
|
|
}
|
|
|
|
func (h *HttpServer) batchExport(w http.ResponseWriter, r *http.Request) {
|
|
var data struct {
|
|
Content string `json:"content"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
fileName := filepath.Join(globalConfig.SaveDirectory, "res-downloader-"+shared.GetCurrentDateTimeFormatted()+".txt")
|
|
err := os.WriteFile(fileName, []byte(data.Content), 0644)
|
|
if err != nil {
|
|
h.error(w, err.Error())
|
|
return
|
|
}
|
|
h.success(w, respData{
|
|
"file_name": fileName,
|
|
})
|
|
}
|