[deps] move client and shared structs to another repo

This commit is contained in:
Aleksandr Soloshenko 2024-05-30 21:16:45 +07:00
parent 1a8b275484
commit 0213382a19
16 changed files with 12 additions and 335 deletions

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.22.0
require (
firebase.google.com/go/v4 v4.12.1
github.com/android-sms-gateway/client-go v1.0.0
github.com/capcom6/go-helpers v0.0.0-20240521035030-5f57bddeecee
github.com/capcom6/go-infra-fx v0.0.2
github.com/go-playground/validator/v10 v10.16.0

4
go.sum
View File

@ -28,6 +28,10 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/android-sms-gateway/client-go v0.0.0-20240530135354-8d1ce85b9734 h1:dwNjhVdfNICWeCbLEcTklMFWtJdCRyA8BWnk4LKfFO0=
github.com/android-sms-gateway/client-go v0.0.0-20240530135354-8d1ce85b9734/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.0.0 h1:TPRNHlgcEW6jThsx0y4AG1J7wH5Iry+c6h+ailrSQW4=
github.com/android-sms-gateway/client-go v1.0.0/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=

View File

@ -4,12 +4,12 @@ import (
"errors"
"fmt"
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/messages"
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
"github.com/capcom6/sms-gateway/internal/sms-gateway/services"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
"github.com/capcom6/sms-gateway/pkg/types"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"

View File

@ -1,10 +1,10 @@
package handlers
import (
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/health"
"github.com/capcom6/sms-gateway/internal/version"
"github.com/capcom6/sms-gateway/pkg/maps"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
"github.com/gofiber/fiber/v2"
"go.uber.org/fx"
"go.uber.org/zap"

View File

@ -5,12 +5,12 @@ import (
"fmt"
"strings"
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/go-infra-fx/http/apikey"
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/messages"
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/limiter"

View File

@ -3,8 +3,8 @@ package handlers
import (
"time"
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/push"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/limiter"

View File

@ -7,11 +7,11 @@ import (
"sync"
"time"
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/go-helpers/slices"
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/push"
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
"github.com/capcom6/sms-gateway/pkg/types"
"github.com/jaevor/go-nanoid"
"github.com/nyaruka/phonenumbers"

View File

@ -4,8 +4,8 @@ import (
"reflect"
"testing"
"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
)
func TestService_recipientsStateToModel(t *testing.T) {

View File

@ -9,7 +9,7 @@ import (
"net/http"
"sync"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
"github.com/android-sms-gateway/client-go/smsgateway"
)
const BASE_URL = "https://sms.capcom.me/api/upstream/v1"

View File

@ -1,88 +0,0 @@
package smsgateway
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
const BASE_URL = "https://sms.capcom.me/api/3rdparty/v1"
type Config struct {
Client *http.Client
BaseURL string
User string
Password string
}
type Client struct {
Config Config
}
func NewClient(config Config) *Client {
if config.Client == nil {
config.Client = http.DefaultClient
}
if config.BaseURL == "" {
config.BaseURL = BASE_URL
}
return &Client{Config: config}
}
func (c *Client) Send(ctx context.Context, message Message) (MessageState, error) {
path := "/message"
resp := MessageState{}
return resp, c.doRequest(ctx, http.MethodPost, path, map[string]string{}, &message, &resp)
}
func (c *Client) GetState(ctx context.Context, messageID string) (MessageState, error) {
path := fmt.Sprintf("/message/%s", messageID)
resp := MessageState{}
return resp, c.doRequest(ctx, http.MethodGet, path, map[string]string{}, nil, &resp)
}
func (c *Client) doRequest(ctx context.Context, method, path string, headers map[string]string, payload, response any) error {
var reqBody io.Reader = nil
if payload != nil {
jsonBytes, err := json.Marshal(payload)
if err != nil {
return err
}
reqBody = strings.NewReader(string(jsonBytes))
}
req, err := http.NewRequestWithContext(ctx, method, c.Config.BaseURL+path, reqBody)
if err != nil {
return err
}
req.SetBasicAuth(c.Config.User, c.Config.Password)
if reqBody != nil {
req.Header.Set("Content-Type", "application/json")
}
for k, v := range headers {
req.Header.Add(k, v)
}
resp, err := c.Config.Client.Do(req)
if err != nil {
return err
}
defer func() {
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("unexpected status code %d with body %s", resp.StatusCode, string(body))
}
return json.NewDecoder(resp.Body).Decode(&response)
}

View File

@ -1,76 +0,0 @@
package smsgateway
import (
"context"
"io"
"net/http"
"net/http/httptest"
"reflect"
"testing"
)
func TestClient_Send(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/message" {
w.WriteHeader(http.StatusNotFound)
return
}
if r.Header.Get("Content-Type") != "application/json" {
w.WriteHeader(http.StatusBadRequest)
return
}
req, _ := io.ReadAll(r.Body)
defer r.Body.Close()
if string(req) != `{"message":"","phoneNumbers":null}` {
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write(req)
return
}
w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte(`{}`))
}))
defer server.Close()
client := NewClient(Config{
BaseURL: server.URL,
})
type args struct {
ctx context.Context
message Message
}
tests := []struct {
name string
c *Client
args args
want MessageState
wantErr bool
}{
{
name: "Success",
c: client,
args: args{
ctx: context.TODO(),
message: Message{},
},
want: MessageState{},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.c.Send(tt.args.ctx, tt.args.message)
if (err != nil) != tt.wantErr {
t.Errorf("Client.Send() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Client.Send() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -1,86 +0,0 @@
package smsgateway
import (
"fmt"
"time"
)
const (
ProcessingStatePending ProcessingState = "Pending" // Pending
ProcessingStateProcessed ProcessingState = "Processed" // Processed (received by device)
ProcessingStateSent ProcessingState = "Sent" // Sent
ProcessingStateDelivered ProcessingState = "Delivered" // Delivered
ProcessingStateFailed ProcessingState = "Failed" // Failed
)
var allProcessStates = map[ProcessingState]struct{}{
ProcessingStatePending: {},
ProcessingStateProcessed: {},
ProcessingStateSent: {},
ProcessingStateDelivered: {},
ProcessingStateFailed: {},
}
// Device
type Device struct {
ID string `json:"id" example:"PyDmBQZZXYmyxMwED8Fzy"` // ID
Name string `json:"name" example:"My Device"` // Name
CreatedAt time.Time `json:"createdAt" example:"2020-01-01T00:00:00Z"` // Created at (read only)
UpdatedAt time.Time `json:"updatedAt" example:"2020-01-01T00:00:00Z"` // Updated at (read only)
DeletedAt *time.Time `json:"deletedAt,omitempty" example:"2020-01-01T00:00:00Z"` // Deleted at (read only)
LastSeen time.Time `json:"lastSeen" example:"2020-01-01T00:00:00Z"` // Last seen at (read only)
}
// Message
type Message struct {
ID string `json:"id,omitempty" validate:"omitempty,max=36" example:"PyDmBQZZXYmyxMwED8Fzy"` // ID (if not set - will be generated)
Message string `json:"message" validate:"required,max=65535" example:"Hello World!"` // Content
SimNumber *uint8 `json:"simNumber,omitempty" validate:"omitempty,max=3" example:"1"` // SIM card number (1-3)
WithDeliveryReport *bool `json:"withDeliveryReport,omitempty" example:"true"` // With delivery report
IsEncrypted bool `json:"isEncrypted,omitempty" example:"true"` // Is encrypted
PhoneNumbers []string `json:"phoneNumbers" validate:"required,min=1,max=100,dive,required,min=10,max=128" example:"79990001234"` // Recipients (phone numbers)
TTL *uint64 `json:"ttl,omitempty" validate:"omitempty,min=5" example:"86400"` // Time to live in seconds (conflicts with `validUntil`)
ValidUntil *time.Time `json:"validUntil,omitempty" example:"2020-01-01T00:00:00Z"` // Valid until (conflicts with `ttl`)
}
func (m Message) Validate() error {
if m.TTL != nil && m.ValidUntil != nil {
return fmt.Errorf("%w: ttl and validUntil", ErrConflictFields)
}
return nil
}
// Message state
type MessageState struct {
ID string `json:"id,omitempty" validate:"omitempty,max=36" example:"PyDmBQZZXYmyxMwED8Fzy"` // Message ID
State ProcessingState `json:"state" validate:"required" example:"Pending"` // State
IsHashed bool `json:"isHashed" example:"false"` // Hashed
IsEncrypted bool `json:"isEncrypted" example:"false"` // Encrypted
Recipients []RecipientState `json:"recipients" validate:"required,min=1,dive"` // Recipients states
States map[string]time.Time `json:"states"` // History of states
}
func (m MessageState) Validate() error {
for k := range m.States {
if _, ok := allProcessStates[ProcessingState(k)]; !ok {
return fmt.Errorf("invalid state value: %s", k)
}
}
return nil
}
// Recipient state
type RecipientState struct {
PhoneNumber string `json:"phoneNumber" validate:"required,min=10,max=128" example:"79990001234"` // Phone number or first 16 symbols of SHA256 hash
State ProcessingState `json:"state" validate:"required" example:"Pending"` // State
Error *string `json:"error,omitempty" example:"timeout"` // Error (for `Failed` state)
}
// Push notification
type PushNotification struct {
Token string `json:"token" validate:"required" example:"PyDmBQZZXYmyxMwED8Fzy"` // Device FCM token
}

View File

@ -1,16 +0,0 @@
package smsgateway
// Device registration request
type MobileRegisterRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,max=128" example:"Android Phone"` // Device name
PushToken *string `json:"pushToken" validate:"omitempty,max=256" example:"gHz-T6NezDlOfllr7F-Be"` // FCM token
}
// Device update request
type MobileUpdateRequest struct {
Id string `json:"id" example:"QslD_GefqiYV6RQXdkM6V"` // ID
PushToken string `json:"pushToken" validate:"omitempty,max=256" example:"gHz-T6NezDlOfllr7F-Be"` // FCM token
}
// Push request
type UpstreamPushRequest = []PushNotification

View File

@ -1,16 +0,0 @@
package smsgateway
// Device registration response
type MobileRegisterResponse struct {
Id string `json:"id" example:"QslD_GefqiYV6RQXdkM6V"` // New device ID
Token string `json:"token" example:"bP0ZdK6rC6hCYZSjzmqhQ"` // Device access token
Login string `json:"login" example:"VQ4GII"` // User login
Password string `json:"password" example:"cp2pydvxd2zwpx"` // User password
}
// Error response
type ErrorResponse struct {
Message string `json:"message" example:"An error occurred"` // Error message
Code int32 `json:"code,omitempty"` // Error code
Data any `json:"data,omitempty"` // Error context
}

View File

@ -1,39 +0,0 @@
package smsgateway
type HealthStatus string
const (
HealthStatusPass HealthStatus = "pass"
HealthStatusWarn HealthStatus = "warn"
HealthStatusFail HealthStatus = "fail"
)
// Details of a health check.
type HealthCheck struct {
// A human-readable description of the check.
Description string `json:"description,omitempty"`
// Unit of measurement for the observed value.
ObservedUnit string `json:"observedUnit,omitempty"`
// Observed value of the check.
ObservedValue int `json:"observedValue"`
// Status of the check.
// It can be one of the following values: "pass", "warn", or "fail".
Status HealthStatus `json:"status"`
}
// Map of check names to their respective details.
type HealthChecks map[string]HealthCheck
// Health status of the application.
type HealthResponse struct {
// Overall status of the application.
// It can be one of the following values: "pass", "warn", or "fail".
Status HealthStatus `json:"status"`
// Version of the application.
Version string `json:"version,omitempty"`
// Release ID of the application.
// It is used to identify the version of the application.
ReleaseID int `json:"releaseId,omitempty"`
// A map of check names to their respective details.
Checks HealthChecks `json:"checks,omitempty"`
}

View File

@ -1,7 +0,0 @@
package smsgateway
import "errors"
type ProcessingState string
var ErrConflictFields = errors.New("conflict fields")