Files
blog/write-go/internal/rssapi/rssapi.go
T
2026-06-01 17:57:22 +08:00

158 lines
3.5 KiB
Go

package rssapi
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"write-server/internal/config"
)
type Feed struct {
URL string `json:"url"`
FeedTitle string `json:"feedTitle"`
SiteURL string `json:"siteUrl,omitempty"`
Error string `json:"error,omitempty"`
}
type FeedHealth struct {
URL string `json:"url"`
Status int `json:"status"`
OK bool `json:"ok"`
Latency int `json:"latency,omitempty"`
Error string `json:"error,omitempty"`
}
type Link struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description,omitempty"`
Image string `json:"image,omitempty"`
Hidden bool `json:"hidden,omitempty"`
RSS string `json:"rss,omitempty"`
AddedAt string `json:"addedAt,omitempty"`
}
func rssFetch(path string, method string, body interface{}) (map[string]interface{}, error) {
u := config.RSS_API_BASE + path
var req *http.Request
var err error
if body != nil && (method == "POST" || method == "PUT") {
data, _ := json.Marshal(body)
req, err = http.NewRequest(method, u, bytes.NewReader(data))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
} else {
req, err = http.NewRequest(method, u, nil)
if err != nil {
return nil, err
}
}
if config.RSS_API_TOKEN != "" {
q := req.URL.Query()
q.Set("token", config.RSS_API_TOKEN)
req.URL.RawQuery = q.Encode()
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result map[string]interface{}
if err := json.Unmarshal(data, &result); err != nil {
return nil, fmt.Errorf("RSS API error: %d", resp.StatusCode)
}
return result, nil
}
func GetFeeds() ([]Feed, error) {
result, err := rssFetch("/api/rss/feeds", "GET", nil)
if err != nil {
return nil, err
}
var feeds []Feed
if raw, ok := result["feeds"]; ok {
data, _ := json.Marshal(raw)
json.Unmarshal(data, &feeds)
}
return feeds, nil
}
func AddFeed(feedURL, feedTitle string) error {
_, err := rssFetch("/api/rss/feeds", "POST", map[string]string{
"url": feedURL,
"feedTitle": feedTitle,
})
return err
}
func DeleteFeed(feedURL string) error {
_, err := rssFetch("/api/rss/feeds?url="+url.QueryEscape(feedURL), "DELETE", nil)
return err
}
func UpdateFeed(oldURL, newURL, feedTitle string) error {
_, err := rssFetch("/api/rss/feeds", "PUT", map[string]string{
"oldUrl": oldURL,
"url": newURL,
"feedTitle": feedTitle,
})
return err
}
func GetLinks(all bool) ([]Link, error) {
path := "/api/rss/links"
if all {
path += "?all=1"
}
result, err := rssFetch(path, "GET", nil)
if err != nil {
return nil, err
}
var links []Link
if raw, ok := result["links"]; ok {
data, _ := json.Marshal(raw)
json.Unmarshal(data, &links)
}
return links, nil
}
func AddLink(link Link) error {
_, err := rssFetch("/api/rss/links", "POST", link)
return err
}
func UpdateLink(oldURL string, data map[string]interface{}) error {
body := map[string]interface{}{"oldUrl": oldURL}
for k, v := range data {
if k != "oldUrl" {
body[k] = v
}
}
_, err := rssFetch("/api/rss/links", "PUT", body)
return err
}
func DeleteLink(linkURL string) error {
_, err := rssFetch("/api/rss/links?url="+url.QueryEscape(linkURL), "DELETE", nil)
return err
}
func CheckLinkHealth(targetURL string) (map[string]interface{}, error) {
return rssFetch("/api/rss/links?health="+url.QueryEscape(targetURL), "GET", nil)
}