-
Notifications
You must be signed in to change notification settings - Fork 0
/
comic.go
135 lines (113 loc) · 2.65 KB
/
comic.go
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
124
125
126
127
128
129
130
131
132
133
134
135
// xkcd: downloads json of a comic given its number and stores it under index/
// if it cannot find it under index/
package xkcd
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
)
type Comic struct {
Year, Month, Day string
Num uint
Link string
News string
SafeTitle string `json:"safe_title"`
Transcript string
Alt string
Img string
Title string
}
const (
baseUrl = "https://xkcd.com/"
)
func GetComic(comicNumber string) (*Comic, error) {
comicNumberInt, err := strconv.Atoi(comicNumber)
if err != nil {
fmt.Fprintf(os.Stderr, "comic number must be an integer")
os.Exit(1)
}
filePath, err := prepareFilePath(uint(comicNumberInt))
if err != nil {
return nil, err
}
var comic Comic
if fileExists(filePath) {
bytes, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}
err = json.Unmarshal(bytes, &comic)
if err != nil {
return nil, err
}
} else {
comicJson, err := requestComicJson(comicNumber)
if err != nil {
return nil, err
}
if err = json.Unmarshal(comicJson, &comic); err != nil {
return nil, err
}
filePath, err = prepareFilePath(comic.Num)
if err != nil {
return nil, err
}
if !fileExists(filePath) {
// in case of requesting 0th(current comic), the json file may or may not exist on disk
if err = writeComicJson(filePath, comicJson); err != nil {
return nil, err
}
}
}
return &comic, nil
}
func fileExists(filePath string) bool {
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return false
}
return true
}
func prepareUrl(comicNumber string) string {
if comicNumber == "0" {
return baseUrl + "/info.0.json"
}
return baseUrl + comicNumber + "/info.0.json"
}
func requestComicJson(comicNumber string) ([]byte, error) {
response, err := http.Get(prepareUrl(comicNumber))
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("fetching comic %s failed", comicNumber)
}
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
return bodyBytes, nil
}
func prepareFilePath(comicNumber uint) (string, error) {
currentDirectory, err := os.Getwd()
if err != nil {
return "", err
}
fileName := strconv.Itoa(int(comicNumber)) + ".json"
return currentDirectory + "/index/" + fileName, nil
}
func writeComicJson(filePath string, comicJson []byte) error {
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0660)
if err != nil {
return err
}
_, err = file.Write(comicJson)
if err != nil {
file.Close()
return err
}
return nil
}