ncore-stats/main.go
2024-10-09 01:11:28 +02:00

180 lines
3.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/PuerkitoBio/goquery"
"github.com/joho/godotenv"
)
type ProfileData struct {
Owner string `json:"owner"`
Timestamp time.Time `json:"timestamp"`
Rank string `json:"rank"`
Upload string `json:"upload"`
CurrentUpload string `json:"current_upload"`
CurrentDownload string `json:"current_download"`
Points string `json:"points"`
}
var (
profiles = map[string]string{}
jsonFile = "data.json"
nick string
pass string
client *http.Client
)
func init() {
if err := godotenv.Load(); err != nil {
log.Fatal("Error loading .env file")
}
nick = os.Getenv("NICK")
pass = os.Getenv("PASS")
for i := 1; i <= 10; i++ {
profileKey := fmt.Sprintf("PROFILE_%d", i)
if profileURL := os.Getenv(profileKey); profileURL != "" {
profiles[profileURL] = profileURL
}
}
client = &http.Client{}
}
func fetchProfile(url string) (*ProfileData, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Cookie", fmt.Sprintf("nick=%s; pass=%s", nick, pass))
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to fetch profile: %s", url)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, err
}
owner := strings.TrimSpace(doc.Find(".fobox_fej").Text())
owner = strings.Replace(owner, " profilja", "", 1)
profile := &ProfileData{
Owner: owner,
Timestamp: time.Now(),
}
doc.Find(".userbox_tartalom_mini .profil_jobb_elso2").Each(func(i int, s *goquery.Selection) {
label := s.Text()
value := s.Next().Text()
switch label {
case "Helyezés:":
profile.Rank = value
case "Feltöltés:":
profile.Upload = value
case "Aktuális feltöltés:":
profile.CurrentUpload = value
case "Aktuális letöltés:":
profile.CurrentDownload = value
case "Pontok száma:":
profile.Points = value
}
})
return profile, nil
}
func readExistingProfiles() ([]ProfileData, error) {
if _, err := os.Stat(jsonFile); os.IsNotExist(err) {
return []ProfileData{}, nil
}
file, err := os.Open(jsonFile)
if err != nil {
return nil, err
}
defer file.Close()
var profiles []ProfileData
byteValue, _ := io.ReadAll(file)
err = json.Unmarshal(byteValue, &profiles)
return profiles, err
}
func logToJSON(profile *ProfileData) error {
existingProfiles, err := readExistingProfiles()
if err != nil {
return err
}
existingProfiles = append(existingProfiles, *profile)
file, err := os.OpenFile(jsonFile, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
enc := json.NewEncoder(file)
enc.SetIndent("", " ")
return enc.Encode(existingProfiles)
}
func dataHandler(w http.ResponseWriter, r *http.Request) {
profiles, err := readExistingProfiles()
if err != nil {
http.Error(w, "Could not read data", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(profiles)
}
func serveHTML(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
}
func main() {
ticker := time.NewTicker(24 * time.Hour)
defer ticker.Stop()
go func() {
for {
for _, url := range profiles {
profile, err := fetchProfile(url)
if err != nil {
log.Println(err)
continue
}
if err := logToJSON(profile); err != nil {
log.Println(err)
}
}
<-ticker.C
}
}()
http.HandleFunc("/data", dataHandler)
http.HandleFunc("/", serveHTML)
log.Fatal(http.ListenAndServe(":3000", nil))
}