Browse Source

v0.0.1

Signed-off-by: Adrien Kara <adrien@iglou.eu>
tags/v0.0.1
Adrien Kara 7 months ago
parent
commit
fc24ba0c58
Signed by: adrien GPG Key ID: 605B69551C56DB62
  1. 3
      go.mod
  2. 197
      yapla.go
  3. 84
      yapla_test.go

3
go.mod

@ -0,0 +1,3 @@
module git.iglou.eu/Production/go-yapla
go 1.16

197
yapla.go

@ -0,0 +1,197 @@
// Copyright 2021 Iglou.eu
// license that can be found in the LICENSE file
package yapla
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
)
type Api struct {
key string
token token
Config Config
}
type Config struct {
URL string
Timeout time.Duration
}
type token struct {
Key string
Expire time.Time
}
type Reply struct {
Result bool `json:"result"`
Data map[string]interface{} `json:"data"`
}
func (api *Api) LoginMember(login, password string) (Reply, error) {
return api.login("/member/login", login, password)
}
func (api *Api) LoginContact(login, password string) (Reply, error) {
return api.login("/contact/login", login, password)
}
func (api *Api) login(path, login, password string) (Reply, error) {
var rep Reply
if err := api.renewToken(); err != nil {
return rep, err
}
rep, err := requestPost(
"/authentication",
api.token.Key,
map[string]string{"login": login, "password": password},
api.Config,
)
if err != nil {
return rep, err
}
return rep, nil
}
func (api *Api) renewToken() error {
if api.token.Expire.After(time.Now().Add(time.Minute * 2)) {
return nil
}
rep, err := requestPost(
"/authentication",
api.token.Key,
map[string]string{"api_key": api.key},
api.Config,
)
if err != nil {
return err
}
if rep.Data["session_token"] == nil || rep.Data["expire_date"] == nil {
return fmt.Errorf("session token or expire date is missing:\n%v", rep)
}
api.token.Key = rep.Data["session_token"].(string)
api.token.Expire, err = expireToTime(rep.Data["expire_date"].(string))
if err != nil {
return err
}
return nil
}
func NewSession(apiKey string, config ...Config) (*Api, error) {
api := &Api{
key: apiKey,
token: token{
Key: "",
Expire: time.Now(),
},
Config: Config{
URL: "https://s1.yapla.com/api/2",
Timeout: time.Second * 10,
},
}
if len(config) > 0 {
api.Config = config[0]
}
err := api.renewToken()
return api, err
}
func expireToTime(e string) (time.Time, error) {
e = strings.TrimSpace(e)
if t, err := time.Parse(time.RFC3339, e); err == nil {
return t, nil
}
var s []string
if strings.ContainsRune(e, 'T') {
s = strings.Split(e, "T")
} else {
s = strings.Split(e, " ")
}
if len(s) != 2 {
return time.Time{}, fmt.Errorf("json `expire_date` time format unexpected `%s`", e)
}
e = fmt.Sprintf("%sT%sZ", s[0], s[1])
return time.Parse(time.RFC3339, e)
}
func requestPost(path, token string, content map[string]string, config Config) (Reply, error) {
var rep Reply
body, err := json.Marshal(content)
if err != nil {
return rep, fmt.Errorf("%s:\n%s", err, body)
}
res, err := request(
http.MethodPost,
fmt.Sprintf("%s%s", config.URL, path),
token,
body,
config.Timeout,
)
if err != nil {
return rep, err
}
if err := json.Unmarshal(res, &rep); err != nil {
return rep, fmt.Errorf("%s:\n%s", err, res)
}
return rep, nil
}
func request(method, url, token string, body []byte, tOut time.Duration) ([]byte, error) {
client := &http.Client{
Timeout: tOut,
}
req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
if err != nil {
return nil, err
}
if token != "" {
req.Header.Set("token", token)
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
res, err := client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != 200 {
return nil, fmt.Errorf("POST %s: %s", url, res.Status)
}
p, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
return p, nil
}

84
yapla_test.go

@ -0,0 +1,84 @@
// Copyright 2021 Iglou.eu
// license that can be found in the LICENSE file
package yapla
import (
"fmt"
"testing"
)
var api *Api
func tError(r bool, s string, t *testing.T) {
if r {
t.Errorf("%s", s)
t.Fail()
}
}
func TestExpireToTime(t *testing.T) {
ts := ""
ti, er := expireToTime(ts)
tError(er == nil, "empty time string expect an error", t)
ts = "fake"
ti, er = expireToTime(ts)
tError(er == nil, "bad time string expect an error", t)
ts = "Feb 3, 2013 at 7:54pm"
ti, er = expireToTime(ts)
tError(er == nil, "other time format expect an error", t)
ts = "2006-01-02T15:04:05Z"
ti, er = expireToTime(ts)
tError(er != nil, fmt.Sprint(er), t)
tError(ti.String() != "2006-01-02 15:04:05 +0000 UTC", ti.String(), t)
ts = "2006-01-02T15:04:05"
ti, er = expireToTime(ts)
tError(er != nil, fmt.Sprint(er), t)
tError(ti.String() != "2006-01-02 15:04:05 +0000 UTC", ti.String(), t)
ts = "2006-01-02 15:04:05"
ti, er = expireToTime(ts)
tError(er != nil, fmt.Sprint(er), t)
tError(ti.String() != "2006-01-02 15:04:05 +0000 UTC", ti.String(), t)
}
func TestNewSession(t *testing.T) {
var er error
api, er = NewSession("")
tError(er == nil, "empty token expect an error", t)
api, er = NewSession("fake")
tError(er == nil, "bad token expect an error", t)
api, er = NewSession(
"HP1ST252NFKX6Z6RVJ4RKEU23WS2QXSTQHTVYA1JAFWYX306",
Config{},
)
tError(er == nil, "empty url expect an error", t)
api, er = NewSession(
"HP1ST252NFKX6Z6RVJ4RKEU23WS2QXSTQHTVYA1JAFWYX306",
Config{
URL: "https://duckduckgo.com",
},
)
tError(er == nil, "not yapla api endpoint expect an erro", t)
api, er = NewSession("HP1ST252NFKX6Z6RVJ4RKEU23WS2QXSTQHTVYA1JAFWYX306")
tError(er != nil, fmt.Sprint(er), t)
}
func TestLogin(t *testing.T) {
rep, er := api.LoginMember("moncompte@macompagnie.com", "monp4ssW0R4!")
tError(er != nil, fmt.Sprint(er), t)
tError(rep.Result, fmt.Sprint(rep), t)
rep, er = api.LoginContact("moncompte@macompagnie.com", "monp4ssW0R4!")
tError(er != nil, fmt.Sprint(er), t)
tError(rep.Result, fmt.Sprint(rep), t)
}
Loading…
Cancel
Save