Skip to content

Commit 8b7b692

Browse files
committed
add tinify
1 parent 38a5fb4 commit 8b7b692

6 files changed

Lines changed: 359 additions & 19 deletions

File tree

.idea/workspace.xml

Lines changed: 21 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tinify/client.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package Tinify
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"io"
7+
"net/http"
8+
"strings"
9+
)
10+
11+
const API_ENDPOINT = "https://api.tinify.com"
12+
13+
type Client struct {
14+
options map[string]interface{}
15+
key string
16+
}
17+
18+
func NewClient(key string) (c *Client, err error) {
19+
c = new(Client)
20+
c.key = key
21+
return
22+
}
23+
24+
// method: http.MethodPost、http.MethodGet
25+
func (c *Client) Request(method string, url string, body interface{}) (response *http.Response, err error) {
26+
if strings.HasPrefix(url, "https") == false {
27+
url = API_ENDPOINT + url
28+
}
29+
req, err := http.NewRequest(method, url, nil)
30+
if err != nil {
31+
return
32+
}
33+
34+
switch body.(type) {
35+
case []byte:
36+
if len(body.([]byte)) > 0 {
37+
req.Body = io.NopCloser(bytes.NewReader(body.([]byte)))
38+
}
39+
case map[string]interface{}:
40+
if len(body.(map[string]interface{})) > 0 {
41+
body2, err2 := json.Marshal(body)
42+
if err2 != nil {
43+
err = err2
44+
return
45+
}
46+
req.Body = io.NopCloser(bytes.NewReader(body2))
47+
}
48+
req.Header["Content-Type"] = []string{"application/json"}
49+
}
50+
51+
req.SetBasicAuth("api", c.key)
52+
53+
response, err = http.DefaultClient.Do(req)
54+
return
55+
}

tinify/result.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package Tinify
2+
3+
import (
4+
"net/http"
5+
"os"
6+
"path/filepath"
7+
"strconv"
8+
)
9+
10+
type Result struct {
11+
data []byte
12+
*ResultMeta
13+
}
14+
15+
func NewResult(meta http.Header, data []byte) *Result {
16+
r := new(Result)
17+
r.ResultMeta = NewResultMeta(meta)
18+
r.data = data
19+
return r
20+
}
21+
22+
func (r *Result) Data() []byte {
23+
return r.data
24+
}
25+
26+
func (r *Result) ToBuffer() []byte {
27+
return r.Data()
28+
}
29+
30+
func (r *Result) ToFile(path string) error {
31+
path, err := filepath.Abs(path)
32+
if err != nil {
33+
return err
34+
}
35+
err = os.WriteFile(path, r.data, os.ModePerm)
36+
return err
37+
}
38+
39+
func (r *Result) Size() int64 {
40+
s := r.meta["Content-Length"]
41+
if len(s) == 0 {
42+
return 0
43+
}
44+
45+
size, _ := strconv.Atoi(s[0])
46+
return int64(size)
47+
}
48+
49+
func (r *Result) MediaType() string {
50+
arr := r.meta["Content-Type"]
51+
if len(arr) == 0 {
52+
return ""
53+
}
54+
return arr[0]
55+
}
56+
57+
func (r *Result) ContentType() string {
58+
return r.MediaType()
59+
}

tinify/result_meta.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package Tinify
2+
3+
import (
4+
"net/http"
5+
6+
"strconv"
7+
)
8+
9+
type ResultMeta struct {
10+
meta http.Header
11+
}
12+
13+
func NewResultMeta(meta http.Header) *ResultMeta {
14+
r := new(ResultMeta)
15+
r.meta = meta
16+
return r
17+
}
18+
19+
func (r *ResultMeta) width() int64 {
20+
w := r.meta["Image-Width"]
21+
if len(w) == 0 {
22+
return 0
23+
}
24+
width, _ := strconv.Atoi(w[0])
25+
26+
return int64(width)
27+
}
28+
29+
func (r *ResultMeta) height() int64 {
30+
h := r.meta["Image-Height"]
31+
if len(h) == 0 {
32+
return 0
33+
}
34+
35+
height, _ := strconv.Atoi(h[0])
36+
return int64(height)
37+
}
38+
39+
func (r *ResultMeta) location() string {
40+
arr := r.meta["Location"]
41+
if len(arr) == 0 {
42+
return ""
43+
}
44+
return arr[0]
45+
}

