1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
package main
import (
"encoding/json"
"fmt"
"image"
_ "image/png"
_ "image/jpeg"
"io"
"log"
"math/rand"
"net/http"
"os"
"strconv"
"github.com/mattn/go-sixel"
"github.com/urfave/cli/v2"
)
const (
hostname = "https://xkcd.com"
target = "info.0.json"
)
type Xkcd struct {
Month string
Num int
Link string
Year string
News string
Safe_title string
Transcript string
Alt string
Img string
Title string
Day string
}
func main() {
app := &cli.App{
Name: "siXKCD",
Usage: "Sixel viewer/fetcher for XKCD Comics",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "id",
Aliases: []string{"i"},
Usage: "Specify which comic `ID` to fetch.\nA value of 0 will fetch the latest comic (default: random)",
},
},
Action: func(ctx *cli.Context) error {
comic := fetchComic("latest")
switch ctx.String("id") {
case "0":
// Latest is already fetched
break
case "":
// Random
rand := rand.Intn(comic.Num+1)
comic = fetchComic(strconv.Itoa(rand))
default:
comic = fetchComic(ctx.String("id"))
}
var img image.Image = fetchImg(comic.Img)
fmt.Println("Title: ", comic.Title)
encoder := sixel.NewEncoder(os.Stdout)
_ = encoder.Encode(img)
if comic.Alt != "" {
fmt.Println(comic.Alt)
}
return nil
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
func fetchComic(id string) Xkcd {
var res *http.Response
var err error
if id == "latest" {
res, err = http.Get(hostname+"/"+target)
} else {
res, err = http.Get(hostname+"/"+id+"/"+target)
}
if err != nil {
log.Fatal(err)
}
content, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
today := Xkcd{}
err = json.Unmarshal(content, &today)
if err != nil {
log.Fatal(err)
}
return today
}
func fetchImg(url string) image.Image {
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
img, _, err := image.Decode(res.Body)
if err != nil {
log.Fatal(err)
}
res.Body.Close()
return img
}
|