manul sync backend works now
This commit is contained in:
139
utils/logger.go
139
utils/logger.go
@ -4,79 +4,40 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
)
|
||||
|
||||
// multiLogger fans every log call out to multiple logger.Logger targets with timestamps.
|
||||
type multiLogger struct {
|
||||
var (
|
||||
baseTargets []logger.Logger
|
||||
once sync.Once
|
||||
initErr error
|
||||
)
|
||||
|
||||
// InstancedLogger prefixes each message with its instance-specific prefix and a timestamp,
|
||||
// while writing to shared log outputs.
|
||||
type InstancedLogger struct {
|
||||
prefix string
|
||||
targets []logger.Logger
|
||||
}
|
||||
|
||||
// timestamped prefixes each message with a timestamp.
|
||||
func timestamped(message string) string {
|
||||
return time.Now().Format("2006-01-02 15:04:05") + " " + message
|
||||
// NewLogger returns a logger instance that writes to the shared logs
|
||||
//
|
||||
// but prefixes every message with [prefix].
|
||||
func NewLogger(prefix string) (*InstancedLogger, error) {
|
||||
once.Do(func() {
|
||||
baseTargets, initErr = createBaseTargets()
|
||||
})
|
||||
if initErr != nil {
|
||||
return nil, initErr
|
||||
}
|
||||
return &InstancedLogger{prefix: prefix, targets: baseTargets}, nil
|
||||
}
|
||||
|
||||
func (m *multiLogger) Print(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Print(msg)
|
||||
}
|
||||
}
|
||||
func (m *multiLogger) Trace(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Trace(msg)
|
||||
}
|
||||
}
|
||||
func (m *multiLogger) Debug(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Debug(msg)
|
||||
}
|
||||
}
|
||||
func (m *multiLogger) Info(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Info(msg)
|
||||
}
|
||||
}
|
||||
func (m *multiLogger) Warning(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Warning(msg)
|
||||
}
|
||||
}
|
||||
func (m *multiLogger) Error(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Error(msg)
|
||||
}
|
||||
}
|
||||
func (m *multiLogger) Fatal(message string) {
|
||||
msg := timestamped(message)
|
||||
for _, l := range m.targets {
|
||||
l.Fatal(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// NewRuntimeFileLogger returns a logger that writes all output both to
|
||||
//
|
||||
// $XDG_CONFIG_HOME/FanslySync/logs/runtime_latest.log (or OS equivalent)
|
||||
//
|
||||
// and to a timestamped file
|
||||
//
|
||||
// $XDG_CONFIG_HOME/FanslySync/logs/runtime_YYYY-MM-DD_HH-MM-SS.log (or OS equivalent)
|
||||
//
|
||||
// It also deletes any timestamped logs older than 14 days.
|
||||
//
|
||||
// The returned logger implements github.com/wailsapp/wails/v2/pkg/logger.Logger
|
||||
// and will be used by Wails for all Go-side logging.
|
||||
func NewRuntimeFileLogger() (logger.Logger, error) {
|
||||
// Make sure the log directory exists
|
||||
// We use $XDG_CONFIG_HOME/FanslySync/logs/runtime_latest.log or OS equivalent for $XDG_CONFIG_HOME
|
||||
// createBaseTargets initializes the shared log file and console loggers once.
|
||||
func createBaseTargets() ([]logger.Logger, error) {
|
||||
cfgDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot determine user config dir: %w", err)
|
||||
@ -86,8 +47,7 @@ func NewRuntimeFileLogger() (logger.Logger, error) {
|
||||
return nil, fmt.Errorf("cannot create log directory: %w", err)
|
||||
}
|
||||
|
||||
// Prune old logs
|
||||
// We keep logs for 14 days, so delete any logs older than that
|
||||
// Prune logs older than 14 days
|
||||
cutoff := time.Now().Add(-14 * 24 * time.Hour)
|
||||
entries, _ := os.ReadDir(logDir)
|
||||
for _, e := range entries {
|
||||
@ -103,20 +63,53 @@ func NewRuntimeFileLogger() (logger.Logger, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old runtime_latest.log if it exists
|
||||
runtimePath := filepath.Join(logDir, "runtime_latest.log")
|
||||
if _, err := os.Stat(runtimePath); err == nil {
|
||||
_ = os.Remove(runtimePath)
|
||||
}
|
||||
|
||||
// Prepare file paths
|
||||
ts := time.Now().Format("2006-01-02_15-04-05")
|
||||
tsPath := filepath.Join(logDir, fmt.Sprintf("runtime_%s.log", ts))
|
||||
latestPath := filepath.Join(logDir, "runtime_latest.log")
|
||||
|
||||
// Create loggers to attach to the multiLogger
|
||||
// Create loggers
|
||||
tsLogger := logger.NewFileLogger(tsPath)
|
||||
latestLogger := logger.NewFileLogger(latestPath)
|
||||
termLogger := logger.NewDefaultLogger()
|
||||
|
||||
// Spread into a multiLogger
|
||||
// This will fan out all log messages to all three loggers
|
||||
multi := &multiLogger{
|
||||
targets: []logger.Logger{tsLogger, latestLogger, termLogger},
|
||||
}
|
||||
|
||||
return multi, nil
|
||||
return []logger.Logger{tsLogger, latestLogger, termLogger}, nil
|
||||
}
|
||||
|
||||
// log dispatches a timestamped, prefixed message to all shared targets.
|
||||
func (l *InstancedLogger) log(level, message string) {
|
||||
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
||||
fullMsg := fmt.Sprintf("%s [%s] %s", timestamp, l.prefix, message)
|
||||
for _, t := range l.targets {
|
||||
switch level {
|
||||
case "Print":
|
||||
t.Print(fullMsg)
|
||||
case "Trace":
|
||||
t.Trace(fullMsg)
|
||||
case "Debug":
|
||||
t.Debug(fullMsg)
|
||||
case "Info":
|
||||
t.Info(fullMsg)
|
||||
case "Warning":
|
||||
t.Warning(fullMsg)
|
||||
case "Error":
|
||||
t.Error(fullMsg)
|
||||
case "Fatal":
|
||||
t.Fatal(fullMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *InstancedLogger) Print(message string) { l.log("Print", message) }
|
||||
func (l *InstancedLogger) Trace(message string) { l.log("Trace", message) }
|
||||
func (l *InstancedLogger) Debug(message string) { l.log("Debug", message) }
|
||||
func (l *InstancedLogger) Info(message string) { l.log("Info", message) }
|
||||
func (l *InstancedLogger) Warning(message string) { l.log("Warning", message) }
|
||||
func (l *InstancedLogger) Error(message string) { l.log("Error", message) }
|
||||
func (l *InstancedLogger) Fatal(message string) { l.log("Fatal", message) }
|
||||
|
@ -1,7 +1,15 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"FanslySync/structs"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
@ -54,3 +62,76 @@ func ShowMessageBox(ctx context.Context, title, message string, opts ...MessageB
|
||||
// Show the message box
|
||||
runtime.MessageDialog(ctx, options)
|
||||
}
|
||||
|
||||
func UploadPaste(payload []byte) (string, error) {
|
||||
// Create HTTP client
|
||||
client := &http.Client{}
|
||||
|
||||
// Max request duration is 30s
|
||||
client.Timeout = 30 * time.Second
|
||||
|
||||
// Create request
|
||||
var payloadStruct structs.PastePayload
|
||||
payloadStruct.Content = string(payload)
|
||||
|
||||
// Marshal the payload to JSON
|
||||
payloadJSON, err := json.Marshal(payloadStruct)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create request (POST to https://paste.hep.gg/api/)
|
||||
req, err := http.NewRequest("POST", "https://paste.hep.gg/api/", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Set headers
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", "FanslySync/3.0 sticks@teamhydra.dev")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("Accept-Encoding", "gzip")
|
||||
|
||||
// Set the body
|
||||
req.Body = io.NopCloser(bytes.NewBuffer(payloadJSON))
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check for non-200 status code
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Read the response body into our struct
|
||||
var pasteResponse structs.PastePutResponse
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Unmarshal the response into our struct
|
||||
err = json.Unmarshal(data, &pasteResponse)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check for error in response
|
||||
if pasteResponse.Error != "" {
|
||||
return "", fmt.Errorf("error from paste server: %s", pasteResponse.Error)
|
||||
}
|
||||
|
||||
// Return the paste ID
|
||||
return fmt.Sprintf("https://paste.hep.gg/api/%s/raw", pasteResponse.Payload.Id), nil
|
||||
}
|
||||
|
||||
// percentage calculates the percentage of curr out of total.
|
||||
func Percentage(curr, total int) float64 {
|
||||
if total == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(curr) / float64(total) * 100
|
||||
}
|
||||
|
Reference in New Issue
Block a user