package realdebrid import ( "errors" "math" "strings" jsoniter "github.com/json-iterator/go" ) var json = jsoniter.ConfigCompatibleWithStandardLibrary type FileJSON struct { FileSize int `json:"filesize"` Link string `json:"link"` } type Download struct { Filename string `json:"filename"` Filesize int64 `json:"filesize"` // bytes, 0 if unknown Link string `json:"link"` // Original link Host string `json:"host"` // Host main domain Download string `json:"download"` // Generated link Streamable int `json:"streamable"` Generated string `json:"-"` // jsonDate } func (d *Download) UnmarshalJSON(data []byte) error { type Alias Download aux := &struct { Generated string `json:"generated"` *Alias }{ Alias: (*Alias)(d), } if err := json.Unmarshal(data, &aux); err != nil { return err } d.Generated = strings.Replace(aux.Generated, "Z", "+01:00", 1) return nil } type Torrent struct { ID string `json:"id"` Name string `json:"filename"` Hash string `json:"hash"` Progress int `json:"-"` Status string `json:"status"` Links []string `json:"links"` Added string `json:"-"` } func (i *Torrent) IsDone() bool { return i.Progress == 100 && len(i.Links) > 0 } func (i *Torrent) UnmarshalJSON(data []byte) error { type Alias Torrent aux := &struct { Progress float64 `json:"progress"` Added string `json:"added"` *Alias }{ Alias: (*Alias)(i), } if err := json.Unmarshal(data, &aux); err != nil { return err } i.Progress = int(math.Floor(aux.Progress)) i.Added = strings.Replace(aux.Added, "Z", "+01:00", 1) return nil } type TorrentInfo struct { ID string `json:"id"` Name string `json:"filename"` Hash string `json:"hash"` Progress int `json:"-"` Status string `json:"status"` Added string `json:"-"` Ended string `json:"-"` Bytes int64 `json:"bytes"` Links []string `json:"links"` OriginalName string `json:"original_filename"` OriginalBytes int64 `json:"original_bytes"` Files []File `json:"files"` } func (i *TorrentInfo) IsComplete() bool { selectedCount := 0 for _, file := range i.Files { if file.Selected == 1 { selectedCount++ } } if i.Progress != 100 { return false } return selectedCount == len(i.Links) && len(i.Links) > 0 } func (i *TorrentInfo) MarshalJSON() ([]byte, error) { type Alias TorrentInfo aux := &struct { Progress float64 `json:"progress"` Added string `json:"added"` Ended string `json:"ended"` *Alias }{ Alias: (*Alias)(i), Progress: float64(i.Progress), // Convert int to float64 for JSON representation Added: i.Added, } if i.Ended != "" { aux.Ended = i.Ended } return json.Marshal(aux) } func (i *TorrentInfo) UnmarshalJSON(data []byte) error { type Alias TorrentInfo aux := &struct { Progress float64 `json:"progress"` Added string `json:"added"` Ended string `json:"ended"` *Alias }{ Alias: (*Alias)(i), } if err := json.Unmarshal(data, &aux); err != nil { return err } i.Progress = int(math.Floor(aux.Progress)) i.Added = strings.Replace(aux.Added, "Z", "+01:00", 1) if aux.Ended != "" { i.Ended = strings.Replace(aux.Ended, "Z", "+01:00", 1) } return nil } type File struct { ID int `json:"id"` Path string `json:"path"` Bytes int64 `json:"bytes"` Selected int `json:"selected"` } type MagnetResponse struct { ID string `json:"id"` URI string `json:"uri"` } type ActiveTorrentCountResponse struct { DownloadingCount int `json:"nb"` MaxNumberOfTorrents int `json:"limit"` } type User struct { ID int `json:"id"` Username string `json:"username"` Email string `json:"email"` Points int `json:"points"` // Fidelity points Locale string `json:"locale"` // User language Type string `json:"type"` // "premium" or "free" Premium int `json:"premium"` // seconds left as a Premium user Expiration string `json:"expiration"` // jsonDate } // key: torrent hash type AvailabilityResponse map[string]HosterHash type HosterHash struct { // key: "rd" Variants map[string][]SelectionVariant Strings []string } // key: file id type SelectionVariant map[int]FileData type FileData struct { Filename string `json:"filename"` Filesize int `json:"filesize"` } func (h *HosterHash) UnmarshalJSON(data []byte) error { // First, try unmarshaling as map[string][]SelectionVariant var variants map[string][]SelectionVariant if err := json.Unmarshal(data, &variants); err == nil { h.Variants = variants return nil } // If that fails, try unmarshaling as []string var strings []string if err := json.Unmarshal(data, &strings); err == nil { h.Strings = strings return nil } return errors.New("availability json data did not match expected formats (map or array)") }