package monstersirenfetch import ( "context" "encoding/json" "io" "strconv" "strings" ) const ( APIPrefix = "https://monster-siren.hypergryph.com/api" ) // Net represents an abstraction over the [net] package. type Net interface { // Get makes a get request to url and returns the response body. // The caller must close the body after it finishes reading from it. Get(ctx context.Context, url string) (body io.ReadCloser, contentLength int64, err error) } // Response is a generic API response. type Response[T any] struct { Code int `json:"code"` Message string `json:"msg"` Data T `json:"data"` } // NullableString is a JSON string where its zero value behaves like null. type NullableString string func (s *NullableString) MarshalJSON() ([]byte, error) { if *s == "" { return []byte("null"), nil } return json.Marshal(string(*s)) } func (s *NullableString) UnmarshalJSON(data []byte) (err error) { var v *string err = json.Unmarshal(data, &v) if err == nil { if v != nil { *s = NullableString(*v) } else { *s = "" } } return } // StringInt is a JSON string representing an integer. type StringInt int func (i *StringInt) String() (s string) { s = strconv.Itoa(int(*i)) if len(s) <= 4 { s = strings.Repeat("0", 4-len(s)) + s } else if len(s) < 6 { s = strings.Repeat("0", 6-len(s)) + s } return } func (i *StringInt) MarshalJSON() ([]byte, error) { return json.Marshal(i.String()) } func (i *StringInt) UnmarshalJSON(data []byte) (err error) { var v string err = json.Unmarshal(data, &v) if err == nil { var n int n, err = strconv.Atoi(v) if err == nil { *i = StringInt(n) } } return } // NewEncoder returns a new encoder that writes to w, configured to match upstream API behaviour. func NewEncoder(w io.Writer) *json.Encoder { e := json.NewEncoder(w) e.SetEscapeHTML(false) return e }