tinify/source.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package Tinify
2+
3+
import (
4+
"errors"
5+
"io"
6+
"io/ioutil"
7+
"net/http"
8+
)
9+
10+
const (
11+
ResizeMethodScale = "scale"
12+
ResizeMethodFit = "fit"
13+
ResizeMethodCover = "cover"
14+
)
15+
16+
type ResizeMethod string
17+
18+
type ResizeOption struct {
19+
Method ResizeMethod `json:"method"`
20+
Width int64 `json:"width"`
21+
Height int64 `json:"height"`
22+
}
23+
24+
type Source struct {
25+
url string
26+
commands map[string]interface{}
27+
}
28+
29+
func newSource(url string, commands map[string]interface{}) *Source {
30+
s := new(Source)
31+
s.url = url
32+
if commands != nil {
33+
s.commands = commands
34+
} else {
35+
s.commands = make(map[string]interface{})
36+
}
37+
38+
return s
39+
}
40+
41+
func FromFile(path string) (s *Source, err error) {
42+
buf, err := ioutil.ReadFile(path)
43+
if err != nil {
44+
return
45+
}
46+
47+
return FromBuffer(buf)
48+
}
49+
50+
func FromBuffer(buf []byte) (s *Source, err error) {
51+
response, err := GetClient().Request(http.MethodPost, "/shrink", buf)
52+
if err != nil {
53+
return
54+
}
55+
56+
s, err = getSourceFromResponse(response)
57+
return
58+
}
59+
60+
func FromUrl(url string) (s *Source, err error) {
61+
if len(url) == 0 {
62+
err = errors.New("url is required")
63+
return
64+
}
65+
66+
body := map[string]interface{}{
67+
"source": map[string]interface{}{
68+
"url": url,
69+
},
70+
}
71+
72+
response, err := GetClient().Request(http.MethodPost, "/shrink", body)
73+
if err != nil {
74+
return
75+
}
76+
77+
s, err = getSourceFromResponse(response)
78+
return
79+
}
80+
81+
func getSourceFromResponse(response *http.Response) (s *Source, err error) {
82+
location := response.Header["Location"]
83+
url := ""
84+
if len(location) > 0 {
85+
url = location[0]
86+
}
87+
88+
s = newSource(url, nil)
89+
return
90+
}
91+
92+
func (s *Source) ToFile(path string) error {
93+
result, err := s.toResult()
94+
if err != nil {
95+
return err
96+
}
97+
98+
return result.ToFile(path)
99+
}
100+
101+
func (s *Source) Resize(option *ResizeOption) error {
102+
if option == nil {
103+
return errors.New("option is required")
104+
}
105+
106+
s.commands["resize"] = option
107+
108+
return nil
109+
}
110+
111+
func (s *Source) toResult() (r *Result, err error) {
112+
if len(s.url) == 0 {
113+
err = errors.New("url is empty")
114+
return
115+
}
116+
117+
//body := make([]byte, 0)
118+
//if len(s.commands) > 0 {
119+
// body, err = json.Marshal(s.commands)
120+
// if err != nil {
121+
// return
122+
// }
123+
//}
124+
response, err := GetClient().Request(http.MethodGet, s.url, s.commands)
125+
if err != nil {
126+
return
127+
}
128+
129+
data, err := io.ReadAll(response.Body)
130+
if err != nil {
131+
return
132+
}
133+
134+
r = NewResult(response.Header, data)
135+
return
136+
}

0 commit comments

Comments
 (0)