286 lines
8.0 KiB
Go
286 lines
8.0 KiB
Go
package integration
|
|
|
|
import (
|
|
"bytes"
|
|
"chatapp-cron/internal/config"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Client struct {
|
|
cfg config.Config
|
|
httpClient *http.Client
|
|
}
|
|
|
|
type SendActivityRewardRequest struct {
|
|
TrackID int64 `json:"trackId"`
|
|
Origin string `json:"origin"`
|
|
SysOrigin string `json:"sysOrigin"`
|
|
SourceGroupID int64 `json:"sourceGroupId"`
|
|
AcceptUserID int64 `json:"acceptUserId"`
|
|
}
|
|
|
|
type UserProfile struct {
|
|
ID Int64Value `json:"id"`
|
|
UserAvatar string `json:"userAvatar"`
|
|
UserNickname string `json:"userNickname"`
|
|
}
|
|
|
|
type RoomContributionActivityCount struct {
|
|
ID string `json:"id"`
|
|
RoomID Int64Value `json:"roomId"`
|
|
ContributionValue AmountValue `json:"contributionValue"`
|
|
DateNumber int `json:"dateNumber"`
|
|
Received bool `json:"received"`
|
|
RewardCoinsSent bool `json:"rewardCoinsSent"`
|
|
}
|
|
|
|
type RoomProfile struct {
|
|
ID Int64Value `json:"id"`
|
|
RoomAccount string `json:"roomAccount"`
|
|
UserID Int64Value `json:"userId"`
|
|
RoomCover string `json:"roomCover"`
|
|
RoomName string `json:"roomName"`
|
|
SysOrigin string `json:"sysOrigin"`
|
|
CountryCode string `json:"countryCode"`
|
|
CountryName string `json:"countryName"`
|
|
}
|
|
|
|
type GoldReceiptCommand struct {
|
|
ReceiptType string `json:"receiptType"`
|
|
UserID int64 `json:"userId"`
|
|
SysOrigin string `json:"sysOrigin"`
|
|
EventID string `json:"eventId"`
|
|
Origin string `json:"origin,omitempty"`
|
|
Remark string `json:"remark,omitempty"`
|
|
Amount PennyAmountPayload `json:"amount"`
|
|
CloseDelayAsset bool `json:"closeDelayAsset"`
|
|
OpUserType string `json:"opUserType"`
|
|
CustomizeOrigin string `json:"customizeOrigin,omitempty"`
|
|
CustomizeOriginDesc string `json:"customizeOriginDesc,omitempty"`
|
|
}
|
|
|
|
type PennyAmountPayload struct {
|
|
PennyAmount int64 `json:"pennyAmount,string"`
|
|
DollarAmount int64 `json:"dollarAmount"`
|
|
}
|
|
|
|
type resultResponse[T any] struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Body T `json:"body"`
|
|
Success *bool `json:"success"`
|
|
}
|
|
|
|
type Int64Value int64
|
|
|
|
func (v *Int64Value) UnmarshalJSON(data []byte) error {
|
|
raw := strings.TrimSpace(string(data))
|
|
if raw == "" || raw == "null" {
|
|
*v = 0
|
|
return nil
|
|
}
|
|
if strings.HasPrefix(raw, "\"") && strings.HasSuffix(raw, "\"") {
|
|
raw = strings.Trim(raw, "\"")
|
|
}
|
|
parsed, err := strconv.ParseInt(raw, 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*v = Int64Value(parsed)
|
|
return nil
|
|
}
|
|
|
|
type AmountValue int64
|
|
|
|
func (v *AmountValue) UnmarshalJSON(data []byte) error {
|
|
raw := strings.TrimSpace(string(data))
|
|
if raw == "" || raw == "null" {
|
|
*v = 0
|
|
return nil
|
|
}
|
|
if strings.HasPrefix(raw, "\"") && strings.HasSuffix(raw, "\"") {
|
|
raw = strings.Trim(raw, "\"")
|
|
}
|
|
if raw == "" {
|
|
*v = 0
|
|
return nil
|
|
}
|
|
floatRaw := raw
|
|
if dot := strings.Index(raw, "."); dot >= 0 {
|
|
raw = raw[:dot]
|
|
}
|
|
if parsed, err := strconv.ParseInt(raw, 10, 64); err == nil {
|
|
*v = AmountValue(parsed)
|
|
return nil
|
|
}
|
|
parsed, err := strconv.ParseFloat(floatRaw, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*v = AmountValue(int64(parsed))
|
|
return nil
|
|
}
|
|
|
|
func New(cfg config.Config) *Client {
|
|
return &Client{
|
|
cfg: cfg,
|
|
httpClient: &http.Client{
|
|
Timeout: cfg.Timeout,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *Client) SendActivityReward(ctx context.Context, req SendActivityRewardRequest) error {
|
|
return c.postJSON(ctx, c.cfg.JavaOtherBaseURL+"/props-activity-cnf/client/sendActivityReward", req, nil)
|
|
}
|
|
|
|
func (c *Client) ListLastWeekRoomContribution(ctx context.Context) ([]RoomContributionActivityCount, error) {
|
|
endpoint := c.cfg.JavaOtherBaseURL + "/room-contribution-activity-count/client/listLastWeek"
|
|
var resp resultResponse[[]RoomContributionActivityCount]
|
|
if err := c.getJSON(ctx, endpoint, &resp); err != nil {
|
|
return nil, err
|
|
}
|
|
return resp.Body, nil
|
|
}
|
|
|
|
func (c *Client) MarkRoomTurnoverRewardCoinsSent(ctx context.Context, id string) (bool, error) {
|
|
id = strings.TrimSpace(id)
|
|
if id == "" {
|
|
return false, fmt.Errorf("empty room contribution id")
|
|
}
|
|
endpoint := c.cfg.JavaOtherBaseURL + "/room-contribution-activity-count/client/rewardCoinsSent?id=" + url.QueryEscape(id)
|
|
var resp resultResponse[bool]
|
|
if err := c.postEmpty(ctx, endpoint, &resp); err != nil {
|
|
return false, err
|
|
}
|
|
return resp.Body, nil
|
|
}
|
|
|
|
func (c *Client) MapRoomProfiles(ctx context.Context, roomIDs []int64) (map[int64]RoomProfile, error) {
|
|
if len(roomIDs) == 0 {
|
|
return map[int64]RoomProfile{}, nil
|
|
}
|
|
endpoint := c.cfg.JavaOtherBaseURL + "/room-manager/client/mapProfileByRoomIds"
|
|
var resp resultResponse[map[string]RoomProfile]
|
|
if err := c.postJSON(ctx, endpoint, roomIDs, &resp); err != nil {
|
|
return nil, err
|
|
}
|
|
result := make(map[int64]RoomProfile, len(resp.Body))
|
|
for key, value := range resp.Body {
|
|
roomID, err := strconv.ParseInt(strings.TrimSpace(key), 10, 64)
|
|
if err != nil {
|
|
roomID = int64(value.ID)
|
|
}
|
|
if roomID <= 0 {
|
|
continue
|
|
}
|
|
result[roomID] = value
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *Client) ChangeGoldBalance(ctx context.Context, cmd GoldReceiptCommand) error {
|
|
var resp resultResponse[json.RawMessage]
|
|
if err := c.postJSON(ctx, c.cfg.JavaWalletBaseURL+"/wallet/gold/client/balance/change", cmd, &resp); err != nil {
|
|
return err
|
|
}
|
|
return ensureSuccessfulResult(resp.Code, resp.Message, resp.Success)
|
|
}
|
|
|
|
func NewPennyAmountPayloadFromDollar(amount int64) PennyAmountPayload {
|
|
return PennyAmountPayload{
|
|
PennyAmount: amount * 100,
|
|
DollarAmount: amount,
|
|
}
|
|
}
|
|
|
|
func (c *Client) GetUserProfile(ctx context.Context, userID int64) (UserProfile, error) {
|
|
endpoint := c.cfg.JavaOtherBaseURL + "/user-profile/client/getByUserId?userId=" + url.QueryEscape(strconv.FormatInt(userID, 10))
|
|
var resp resultResponse[UserProfile]
|
|
if err := c.getJSON(ctx, endpoint, &resp); err != nil {
|
|
return UserProfile{}, err
|
|
}
|
|
if int64(resp.Body.ID) == 0 {
|
|
return UserProfile{}, fmt.Errorf("empty user profile response")
|
|
}
|
|
return resp.Body, nil
|
|
}
|
|
|
|
func (c *Client) getJSON(ctx context.Context, endpoint string, out any) error {
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
return decodeResponse(resp, out)
|
|
}
|
|
|
|
func (c *Client) postJSON(ctx context.Context, endpoint string, payload any, out any) error {
|
|
data, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewReader(data))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
return decodeResponse(resp, out)
|
|
}
|
|
|
|
func (c *Client) postEmpty(ctx context.Context, endpoint string, out any) error {
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
return decodeResponse(resp, out)
|
|
}
|
|
|
|
func decodeResponse(resp *http.Response, out any) error {
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.StatusCode >= http.StatusBadRequest {
|
|
return fmt.Errorf("java api failed: status=%d body=%s", resp.StatusCode, strings.TrimSpace(string(body)))
|
|
}
|
|
if out == nil || len(body) == 0 {
|
|
return nil
|
|
}
|
|
if err := json.Unmarshal(body, out); err != nil {
|
|
return fmt.Errorf("decode response failed: %w body=%s", err, strings.TrimSpace(string(body)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ensureSuccessfulResult(code int, message string, success *bool) error {
|
|
if success != nil && !*success {
|
|
return fmt.Errorf("java api returned unsuccessful result: code=%d message=%s", code, strings.TrimSpace(message))
|
|
}
|
|
if code != 0 && code != 200 {
|
|
return fmt.Errorf("java api returned error result: code=%d message=%s", code, strings.TrimSpace(message))
|
|
}
|
|
return nil
|
|
}
|