summaryrefslogtreecommitdiff
path: root/sixkcd.go
blob: efb65a7b1d2763dee5b9a8d2ea769c36c97dfe3d (plain)
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
}