This commit is contained in:
2025-04-20 00:32:41 +10:00
commit 9a098b205a
26 changed files with 1839 additions and 0 deletions

15
utils/clean.go Normal file
View File

@ -0,0 +1,15 @@
package utils
import (
"regexp"
"strings"
)
func CleanDirName(input string) string {
re := regexp.MustCompile(`[<>:"/\\|?*\x00-\x1F]`)
cleaned := re.ReplaceAllString(input, "_")
cleaned = strings.TrimSpace(cleaned)
return cleaned
}

117
utils/epub.go Normal file
View File

@ -0,0 +1,117 @@
package utils
import (
"archive/zip"
"bilinovel-downloader/template"
"io"
"os"
"path/filepath"
)
func CreateEpub(path string) error {
savePath := path + ".epub"
zipFile, err := os.Create(savePath)
if err != nil {
return err
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
err = addStringToZip(zipWriter, "mimetype", "application/epub+zip", zip.Store)
if err != nil {
return err
}
err = addDirContentToZip(zipWriter, path, zip.Deflate)
if err != nil {
return err
}
err = addStringToZip(zipWriter, "OEBPS/Styles/style.css", template.StyleCSS, zip.Deflate)
if err != nil {
return err
}
return nil
}
// func addFileToZip(zipWriter *zip.Writer, filename string, relPath string, method uint16) error {
// file, err := os.Open(filename)
// if err != nil {
// return err
// }
// defer file.Close()
// info, err := file.Stat()
// if err != nil {
// return err
// }
// header, err := zip.FileInfoHeader(info)
// if err != nil {
// return err
// }
// header.Name = relPath
// header.Method = method
// writer, err := zipWriter.CreateHeader(header)
// if err != nil {
// return err
// }
// _, err = io.Copy(writer, file)
// return err
// }
func addStringToZip(zipWriter *zip.Writer, relPath, content string, method uint16) error {
header := &zip.FileHeader{
Name: relPath,
Method: method,
}
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
_, err = writer.Write([]byte(content))
return err
}
func addDirContentToZip(zipWriter *zip.Writer, dirPath string, method uint16) error {
return filepath.Walk(dirPath, func(filePath string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
relPath, err := filepath.Rel(dirPath, filePath)
if err != nil {
return err
}
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = relPath
header.Method = method
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(writer, file)
return err
})
}

56
utils/request.go Normal file
View File

@ -0,0 +1,56 @@
package utils
import (
"context"
"net"
"net/http"
"time"
"github.com/go-resty/resty/v2"
)
var client *resty.Client
func init() {
client = resty.New()
client.SetTransport(&http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
if addr == "www.bilinovel.com:443" {
addr = "64.140.161.52:443"
}
return (&net.Dialer{
Timeout: 10 * time.Second,
}).DialContext(ctx, network, addr)
},
TLSHandshakeTimeout: 10 * time.Second,
})
client.SetRetryCount(10).
SetRetryWaitTime(3 * time.Second).
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
if resp.StatusCode() == http.StatusTooManyRequests {
if retryAfter := resp.Header().Get("Retry-After"); retryAfter != "" {
if seconds, err := time.ParseDuration(retryAfter + "s"); err == nil {
return seconds, nil
}
if t, err := http.ParseTime(retryAfter); err == nil {
return time.Until(t), nil
}
}
return 3 * time.Second, nil
}
return 0, nil
}).
AddRetryCondition(func(r *resty.Response, err error) bool {
return err != nil || r.StatusCode() == http.StatusTooManyRequests
})
}
func Request() *resty.Request {
return client.R().SetLogger(disableLogger{}).SetHeader("Accept-Charset", "utf-8").SetHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0")
}
type disableLogger struct{}
func (d disableLogger) Errorf(string, ...interface{}) {}
func (d disableLogger) Warnf(string, ...interface{}) {}
func (d disableLogger) Debugf(string, ...interface{}) {}

15
utils/unique.go Normal file
View File

@ -0,0 +1,15 @@
package utils
func Unique[T comparable](slice []T) []T {
seen := make(map[T]struct{})
var result []T
for _, v := range slice {
if _, ok := seen[v]; !ok {
seen[v] = struct{}{}
result = append(result, v)
}
}
return result
}