Skip to content

Commit f18969b

Browse files
committed
Initial PoC
1 parent 537da74 commit f18969b

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

cmd/unsavory/main.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
8+
pb "github.com/citizen428/unsavory/internal/pinboard"
9+
)
10+
11+
var token = flag.String("token", "", "Pinboard API token")
12+
13+
func main() {
14+
flag.Parse()
15+
if *token == "" {
16+
fmt.Fprintf(os.Stderr, "missing required API token\n")
17+
os.Exit(1)
18+
}
19+
20+
client := pb.NewClient(*token)
21+
urls := client.GetAllURLs()
22+
results := make(chan pb.CheckResponse)
23+
fmt.Printf("Retrieved %d URLS\n", len(urls))
24+
25+
for _, url := range urls {
26+
go client.CheckURL(url, results)
27+
}
28+
29+
var result pb.CheckResponse
30+
for range urls {
31+
result = <-results
32+
if result.StatusCode == 404 {
33+
fmt.Printf("Deleting %s\n", result.URL)
34+
client.DeleteURL(result.URL)
35+
}
36+
}
37+
}

internal/pinboard/pinboard.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package pinboard
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"os"
8+
"time"
9+
)
10+
11+
type pinboard struct {
12+
baseURL string
13+
userAgent string
14+
token string
15+
16+
client *http.Client
17+
}
18+
19+
type CheckResponse struct {
20+
URL string
21+
Status string
22+
StatusCode int
23+
}
24+
25+
func NewClient(token string) pinboard {
26+
client := &http.Client{
27+
Timeout: time.Second * 10,
28+
}
29+
30+
return pinboard{
31+
baseURL: "https://api.pinboard.in/v1/",
32+
userAgent: "UnsavoryNG",
33+
token: token,
34+
client: client}
35+
}
36+
37+
func (pb pinboard) GetAllURLs() []string {
38+
var posts []struct {
39+
URL string `json:"href"`
40+
}
41+
42+
resp, err := pb.request("posts/all", "")
43+
if err != nil {
44+
fmt.Println("Could not retrieve URLs!\nPlease check your API token.")
45+
os.Exit(1)
46+
}
47+
defer resp.Body.Close()
48+
49+
json.NewDecoder(resp.Body).Decode(&posts)
50+
51+
urls := make([]string, len(posts))
52+
53+
for i, post := range posts {
54+
urls[i] = post.URL
55+
}
56+
return urls
57+
}
58+
59+
func (pb pinboard) CheckURL(url string, results chan<- CheckResponse) {
60+
resp, err := pb.client.Head(url)
61+
if err != nil {
62+
results <- CheckResponse{url, err.Error(), 0}
63+
return
64+
}
65+
results <- CheckResponse{url, resp.Status, resp.StatusCode}
66+
}
67+
68+
func (pb pinboard) DeleteURL(url string) *http.Response {
69+
resp, err := pb.request("posts/delete", fmt.Sprintf("&url=%s", url))
70+
if err != nil {
71+
panic("Could not delete post")
72+
}
73+
return resp
74+
}
75+
76+
func (pb pinboard) request(path string, query string) (*http.Response, error) {
77+
url := fmt.Sprintf("%s%s?auth_token=%s&format=json%s", pb.baseURL, path, pb.token, query)
78+
req, err := http.NewRequest("GET", url, nil)
79+
if err != nil {
80+
panic("Invalid request")
81+
}
82+
return pb.client.Do(req)
83+
}

0 commit comments

Comments
 (0)