package artalk import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/url" "write-server/internal/config" ) var authToken string func SetAuthToken(token string) { authToken = token } func GetAuthToken() string { return authToken } type ArtalkPage struct { ID int `json:"id"` AdminOnly bool `json:"admin_only"` Key string `json:"key"` Title string `json:"title"` URL string `json:"url"` View int `json:"view"` CommentCount int `json:"comment_count"` Date string `json:"date"` } type ArtalkComment struct { ID int `json:"id"` Content string `json:"content"` Nick string `json:"nick"` Email string `json:"email"` PageKey string `json:"page_key"` IsCollapsed bool `json:"is_collapsed"` IsPending bool `json:"is_pending"` IsPinned bool `json:"is_pinned"` VoteUp int `json:"vote_up"` VoteDown int `json:"vote_down"` RID int `json:"rid"` Date string `json:"date"` } func Login(email, password string) (map[string]interface{}, error) { u := config.ARTALK_SERVER + "/api/v2/auth/email/login" body, _ := json.Marshal(map[string]string{"email": email, "password": password}) resp, err := http.Post(u, "application/json", bytes.NewReader(body)) if err != nil { return nil, err } defer resp.Body.Close() data, _ := io.ReadAll(resp.Body) var result map[string]interface{} json.Unmarshal(data, &result) if token, ok := result["token"].(string); ok { authToken = token } return result, nil } func artalkFetch(path string) (map[string]interface{}, error) { u := config.ARTALK_SERVER + path req, _ := http.NewRequest("GET", u, nil) req.Header.Set("Content-Type", "application/json") if authToken != "" { req.Header.Set("Authorization", "Bearer "+authToken) } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() data, _ := io.ReadAll(resp.Body) var result map[string]interface{} json.Unmarshal(data, &result) return result, nil } func GetPages(offset, limit int, pageType string) ([]ArtalkPage, int, error) { params := url.Values{} params.Set("site_name", config.ARTALK_SITE) params.Set("offset", fmt.Sprintf("%d", offset)) params.Set("limit", fmt.Sprintf("%d", limit)) params.Set("type", pageType) result, err := artalkFetch("/api/v2/pages?" + params.Encode()) if err != nil { return nil, 0, err } var pages []ArtalkPage if raw, ok := result["pages"]; ok { d, _ := json.Marshal(raw) json.Unmarshal(d, &pages) } else if raw, ok := result["data"]; ok { d, _ := json.Marshal(raw) json.Unmarshal(d, &pages) } total := 0 if v, ok := result["count"]; ok { fmt.Sscanf(fmt.Sprintf("%v", v), "%d", &total) } else if v, ok := result["total"]; ok { fmt.Sscanf(fmt.Sprintf("%v", v), "%d", &total) } return pages, total, nil } func GetComments(pageKey string, offset, limit int) ([]ArtalkComment, int, error) { params := url.Values{} params.Set("site_name", config.ARTALK_SITE) params.Set("page_key", pageKey) params.Set("offset", fmt.Sprintf("%d", offset)) params.Set("limit", fmt.Sprintf("%d", limit)) params.Set("flat_mode", "true") params.Set("sort_by", "date_desc") result, err := artalkFetch("/api/v2/comments?" + params.Encode()) if err != nil { return nil, 0, err } var comments []ArtalkComment if raw, ok := result["comments"]; ok { d, _ := json.Marshal(raw) json.Unmarshal(d, &comments) } else if raw, ok := result["data"]; ok { d, _ := json.Marshal(raw) json.Unmarshal(d, &comments) } total := 0 if v, ok := result["count"]; ok { fmt.Sscanf(fmt.Sprintf("%v", v), "%d", &total) } else if v, ok := result["total"]; ok { fmt.Sscanf(fmt.Sprintf("%v", v), "%d", &total) } return comments, total, nil } func UpdateComment(id int, data map[string]interface{}) error { u := config.ARTALK_SERVER + fmt.Sprintf("/api/v2/comments/%d", id) data["site_name"] = config.ARTALK_SITE body, _ := json.Marshal(data) req, _ := http.NewRequest("PUT", u, bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") if authToken != "" { req.Header.Set("Authorization", "Bearer "+authToken) } resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() return nil } func CreateComment(data map[string]interface{}) (map[string]interface{}, error) { u := config.ARTALK_SERVER + "/api/v2/comments" data["site_name"] = config.ARTALK_SITE body, _ := json.Marshal(data) req, _ := http.NewRequest("POST", u, bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") if authToken != "" { req.Header.Set("Authorization", "Bearer "+authToken) } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() respData, _ := io.ReadAll(resp.Body) var result map[string]interface{} json.Unmarshal(respData, &result) return result, nil } func DeleteComment(id int) error { u := config.ARTALK_SERVER + fmt.Sprintf("/api/v2/comments/%d", id) req, _ := http.NewRequest("DELETE", u, bytes.NewReader([]byte(`{"site_name":"` + config.ARTALK_SITE + `"}`))) req.Header.Set("Content-Type", "application/json") if authToken != "" { req.Header.Set("Authorization", "Bearer "+authToken) } _, err := http.DefaultClient.Do(req) return err }