feat: implemented the way to acquire events in a Go structured way.
This commit is contained in:
parent
2e5805b97b
commit
4b088f5617
11 changed files with 361 additions and 57 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
*.exe
|
*.exe
|
||||||
*.exe~
|
*.exe~
|
||||||
.env
|
.env
|
||||||
|
secret.json
|
||||||
|
|
42
amocrm.go
42
amocrm.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"vultras.su/core/amo/contacts"
|
"vultras.su/core/amo/contacts"
|
||||||
"vultras.su/core/amo/leads"
|
"vultras.su/core/amo/leads"
|
||||||
"vultras.su/core/amo/users"
|
"vultras.su/core/amo/users"
|
||||||
|
"vultras.su/core/amo/events"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IAmoClient interface {
|
type IAmoClient interface {
|
||||||
|
@ -28,15 +29,15 @@ type Client struct {
|
||||||
|
|
||||||
type OauthTokenResponse = api.OauthTokenResponse
|
type OauthTokenResponse = api.OauthTokenResponse
|
||||||
|
|
||||||
func NewAmoClient(options *Options ) (*Client, *TokenPair, error) {
|
func NewAmoClient(secretPath string) (*Client, error) {
|
||||||
apiClient, pair, err := api.NewClient(options)
|
apiClient, err := api.NewApi(secretPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
Api: apiClient,
|
Api: apiClient,
|
||||||
}, pair, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) updateEntity(url string, id int, body interface{}) error {
|
func (client *Client) updateEntity(url string, id int, body interface{}) error {
|
||||||
|
@ -68,7 +69,7 @@ func (client *Client) UpdateLead(lead *leads.Lead) error {
|
||||||
func (client *Client) GetCompany(companyId string, query string) (*companies.Company, error) {
|
func (client *Client) GetCompany(companyId string, query string) (*companies.Company, error) {
|
||||||
deal := new(companies.Company)
|
deal := new(companies.Company)
|
||||||
resource := fmt.Sprintf("/api/v4/companies/%s", companyId)
|
resource := fmt.Sprintf("/api/v4/companies/%s", companyId)
|
||||||
if len(query) != 0 {
|
if query != "" {
|
||||||
resource = resource + "?" + query
|
resource = resource + "?" + query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +77,37 @@ func (client *Client) GetCompany(companyId string, query string) (*companies.Com
|
||||||
return deal, err
|
return deal, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the events from AmoCRM by specified request.
|
||||||
|
// If there are no such events returns an empty slice of events.
|
||||||
|
func (client *Client) GetEvents(req events.EventsRequest) ([]events.Event, error) {
|
||||||
|
res := "/api/v4/events"
|
||||||
|
format := req.Format()
|
||||||
|
if format != "" {
|
||||||
|
res += "?" + format
|
||||||
|
}
|
||||||
|
|
||||||
|
var abs bool
|
||||||
|
ret := []events.Event{}
|
||||||
|
for {
|
||||||
|
resp := events.EventsResponse{}
|
||||||
|
err := client.Api.Get(res, &resp, abs)
|
||||||
|
if err != nil {
|
||||||
|
if err == api.NoContentErr {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret = append(ret, resp.Embedded.Events...)
|
||||||
|
if resp.Links.Next.Href == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
abs = true
|
||||||
|
res = resp.Links.Next.Href
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) UpdateCompany(company *companies.Company) error {
|
func (client *Client) UpdateCompany(company *companies.Company) error {
|
||||||
return client.updateEntity("/api/v4/companies", company.Id, company)
|
return client.updateEntity("/api/v4/companies", company.Id, company)
|
||||||
}
|
}
|
||||||
|
|
168
api/api.go
168
api/api.go
|
@ -8,6 +8,9 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -17,27 +20,31 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientOptions struct {
|
type ClientOptions struct {
|
||||||
Url string
|
Url string `json:"url"`
|
||||||
RedirectUrl string
|
RedirectUrl string `json:"redirect_url"`
|
||||||
|
|
||||||
AuthCode string
|
AuthCode string `json:"auth_code"`
|
||||||
|
|
||||||
ClientId string
|
ClientId string `json:"client_id"`
|
||||||
ClientSecret string
|
ClientSecret string `json:"client_secret"`
|
||||||
|
|
||||||
AccessToken string
|
AccessToken string `json:"access_token"`
|
||||||
RefreshToken string
|
ExpirationDate time.Time `json:"access"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
options *ClientOptions
|
options *ClientOptions
|
||||||
BaseUrl *url.URL
|
BaseUrl *url.URL
|
||||||
|
secretStoreFilePath string
|
||||||
|
Debug bool `json`
|
||||||
}
|
}
|
||||||
|
|
||||||
type requestOptions struct {
|
type requestOptions struct {
|
||||||
HttpMethod string
|
HttpMethod string
|
||||||
Body interface{}
|
Body interface{}
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
|
Abs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type OauthTokenResponse struct {
|
type OauthTokenResponse struct {
|
||||||
|
@ -51,42 +58,114 @@ type TokenPair struct {
|
||||||
Access, Refresh string
|
Access, Refresh string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(options *ClientOptions) (*Client, *TokenPair, error) {
|
func NewApi(secretPath string) (*Client, error) {
|
||||||
if options.Url == "" {
|
ret := &Client{
|
||||||
return nil, nil, errors.New("AmoCrm: Invalid options: Url")
|
secretStoreFilePath: secretPath,
|
||||||
|
}
|
||||||
|
options, err := ret.readSecret()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.Url == "" || options.RedirectUrl == "" {
|
||||||
|
return nil, errors.New("AmoCrm: Invalid options: Url")
|
||||||
}
|
}
|
||||||
resolvedUrl, err := url.Parse(options.Url)
|
resolvedUrl, err := url.Parse(options.Url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := &Client{
|
|
||||||
options: options,
|
|
||||||
}
|
|
||||||
ret.BaseUrl = resolvedUrl
|
ret.BaseUrl = resolvedUrl
|
||||||
|
|
||||||
var pair *TokenPair
|
if err != nil {
|
||||||
if options.AccessToken == "" || options.RefreshToken == "" {
|
return nil, err
|
||||||
pair, err = ret.ExchangeAuth()
|
}
|
||||||
if err != nil {
|
ret.options = options
|
||||||
return nil, nil, err
|
|
||||||
|
var (
|
||||||
|
//pair *TokenPair
|
||||||
|
exchangeErr error
|
||||||
|
exchanged bool
|
||||||
|
)
|
||||||
|
if ret.options.AccessToken == "" || ret.options.RefreshToken == "" {
|
||||||
|
if ret.options.ClientSecret == "" ||
|
||||||
|
ret.options.ClientId == "" ||
|
||||||
|
ret.options.AuthCode == "" {
|
||||||
|
return nil, errors.New("AmoCrm: invalid options: ExchangeAuth")
|
||||||
}
|
}
|
||||||
|
_, exchangeErr = ret.ExchangeAuth()
|
||||||
|
exchanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !exchanged || exchangeErr != nil {
|
||||||
|
// Refreshing token before the work.
|
||||||
|
// Should think of how often should refresh
|
||||||
|
// the token. (see the ExpiresIn)
|
||||||
|
_, err = ret.RefreshToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
options: options,
|
options: options,
|
||||||
BaseUrl: resolvedUrl,
|
BaseUrl: resolvedUrl,
|
||||||
}, pair, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *Client) doRequest(resourceUrl string, requestParams requestOptions, result interface{}) error {
|
func (api *Client) readSecret() (*ClientOptions, error) {
|
||||||
resolvedUrl, err := url.Parse(resourceUrl)
|
f, err := os.Open(api.secretStoreFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bts, err := io.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ret := ClientOptions{}
|
||||||
|
err = json.Unmarshal(bts, &ret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Client) writeSecret() error {
|
||||||
|
bts, err := json.MarshalIndent(api.options, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
requestUrl := api.BaseUrl.ResolveReference(resolvedUrl)
|
err = os.WriteFile(api.secretStoreFilePath, bts, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *Client) doRequest(resourceUrl string, requestParams requestOptions, result interface{}) error {
|
||||||
|
var (
|
||||||
|
requestUrl *url.URL
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if !requestParams.Abs {
|
||||||
|
resolvedUrl, err := url.Parse(resourceUrl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
requestUrl = api.BaseUrl.ResolveReference(resolvedUrl)
|
||||||
|
} else {
|
||||||
|
requestUrl, err = url.Parse(resourceUrl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requestBody := new(bytes.Buffer)
|
requestBody := new(bytes.Buffer)
|
||||||
if requestParams.Body != nil {
|
if requestParams.Body != nil {
|
||||||
|
@ -108,6 +187,9 @@ func (api *Client) doRequest(resourceUrl string, requestParams requestOptions, r
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := http.DefaultClient.Do(request)
|
response, err := http.DefaultClient.Do(request)
|
||||||
|
if api.Debug {
|
||||||
|
fmt.Printf("\nAmo request: %+v\nAmo repsonse: %+v\n", request, response)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf(
|
return errors.New(fmt.Sprintf(
|
||||||
"Request error: %s %d %s %s",
|
"Request error: %s %d %s %s",
|
||||||
|
@ -118,8 +200,23 @@ func (api *Client) doRequest(resourceUrl string, requestParams requestOptions, r
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
|
if response.StatusCode == 204 {
|
||||||
|
return NoContentErr
|
||||||
|
}
|
||||||
|
|
||||||
if response.StatusCode >= 400 {
|
if response.StatusCode >= 400 {
|
||||||
|
/*if response.StatusCode == 401 {
|
||||||
|
_, err := api.RefreshToken()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return api.doRequest(
|
||||||
|
resourceUrl,
|
||||||
|
requestParams,
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
|
||||||
bodyBytes, _ := ioutil.ReadAll(response.Body)
|
bodyBytes, _ := ioutil.ReadAll(response.Body)
|
||||||
return errors.New(fmt.Sprintf(
|
return errors.New(fmt.Sprintf(
|
||||||
"%s %d %s %s",
|
"%s %d %s %s",
|
||||||
|
@ -168,6 +265,10 @@ func (api *Client) ExchangeAuth() (*TokenPair, error) {
|
||||||
|
|
||||||
api.options.AccessToken = result.AccessToken
|
api.options.AccessToken = result.AccessToken
|
||||||
api.options.RefreshToken = result.RefreshToken
|
api.options.RefreshToken = result.RefreshToken
|
||||||
|
err = api.writeSecret()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +279,7 @@ func (api *Client) RefreshToken() (*OauthTokenResponse, error) {
|
||||||
"client_secret": api.options.ClientSecret,
|
"client_secret": api.options.ClientSecret,
|
||||||
"grant_type": "refresh_token",
|
"grant_type": "refresh_token",
|
||||||
"refresh_token": api.options.RefreshToken,
|
"refresh_token": api.options.RefreshToken,
|
||||||
"redirect_uri": api.options.Url,
|
"redirect_uri": api.options.RedirectUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := api.doRequest("/oauth2/access_token", requestOptions{
|
err := api.doRequest("/oauth2/access_token", requestOptions{
|
||||||
|
@ -186,15 +287,30 @@ func (api *Client) RefreshToken() (*OauthTokenResponse, error) {
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: getHeaders(""),
|
Headers: getHeaders(""),
|
||||||
}, result)
|
}, result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return result, err
|
api.options.AccessToken = result.AccessToken
|
||||||
|
api.options.RefreshToken = result.RefreshToken
|
||||||
|
err = api.writeSecret()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *Client) Get(resource string, result interface{}) error {
|
func (api *Client) Get(resource string, result interface{}, abs ...bool) error {
|
||||||
|
var a bool
|
||||||
|
if len(abs) > 0 {
|
||||||
|
a = abs[0]
|
||||||
|
}
|
||||||
return api.doRequest(resource, requestOptions{
|
return api.doRequest(resource, requestOptions{
|
||||||
HttpMethod: http.MethodGet,
|
HttpMethod: http.MethodGet,
|
||||||
Body: nil,
|
Body: nil,
|
||||||
Headers: getHeaders(api.options.AccessToken),
|
Headers: getHeaders(api.options.AccessToken),
|
||||||
|
Abs: a,
|
||||||
}, result)
|
}, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
api/errors.go
Normal file
9
api/errors.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
NoContentErr = errors.New("no content")
|
||||||
|
)
|
|
@ -2,13 +2,16 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"vultras.su/core/amo"
|
"vultras.su/core/amo"
|
||||||
|
"vultras.su/core/amo/api"
|
||||||
"vultras.su/core/amo/webhooks"
|
"vultras.su/core/amo/webhooks"
|
||||||
|
"vultras.su/core/amo/events"
|
||||||
"vultras.su/core/bond"
|
"vultras.su/core/bond"
|
||||||
"vultras.su/core/bond/statuses"
|
"vultras.su/core/bond/statuses"
|
||||||
"os"
|
//"os"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context = bond.Context
|
type Context = bond.Context
|
||||||
|
@ -54,36 +57,46 @@ Def(
|
||||||
))
|
))
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
//fmt.Println(opts)
|
||||||
opts := &amo.Options{
|
client, err := amo.NewAmoClient("secret.json")
|
||||||
Url: os.Getenv("AMO_URL"),
|
|
||||||
RedirectUrl: os.Getenv("AMO_REDIRECT_URL"),
|
|
||||||
AccessToken: os.Getenv("AMO_ACCESS"),
|
|
||||||
RefreshToken: os.Getenv("AMO_REFRESH"),
|
|
||||||
ClientSecret: os.Getenv("AMO_CLIENT_SECRET"),
|
|
||||||
ClientId: os.Getenv("AMO_CLIENT_ID"),
|
|
||||||
AuthCode: os.Getenv("AMO_AUTH_CODE"),
|
|
||||||
}
|
|
||||||
fmt.Println(opts)
|
|
||||||
client, pair, err := amo.NewAmoClient(opts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
client.Api.Debug = true
|
||||||
gclient = client
|
gclient = client
|
||||||
if pair != nil {
|
|
||||||
fmt.Println("PAIR: %q", pair)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*company, err := client.GetCompany("80699047", "")
|
company, err := client.GetCompany("80828925", "")
|
||||||
if err != nil {
|
if err != nil && err != api.NoContentErr {
|
||||||
panic(err)
|
panic(err)
|
||||||
}*/
|
|
||||||
srv := bond.Server{
|
|
||||||
Addr: ":15080",
|
|
||||||
Handler: root,
|
|
||||||
}
|
}
|
||||||
err = srv.ListenAndServe()
|
fmt.Printf("company: %+v\n", company)
|
||||||
if err != nil {
|
interval := time.Second * 10
|
||||||
panic(err)
|
|
||||||
|
now := time.Now()
|
||||||
|
lastChanged := now
|
||||||
|
for {
|
||||||
|
time.Sleep(interval)
|
||||||
|
req := events.EventsRequest{}
|
||||||
|
req.Limit = 10
|
||||||
|
req.Filter.Entity = []string{"company", "contact"}
|
||||||
|
req.Filter.Type = events.CustomFieldValueChanged(
|
||||||
|
2192301,
|
||||||
|
2678095,
|
||||||
|
)
|
||||||
|
req.With = []string{"company_name"}
|
||||||
|
req.Filter.CreatedAt.From = lastChanged
|
||||||
|
events, err := client.GetEvents(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error: %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(events) == 0 {
|
||||||
|
fmt.Printf("nothing changed")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lastChanged = time.Now()
|
||||||
|
for i, event := range events {
|
||||||
|
fmt.Printf("event %d: %v\n", i, event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
events/custom-field.go
Normal file
25
events/custom-field.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package events
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Value struct {
|
||||||
|
CustomFieldValue *CustomFieldValue `json:"custom_field_value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CustomFieldValue struct {
|
||||||
|
EnumId int `json:"enum_id,omitempty"`
|
||||||
|
FieldId int `json:"field_id"`
|
||||||
|
FieldType int `json:"field_type"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func CustomFieldValueChanged(ids ...int64) []string {
|
||||||
|
ret := make([]string, len(ids))
|
||||||
|
for i, id := range ids {
|
||||||
|
ret[i] = fmt.Sprintf("custom_field_%d_value_changed", id)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
43
events/event.go
Normal file
43
events/event.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package events
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventsResponse struct {
|
||||||
|
Page int `json:"_page"`
|
||||||
|
Links struct {
|
||||||
|
Self struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
} `json:"self"`
|
||||||
|
Next struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
} `json:"next"`
|
||||||
|
} `json:"_links"`
|
||||||
|
|
||||||
|
Embedded struct{
|
||||||
|
Events []Event `json:"events"`
|
||||||
|
} `json:"_embedded"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//type Events []Event
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
EntityId int `json:"entity_id"`
|
||||||
|
EntityType string `json:"entity_type"`
|
||||||
|
CreatedBy int64 `json:"created_by"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
ValueAfter []Value `json:"value_after"`
|
||||||
|
ValueBefore []Value `json:"value_before,omitempty"`
|
||||||
|
AccountId int `json:"account_id"`
|
||||||
|
Embedded struct {
|
||||||
|
} `json:"_embedded"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Event) String() string {
|
||||||
|
bts, _ := json.MarshalIndent(e, "", "\t")
|
||||||
|
return string(bts)
|
||||||
|
}
|
||||||
|
|
61
events/main.go
Normal file
61
events/main.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package events
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"strings"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventsRequest struct {
|
||||||
|
Filter struct {
|
||||||
|
CreatedAt struct {
|
||||||
|
From, To time.Time
|
||||||
|
}
|
||||||
|
Type []string
|
||||||
|
Entity []string
|
||||||
|
}
|
||||||
|
Page, Limit uint
|
||||||
|
Ids, CreatedBy []int
|
||||||
|
With []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (req EventsRequest) Format() string {
|
||||||
|
opts := []string{}
|
||||||
|
|
||||||
|
if len(req.With) > 0 {
|
||||||
|
buf := fmt.Sprintf("with=%s", req.With[0])
|
||||||
|
for _, with := range req.With[1:] {
|
||||||
|
buf += ","+with
|
||||||
|
}
|
||||||
|
opts = append(opts, buf)
|
||||||
|
}
|
||||||
|
if req.Page > 0 {
|
||||||
|
opts = append(opts, fmt.Sprintf("page=%d", req.Page))
|
||||||
|
}
|
||||||
|
if req.Limit > 0 {
|
||||||
|
opts = append(opts, fmt.Sprintf("limit=%d", req.Limit))
|
||||||
|
}
|
||||||
|
if !req.Filter.CreatedAt.From.IsZero() && req.Filter.CreatedAt.To.IsZero() {
|
||||||
|
opts = append(opts, fmt.Sprintf("filter[created_at]=%d",
|
||||||
|
req.Filter.CreatedAt.From.Unix(),
|
||||||
|
))
|
||||||
|
} else if !req.Filter.CreatedAt.From.IsZero() && !req.Filter.CreatedAt.To.IsZero() {
|
||||||
|
opts = append(
|
||||||
|
opts,
|
||||||
|
fmt.Sprintf("filter[created_at][from]=%d", req.Filter.CreatedAt.From.Unix()),
|
||||||
|
fmt.Sprintf("filter[created_at][to]=%d", req.Filter.CreatedAt.To.Unix()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, typ := range req.Filter.Type {
|
||||||
|
opts = append(opts, fmt.Sprintf("filter[type][%d]=%s", i, typ))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ent := range req.Filter.Entity {
|
||||||
|
opts = append(opts, fmt.Sprintf("filter[entity][%d]=%s", i, ent))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := strings.Join(opts, "&")
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.21.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
vultras.su/core/bond v0.0.0-20240114204709-a9c2c8810682
|
vultras.su/core/bond v0.0.0-20240118183558-6fa4ef4cf402
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -11,3 +11,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
vultras.su/core/bond v0.0.0-20240114204709-a9c2c8810682 h1:NiT5kAwzjTO+C4/y2EyRI6N8DOl5YFLuyZEUqrYwfFE=
|
vultras.su/core/bond v0.0.0-20240114204709-a9c2c8810682 h1:NiT5kAwzjTO+C4/y2EyRI6N8DOl5YFLuyZEUqrYwfFE=
|
||||||
vultras.su/core/bond v0.0.0-20240114204709-a9c2c8810682/go.mod h1:d8O5wwQlZrVAeoV7qIwxXabB9RuqgopP7wEyRl3++Tc=
|
vultras.su/core/bond v0.0.0-20240114204709-a9c2c8810682/go.mod h1:d8O5wwQlZrVAeoV7qIwxXabB9RuqgopP7wEyRl3++Tc=
|
||||||
|
vultras.su/core/bond v0.0.0-20240118183558-6fa4ef4cf402 h1:XUEdQesLiMX8mK2ZQpJyfE0p+MfmgnOdM1Mt72F+FW4=
|
||||||
|
vultras.su/core/bond v0.0.0-20240118183558-6fa4ef4cf402/go.mod h1:d8O5wwQlZrVAeoV7qIwxXabB9RuqgopP7wEyRl3++Tc=
|
||||||
|
|
2
webhooks/handler.go
Normal file
2
webhooks/handler.go
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
package webhooks
|
||||||
|
|
Loading…
Reference in a new issue