We Had To Use Dark Magic To Make This Work
This commit is contained in:
2
.gitignore
vendored
Executable file
2
.gitignore
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
.idea/
|
||||
.DS_Store
|
21
README.md
Executable file
21
README.md
Executable file
@@ -0,0 +1,21 @@
|
||||
# Email api golang skd
|
||||
|
||||
```shell
|
||||
go get git.siteworxpro.com/golang/packages/email-api
|
||||
```
|
||||
|
||||
````go
|
||||
import "git.siteworxpro.com/golang/packages/email-api/client"
|
||||
|
||||
config := client.ConfigFromEnv()
|
||||
apiClient := client.NewClient(config)
|
||||
|
||||
emails, err := apiClient.GetEmails(1, 100)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, email := range emails.Emails {
|
||||
println(email.Uuid)
|
||||
}
|
||||
````
|
39
client/client.go
Executable file
39
client/client.go
Executable file
@@ -0,0 +1,39 @@
|
||||
package client
|
||||
|
||||
type Client struct {
|
||||
config *Configuration
|
||||
token *Token
|
||||
}
|
||||
|
||||
var c = struct {
|
||||
client *Client
|
||||
initialized bool
|
||||
}{}
|
||||
|
||||
type accessTokenRequest struct {
|
||||
GrantType string `json:"grant_type"`
|
||||
ClientId string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
}
|
||||
|
||||
func NewClient(config *Configuration) *Client {
|
||||
|
||||
if c.initialized {
|
||||
return c.client
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
config: config,
|
||||
}
|
||||
|
||||
token, err := getToken(client.config)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
client.token = token
|
||||
|
||||
c.client = client
|
||||
|
||||
return c.client
|
||||
}
|
36
client/configuration.go
Executable file
36
client/configuration.go
Executable file
@@ -0,0 +1,36 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"git.siteworxpro.com/golang/packages/utilities/Env"
|
||||
"log"
|
||||
)
|
||||
|
||||
const (
|
||||
apiEndpoint Env.EnvironmentVariable = "API_ENDPOINT"
|
||||
clientId Env.EnvironmentVariable = "CLIENT_ID"
|
||||
clientSecret Env.EnvironmentVariable = "CLIENT_SECRET"
|
||||
)
|
||||
|
||||
type Configuration struct {
|
||||
Endpoint string
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
}
|
||||
|
||||
func ConfigFromEnv() *Configuration {
|
||||
config := Configuration{
|
||||
Endpoint: apiEndpoint.GetEnvString("https://email.siteworxpro.com"),
|
||||
ClientId: clientId.GetEnvString(""),
|
||||
ClientSecret: clientSecret.GetEnvString(""),
|
||||
}
|
||||
|
||||
if config.ClientId == "" {
|
||||
log.Fatal("Client ID not provided in ENV. use CLIENT_ID")
|
||||
}
|
||||
|
||||
if config.ClientSecret == "" {
|
||||
log.Fatal("Client Secret not provided in ENV. use ClientSecret")
|
||||
}
|
||||
|
||||
return &config
|
||||
}
|
64
client/create.go
Executable file
64
client/create.go
Executable file
@@ -0,0 +1,64 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type EmailRequest struct {
|
||||
Source string `json:"Source"`
|
||||
Destination struct {
|
||||
ToAddresses []string `json:"ToAddresses"`
|
||||
CcAddresses []string `json:"CcAddresses"`
|
||||
BccAddresses []string `json:"BccAddresses"`
|
||||
} `json:"Destination"`
|
||||
Message struct {
|
||||
Body struct {
|
||||
Html struct {
|
||||
Data string `json:"Data"`
|
||||
} `json:"Html,omitempty"`
|
||||
Text struct {
|
||||
Data string `json:"Data"`
|
||||
} `json:"Text,omitempty"`
|
||||
} `json:"Body"`
|
||||
Subject struct {
|
||||
Data string `json:"Data"`
|
||||
} `json:"Subject"`
|
||||
} `json:"Message"`
|
||||
ScheduledTime time.Time `json:"ScheduledTime,omitempty"`
|
||||
Catch bool `json:"Catch,omitempty"`
|
||||
}
|
||||
|
||||
type EmailCreateResponse struct {
|
||||
Id string `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
func (client *Client) SendEmail(request *EmailRequest) (*EmailCreateResponse, error) {
|
||||
jsonData, _ := json.Marshal(request)
|
||||
|
||||
httpClient := &http.Client{}
|
||||
req, _ := http.NewRequest(
|
||||
"POST",
|
||||
client.config.Endpoint+"/api/email",
|
||||
bytes.NewReader(jsonData),
|
||||
)
|
||||
req.Header.Set("Authorization", client.token.TokenType+" "+client.token.AccessToken)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := Response[EmailCreateResponse]{}
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &response.Payload, nil
|
||||
}
|
70
client/get.go
Executable file
70
client/get.go
Executable file
@@ -0,0 +1,70 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (client *Client) GetEmails(page uint16, limit uint16) (*EmailResponse, error) {
|
||||
response := Response[EmailResponse]{}
|
||||
|
||||
httpClient := &http.Client{}
|
||||
req, _ := http.NewRequest(
|
||||
"GET",
|
||||
client.config.Endpoint+"/api/email?page="+strconv.Itoa(int(page))+"&limit="+strconv.Itoa(int(limit)),
|
||||
nil,
|
||||
)
|
||||
req.Header.Set("Authorization", client.token.TokenType+" "+client.token.AccessToken)
|
||||
get, err := httpClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if get.StatusCode >= 400 {
|
||||
return nil, fmt.Errorf("")
|
||||
}
|
||||
|
||||
body := make([]byte, get.ContentLength)
|
||||
_, err = get.Body.Read(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &response.Payload, nil
|
||||
}
|
||||
|
||||
func (client *Client) GetEmail(uuid string) (*Email, error) {
|
||||
httpClient := &http.Client{}
|
||||
req, _ := http.NewRequest(
|
||||
"GET",
|
||||
client.config.Endpoint+"/api/email/"+uuid,
|
||||
nil,
|
||||
)
|
||||
req.Header.Set("Authorization", client.token.TokenType+" "+client.token.AccessToken)
|
||||
get, err := httpClient.Do(req)
|
||||
defer get.Body.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if get.StatusCode >= 400 {
|
||||
return nil, fmt.Errorf("")
|
||||
}
|
||||
|
||||
response := Response[Email]{}
|
||||
err = json.NewDecoder(get.Body).Decode(&response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &response.Payload, nil
|
||||
}
|
99
client/token.go
Executable file
99
client/token.go
Executable file
@@ -0,0 +1,99 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"git.siteworxpro.com/golang/packages/email-api/redis"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
ExpiresIn uint16 `json:"expires_in"`
|
||||
}
|
||||
|
||||
type AccessTokenRequest struct {
|
||||
GrantType string `json:"grant_type"`
|
||||
ClientId string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
}
|
||||
|
||||
func NewToken(config *Configuration) *Token {
|
||||
|
||||
return &Token{}
|
||||
}
|
||||
|
||||
func getToken(configuration *Configuration) (*Token, error) {
|
||||
|
||||
token := FromCache()
|
||||
|
||||
if token.AccessToken != "" {
|
||||
return token, nil
|
||||
}
|
||||
|
||||
request := accessTokenRequest{
|
||||
GrantType: "client_credentials",
|
||||
ClientId: configuration.ClientId,
|
||||
ClientSecret: configuration.ClientSecret,
|
||||
}
|
||||
|
||||
body, _ := json.Marshal(request)
|
||||
|
||||
resp, err := http.Post(configuration.Endpoint+"/access_token", "application/json", bytes.NewBuffer(body))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
responseBody := make([]byte, resp.ContentLength)
|
||||
_, err = resp.Body.Read(responseBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(responseBody, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
saveCache(token)
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func FromCache() *Token {
|
||||
rdb := redis.NewRedis()
|
||||
|
||||
token := Token{}
|
||||
|
||||
result, err := rdb.Get(context.Background(), "api.access_token").Result()
|
||||
if err != nil {
|
||||
return &token
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(result), &token)
|
||||
if err != nil {
|
||||
return &token
|
||||
}
|
||||
|
||||
return &token
|
||||
}
|
||||
|
||||
func saveCache(token *Token) {
|
||||
rdb := redis.NewRedis()
|
||||
|
||||
tokenJson, _ := json.Marshal(token)
|
||||
|
||||
expiresIn := time.Duration(int64(token.ExpiresIn) * 100000000)
|
||||
|
||||
cmd := rdb.Set(context.Background(), "api.access_token", tokenJson, expiresIn)
|
||||
result, err := cmd.Result()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
println(result)
|
||||
}
|
29
client/types.go
Executable file
29
client/types.go
Executable file
@@ -0,0 +1,29 @@
|
||||
package client
|
||||
|
||||
import "time"
|
||||
|
||||
type Email struct {
|
||||
Uuid string `json:"uuid"`
|
||||
IsSent uint8 `json:"is_sent"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
SentTime time.Time `json:"sent_time"`
|
||||
To string `json:"to"`
|
||||
From string `json:"from"`
|
||||
Subject string `json:"subject"`
|
||||
Body string `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
type EmailResponse struct {
|
||||
Emails []Email `json:"emails"`
|
||||
Page uint16 `json:"page"`
|
||||
AvailablePages uint16 `json:"availablePages"`
|
||||
Total uint16 `json:"total"`
|
||||
}
|
||||
|
||||
type Response[T any] struct {
|
||||
Payload T `json:"payload"`
|
||||
Time uint32 `json:"time"`
|
||||
Version string `json:"version"`
|
||||
Status string `json:"status"`
|
||||
Md5 string `json:"md5"`
|
||||
}
|
10
go.mod
Executable file
10
go.mod
Executable file
@@ -0,0 +1,10 @@
|
||||
module git.siteworxpro.com/golang/packages/email-api
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
git.siteworxpro.com/golang/packages/utilities v1.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/redis/go-redis/v9 v9.0.2 // indirect
|
||||
)
|
6
go.sum
Executable file
6
go.sum
Executable file
@@ -0,0 +1,6 @@
|
||||
git.siteworxpro.com/golang/packages/utilities v1.0.1/go.mod h1:5ZZDqKb5Y7B552oJjhaMVAj6r9xvqw/wkp1EADmT5wg=
|
||||
git.siteworxpro.com/golang/packages/utilities v1.2.0 h1:UDsaEl0NOqPcHudMKcOGwtlShBoqCW3NXYZH9zh+Ju8=
|
||||
git.siteworxpro.com/golang/packages/utilities v1.2.0/go.mod h1:5ZZDqKb5Y7B552oJjhaMVAj6r9xvqw/wkp1EADmT5wg=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
|
40
redis/redis.go
Executable file
40
redis/redis.go
Executable file
@@ -0,0 +1,40 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"git.siteworxpro.com/golang/packages/utilities/Env"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
redisHost Env.EnvironmentVariable = "REDIS_HOST"
|
||||
redisHPassword Env.EnvironmentVariable = "REDIS_PASSWORD"
|
||||
redisDb Env.EnvironmentVariable = "REDIS_DB"
|
||||
)
|
||||
|
||||
var r = struct {
|
||||
client *redis.Client
|
||||
initialized bool
|
||||
}{}
|
||||
|
||||
func NewRedis() *redis.Client {
|
||||
if r.initialized {
|
||||
return r.client
|
||||
}
|
||||
|
||||
db, err := strconv.ParseInt(redisDb.GetEnvString("0"), 10, 64)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: redisHost.GetEnvString("localhost:6379"),
|
||||
Password: redisHPassword.GetEnvString(""),
|
||||
DB: int(db),
|
||||
})
|
||||
|
||||
r.client = rdb
|
||||
|
||||
return r.client
|
||||
}
|
Reference in New Issue
Block a user