368 lines
10 KiB
Go
368 lines
10 KiB
Go
package tmobile
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
errorsO "errors"
|
|
|
|
"fiskerinc.com/modules/grpc/sms"
|
|
tmtg "fiskerinc.com/modules/tmobtokengen"
|
|
"fiskerinc.com/modules/utils/envtool"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type TMobileMiniClient struct {
|
|
client httpClienter
|
|
tg tmtg.Generator
|
|
accessToken string
|
|
baseURL string
|
|
}
|
|
|
|
|
|
|
|
// Meant to be used within 30 minutes, and then disposed of
|
|
func NewTMobileMiniClient() (client *TMobileMiniClient, err error) {
|
|
client = &TMobileMiniClient{}
|
|
tg, err := InitTokenGen(
|
|
envtool.GetEnv("TMOBILE_PRIVATE_KEY", ""),
|
|
envtool.GetEnv("TMOBILE_CLIENT_ID", ""),
|
|
envtool.GetEnv("TMOBILE_SECRET", ""),
|
|
)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
client.tg = tg
|
|
client.baseURL = Endpoint
|
|
client.client = &http.Client{
|
|
Timeout: time.Minute,
|
|
}
|
|
|
|
acsToken, err := client.AccessToken(context.Background())
|
|
if err != nil {
|
|
return
|
|
}
|
|
client.SetAccessToken(acsToken.AccessToken)
|
|
return
|
|
}
|
|
|
|
// AccessToken implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) AccessToken(ctx context.Context) (out *AccessTokenResponse, err error) {
|
|
path := "/oauth2/v1/tokens"
|
|
emap := make(tmtg.EHTSMap).SetAuthorization(tmc.tg.ClientSecretAsAuthVal()).
|
|
SetURI(path).
|
|
SetHTTPMethod(http.MethodPost)
|
|
|
|
token, err := tmc.tg.Generate(emap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fullPath := tmc.baseURL + path
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, nil)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrCreateRequest, "failed to create request")
|
|
}
|
|
|
|
req.Header.Set(Authorization, tmc.tg.ClientSecretAsAuthVal())
|
|
req.Header.Set(XAuthorization, token)
|
|
|
|
err = tmc.do(req, &out)
|
|
if err != nil {
|
|
return nil, errors.WithMessage(err, failedToDoRequest)
|
|
}
|
|
return
|
|
}
|
|
|
|
|
|
// HandleChangeDeviceStatus implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) ChangeDeviceStatus(ctx context.Context, cda ChangeDeviceActivation) (err error) {
|
|
var fn func(ctx context.Context, in *ICCIDBody)(out *ICCIDBody, err error)
|
|
if cda.Enabled {
|
|
fn = tmc.handleServiceRestore
|
|
}else {
|
|
fn = tmc.handleServiceCancel
|
|
}
|
|
for _, iccid := range cda.ICCIDs {
|
|
iccid = strings.TrimSuffix(strings.TrimSuffix(iccid, "F"), "f")
|
|
temp := ICCIDBody{
|
|
ICCID: iccid,
|
|
}
|
|
_, tErr := fn(ctx, &temp)
|
|
if tErr != nil {
|
|
err = errorsO.Join(err, tErr)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
// ChangeRatePlan implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) ChangeRatePlan(context.Context, *ChangeRatePlanRequest) (*ChangeRatePlanResponse, error) {
|
|
panic("unimplemented")
|
|
}
|
|
|
|
// CustomAttributes implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) CustomAttributes(ctx context.Context, in *CustomAtributesRequest) (*CustomAtributesResponse, error) {
|
|
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/device-attributes"
|
|
fullPath := tmc.baseURL + path
|
|
|
|
payload := new(bytes.Buffer)
|
|
if err := json.NewEncoder(payload).Encode(in); err != nil {
|
|
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
|
}
|
|
payloadStr := payload.String()
|
|
|
|
emap := make(tmtg.EHTSMap).SetAuthorization(tmc.accessToken).
|
|
SetURI(path).
|
|
SetHTTPMethod(http.MethodPost).
|
|
SetContentType(applicationJSON).
|
|
SetBody(payloadStr)
|
|
|
|
popToken, err := tmc.tg.Generate(emap)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set(Authorization, tmc.accessToken)
|
|
req.Header.Set(XAuthOriginator, ToXAuthOriginator(tmc.accessToken))
|
|
req.Header.Set(XAuthorization, popToken)
|
|
req.Header.Set(contentType, applicationJSON)
|
|
out := &CustomAtributesResponse{}
|
|
|
|
err = tmc.do(req, out)
|
|
if err != nil {
|
|
return nil, errors.WithMessage(err, failedToDoRequest)
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
// Details implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) Details(ctx context.Context, iccid string) (out *SMSDetailsResponse, err error) {
|
|
// Really not the way
|
|
path := fmt.Sprintf("/eitcsr-iotcp-notifications-v2/prd02/iotcp/v2/notifications/sms/messages/%s", iccid)
|
|
|
|
emap := make(tmtg.EHTSMap).SetAuthorization(tmc.accessToken).
|
|
SetURI(path).
|
|
SetHTTPMethod(http.MethodGet)
|
|
|
|
token, err := tmc.tg.Generate(emap)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrTokenGen, "failed to generate token: %v", err)
|
|
}
|
|
|
|
fullPath := tmc.baseURL + path
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fullPath, nil)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrCreateRequest, "failed to create request: %v", err)
|
|
}
|
|
|
|
req.Header.Set(Authorization, tmc.accessToken)
|
|
req.Header.Set(XAuthOriginator, ToXAuthOriginator(tmc.accessToken))
|
|
req.Header.Set(XAuthorization, token)
|
|
req.Header.Set(contentType, applicationJSON)
|
|
|
|
err = tmc.do(req, &out)
|
|
if err != nil {
|
|
return nil, errors.WithMessage(err, failedToDoRequest)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// DeviceDetails implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) DeviceDetails(ctx context.Context, in *DeviceDetailsRequest) (out *DeviceDetailsResponse, err error) {
|
|
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/details"
|
|
fullPath := tmc.baseURL + path
|
|
|
|
payload := new(bytes.Buffer)
|
|
if err := json.NewEncoder(payload).Encode(in); err != nil {
|
|
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
|
}
|
|
payloadStr := payload.String()
|
|
|
|
emap := make(tmtg.EHTSMap).SetAuthorization(tmc.accessToken).
|
|
SetURI(path).
|
|
SetHTTPMethod(http.MethodPost).
|
|
SetContentType(applicationJSON).
|
|
SetBody(payloadStr)
|
|
|
|
popToken, err := tmc.tg.Generate(emap)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set(Authorization, tmc.accessToken)
|
|
req.Header.Set(XAuthOriginator, ToXAuthOriginator(tmc.accessToken))
|
|
req.Header.Set(XAuthorization, popToken)
|
|
req.Header.Set(contentType, applicationJSON)
|
|
out = &DeviceDetailsResponse{}
|
|
|
|
err = tmc.do(req, &out)
|
|
if err != nil {
|
|
return nil, errors.WithMessage(err, failedToDoRequest)
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
// GetProducts implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) GetProducts(context.Context, *sms.GetAvailableProductsRequest) (*sms.GetAvailableProductsResponse, error) {
|
|
panic("unimplemented")
|
|
}
|
|
|
|
// SendSMS implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) SendSMS(ctx context.Context, in *SendSMSRequest) (out *SendSMSResponse, err error) {
|
|
panic("unimplemented")
|
|
}
|
|
|
|
// SetAccessToken implements TMobClienter.
|
|
// Possible one dumb piece of code
|
|
func (tmc *TMobileMiniClient) SetAccessToken(accessToken string) {
|
|
tmc.accessToken = "Bearer " + accessToken
|
|
}
|
|
|
|
// SetFilter implements TMobClienter.
|
|
func (tmc *TMobileMiniClient) SetFilter(filter []string) {
|
|
panic("unimplemented")
|
|
}
|
|
|
|
var _ TMobClienter = &TMobileMiniClient{}
|
|
|
|
func (c *TMobileMiniClient) do(req *http.Request, out interface{}) error {
|
|
|
|
resp, err := c.client.Do(req)
|
|
if err != nil {
|
|
return errors.WithMessagef(ErrDoRequest, "failed to do request: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode >= 300 {
|
|
var body []byte
|
|
body, err = io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return errors.WithMessagef(ErrReadResponseBody, "failed to read response body: %v", err)
|
|
}
|
|
|
|
toWrapErr := ErrBadStatusCode
|
|
if resp.StatusCode == http.StatusUnauthorized {
|
|
toWrapErr = ErrAccessTokenExpired
|
|
} else if resp.StatusCode == http.StatusBadGateway {
|
|
toWrapErr = ErrBadGatewayCode
|
|
} else if resp.StatusCode == http.StatusGatewayTimeout {
|
|
toWrapErr = ErrBadGatewayCode
|
|
}
|
|
|
|
return errors.WithMessagef(toWrapErr, "request failed with status code %d, body: %s", resp.StatusCode, string(body))
|
|
}
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(out)
|
|
if err != nil {
|
|
return errors.WithMessagef(ErrJSONMarshal, "failed to decode response: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// sets status as ACTIVATED
|
|
func (tmc *TMobileMiniClient) handleServiceRestore(ctx context.Context, in *ICCIDBody)(out *ICCIDBody, err error){
|
|
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/service-restore"
|
|
fullPath := tmc.baseURL + path
|
|
|
|
payload := new(bytes.Buffer)
|
|
err = json.NewEncoder(payload).Encode(in)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
|
}
|
|
payloadStr := payload.String()
|
|
fmt.Println(payloadStr)
|
|
|
|
emap := make(tmtg.EHTSMap).SetAuthorization(tmc.accessToken).
|
|
SetURI(path).
|
|
SetHTTPMethod(http.MethodPost).
|
|
SetContentType(applicationJSON).
|
|
SetBody(payloadStr)
|
|
popToken, err := tmc.tg.Generate(emap)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set(Authorization, tmc.accessToken)
|
|
req.Header.Set(XAuthOriginator, ToXAuthOriginator(tmc.accessToken))
|
|
req.Header.Set(XAuthorization, popToken)
|
|
req.Header.Set(contentType, applicationJSON)
|
|
out = &ICCIDBody{}
|
|
|
|
err = tmc.do(req, &out)
|
|
|
|
if err != nil {
|
|
return nil, errors.WithMessage(err, failedToDoRequest)
|
|
}
|
|
return
|
|
}
|
|
|
|
// sets status as DEACTIVATED
|
|
func (tmc *TMobileMiniClient) handleServiceCancel(ctx context.Context, in *ICCIDBody)(out *ICCIDBody, err error){
|
|
path := "/eitcsr-iotcp-line-of-service-v1/prd02/iotcp/v1/line-of-service/devices/service-suspend"
|
|
fullPath := tmc.baseURL + path
|
|
|
|
payload := new(bytes.Buffer)
|
|
err = json.NewEncoder(payload).Encode(in)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrJSONMarshal, failedToParseRequest, err)
|
|
}
|
|
payloadStr := payload.String()
|
|
|
|
emap := make(tmtg.EHTSMap).SetAuthorization(tmc.accessToken).
|
|
SetURI(path).
|
|
SetHTTPMethod(http.MethodPost).
|
|
SetContentType(applicationJSON).
|
|
SetBody(payloadStr)
|
|
popToken, err := tmc.tg.Generate(emap)
|
|
if err != nil {
|
|
return nil, errors.WithMessagef(ErrTokenGen, failedGeneratePod, err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fullPath, payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Set(Authorization, tmc.accessToken)
|
|
req.Header.Set(XAuthOriginator, ToXAuthOriginator(tmc.accessToken))
|
|
req.Header.Set(XAuthorization, popToken)
|
|
req.Header.Set(contentType, applicationJSON)
|
|
out = &ICCIDBody{}
|
|
|
|
err = tmc.do(req, &out)
|
|
|
|
if err != nil {
|
|
return nil, errors.WithMessage(err, failedToDoRequest)
|
|
}
|
|
return
|
|
} |