/
MozApi.go
116 lines (96 loc) · 3.01 KB
/
MozApi.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
// MozApi project MozApi.go
package MozApi
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
// HMAC-SHA1 hash of your Access ID, the Expires parameter, and your Secret Key.
func getHmac_sha1(accessid string, expires string, secret string) string {
key := []byte(secret)
h := hmac.New(sha1.New, key)
h.Write([]byte(accessid))
h.Write([]byte("\n"))
h.Write([]byte(expires))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// Does a http post to the moz api url, with your accessid, secret key, url metrics option, and the urls you want to get url metrics
// sample call: GetURLMetrics(xxxx, keyxxxx, URL_METRICS_PAGE_AUTHORITY | URL_METRICS_DOMAIN_AUTHORITY, 300, []string{"google.com", "yahoo.com"})
func GetURLMetrics(accessid string, key string, cols uint64, secondsExpire time.Duration, urls []string) ([]byte, error) {
currentTime := time.Now()
//adds expiry
t := currentTime.Add(time.Second * secondsExpire).Unix()
//convert to string
expireTime := strconv.FormatInt(t, 10)
//build signed auth
signed := getHmac_sha1(accessid, expireTime, key)
var mozUrl bytes.Buffer
//build now the url
mozUrl.WriteString("https://lsapi.seomoz.com/linkscape/url-metrics/?")
mozUrl.WriteString("Cols=")
mozUrl.WriteString(strconv.FormatUint(cols, 10))
mozUrl.WriteString("&AccessID=")
mozUrl.WriteString(accessid)
mozUrl.WriteString("&Expires=")
mozUrl.WriteString(expireTime)
mozUrl.WriteString("&Signature=")
mozUrl.WriteString(url.QueryEscape(signed))
//fmt.Println(mozUrl.String())
b, err := json.Marshal(urls)
if err != nil {
return nil, err
}
//fmt.Printf("post data %v.\n", string(b))
req, err := http.NewRequest("POST", mozUrl.String(), bytes.NewBuffer(b))
if err != nil {
// handle error
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
// Since return type of moz api can be:
// {status:401, error_message:"the error"}
// or
// [{pda:82}, {pda:71}]
// so we need a handler to check if return has error, or has the needed moz data values
// if no 'error_message', then proceed to extract the moz return data using the ExtractMozData
func CheckResultError(b []byte) (bool, map[string]interface{}, error) {
if strings.Contains(string(b), "error_message") {
var data map[string]interface{}
if err := json.Unmarshal(b, &data); err != nil {
//fmt.Printf("Unmarshall err: %v.\n", err)
return true, nil, err
}
return true, data, nil
}
return false, nil, nil
}
// just convert the json string from moz api call to array of map
func ExtractMozData(b []byte) ([](map[string]interface{}), error) {
var docs [](map[string]interface{})
if err := json.Unmarshal(b, &docs); err != nil {
fmt.Printf("Unmarshall err: %v.\n", err)
return nil, err
}
return docs, nil
}