Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Created April 10, 2020 12:45
Show Gist options
  • Save peterhellberg/c692d0b9d3f7a503558b4944e98fccc5 to your computer and use it in GitHub Desktop.
Save peterhellberg/c692d0b9d3f7a503558b4944e98fccc5 to your computer and use it in GitHub Desktop.
Retrieve SMS History from 46elks via their API as documented on https://46elks.com/docs/sms-history
package main
import (
"encoding/json"
"flag"
"fmt"
"net/http"
"net/url"
"os"
)
func main() {
var host, username, password, to, start, end string
var limit int
flag.StringVar(&host, "h", "api.46elks.com", "46elks host")
flag.StringVar(&username, "u", "", "46elks username")
flag.StringVar(&password, "p", "", "46elks password")
flag.StringVar(&start, "s", "", "Retrieve SMS before this date")
flag.StringVar(&end, "e", "", "Retrieve SMS after this date")
flag.StringVar(&to, "t", "", "Filter on recipient")
flag.IntVar(&limit, "l", 0, "Limit the number of results on each page")
flag.Parse()
c := newClient(host, username, password)
q := newQuery(start, end, to, limit)
shr, err := c.SMSHistory(q)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
enc.Encode(shr)
}
type SMS struct {
ID string `json:"id"`
Created string `json:"created"`
Direction string `json:"direction"`
From string `json:"from"`
To string `json:"to"`
Message string `json:"message"`
Status string `json:"status"`
Delivered string `json:"delivered"`
Cost int `json:"cost"`
}
type SMSHistoryResponse struct {
Data []SMS `json:"data"`
Next string `json:"next"`
}
type Client struct {
username string
password string
httpClient *http.Client
baseURL *url.URL
}
func newClient(host, username, password string) *Client {
return &Client{
username: username,
password: password,
httpClient: &http.Client{},
baseURL: &url.URL{Scheme: "https", Host: host},
}
}
func (c *Client) rawurl(path string, query url.Values) string {
ref := &url.URL{Path: path, RawQuery: query.Encode()}
return c.baseURL.ResolveReference(ref).String()
}
func (c *Client) SMSHistory(query url.Values) (*SMSHistoryResponse, error) {
req, err := c.getRequest("/a1/sms", query)
if err != nil {
return nil, err
}
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
var shr SMSHistoryResponse
return &shr, json.NewDecoder(resp.Body).Decode(&shr)
case http.StatusUnauthorized:
return nil, fmt.Errorf("unauthorized")
default:
return nil, fmt.Errorf("unhandled status code: %d", resp.StatusCode)
}
}
func (c *Client) getRequest(path string, query url.Values) (*http.Request, error) {
req, err := http.NewRequest(http.MethodGet, c.rawurl(path, query), nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(c.username, c.password)
return req, nil
}
func newQuery(start, end, to string, limit int) url.Values {
query := url.Values{}
if start != "" {
query.Set("start", start)
}
if end != "" {
query.Set("end", end)
}
if to != "" {
query.Set("to", to)
}
if limit > 0 && limit <= 100 {
query.Set("limit", fmt.Sprintf("%d", limit))
}
return query
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment