147 lines
4.2 KiB
Go
147 lines
4.2 KiB
Go
package voicechat
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"sync/atomic"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
|
)
|
|
|
|
type eosauth struct {
|
|
AccessToken string `json:"access_token"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
ExpiresIn int64 `json:"expires_in"`
|
|
DeploymentId string `json:"deployment_id"`
|
|
ProductId string `json:"product_id"`
|
|
SandboxId string `json:"sandbox_id"`
|
|
TokenType string `json:"token_type"`
|
|
}
|
|
|
|
func eosTokenRefresh(target *unsafe.Pointer, ctx context.Context) {
|
|
defer func() {
|
|
r := recover()
|
|
if r != nil {
|
|
logger.Error(r)
|
|
}
|
|
}()
|
|
|
|
endpoint := "https://api.epicgames.dev/auth/v1/oauth/token"
|
|
auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", config.EosClientId, config.EosClientSecret)))
|
|
for {
|
|
req, _ := http.NewRequest("POST", endpoint, bytes.NewBufferString("grant_type=client_credentials&deployment_id="+config.EosDeploymentId))
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("Authorization", fmt.Sprintf("Basic %s", auth))
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
logger.Println("eosTokenRefresh failed. eos token reqeust err :", err)
|
|
time.Sleep(time.Minute)
|
|
continue
|
|
}
|
|
|
|
var neweos eosauth
|
|
err = json.NewDecoder(resp.Body).Decode(&neweos)
|
|
resp.Body.Close()
|
|
|
|
if err != nil {
|
|
logger.Println("eosTokenRefresh failed. decode err :", err)
|
|
return
|
|
}
|
|
|
|
logger.Printf("eos access_token retreived : %s...", neweos.AccessToken[:20])
|
|
atomic.StorePointer(target, unsafe.Pointer(&neweos))
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
|
|
case <-time.After(time.Duration(neweos.ExpiresIn-60) * time.Second):
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
type eosRoomParticipantRequests struct {
|
|
Puid string `json:"puid"`
|
|
ClientIP string `json:"clientIP"`
|
|
HardMuted bool `json:"hardMuted"`
|
|
}
|
|
|
|
type eosRoomParticipants struct {
|
|
Participants []eosRoomParticipantRequests `json:"participants"`
|
|
}
|
|
|
|
func (gv *eosauth) joinVoiceChat(data JoinVoiceChatRequst) map[string]any {
|
|
// https://dev.epicgames.com/docs/web-api-ref/voice-web-api
|
|
accessToken := gv.AccessToken
|
|
if len(accessToken) == 0 {
|
|
logger.Println("eos voice chat is not ready. access_token is empty")
|
|
return nil
|
|
}
|
|
|
|
voiceendpoint := fmt.Sprintf("https://api.epicgames.dev/rtc/v1/%s/room/%s", config.EosDeploymentId, data.Gid)
|
|
participants := eosRoomParticipants{
|
|
Participants: []eosRoomParticipantRequests{
|
|
{Puid: data.Alias},
|
|
},
|
|
}
|
|
|
|
body, _ := json.Marshal(participants)
|
|
req, _ := http.NewRequest("POST", voiceendpoint, bytes.NewBuffer(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
logger.Println("join voice room failed. api.epicgames.dev return err :", err)
|
|
return nil
|
|
}
|
|
|
|
var result map[string]any
|
|
json.NewDecoder(resp.Body).Decode(&result)
|
|
resp.Body.Close()
|
|
|
|
result["client_id"] = config.EosClientId
|
|
result["client_secret"] = config.EosClientSecret
|
|
|
|
par := result["participants"].([]any)[0]
|
|
participant := par.(map[string]any)
|
|
|
|
channelCredentials := map[string]any{
|
|
"override_userid": data.Alias,
|
|
"client_base_url": result["clientBaseUrl"],
|
|
"participant_token": participant["token"],
|
|
}
|
|
marshaled, _ := json.Marshal(channelCredentials)
|
|
result["channel_credentials"] = base64.StdEncoding.EncodeToString(marshaled)
|
|
|
|
return result
|
|
}
|
|
|
|
func (gv *eosauth) leaveVoiceChat(data LeaveVoiceChatRequst) {
|
|
voiceendpoint := fmt.Sprintf("https://api.epicgames.dev/rtc/v1/%s/room/%s/participants/%s", config.EosDeploymentId, data.Gid, data.Alias)
|
|
accessToken := gv.AccessToken
|
|
|
|
req, _ := http.NewRequest("DELETE", voiceendpoint, nil)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
|
resp, err := http.DefaultClient.Do(req)
|
|
|
|
if err != nil {
|
|
logger.Println("LeaveVoiceChat failed. err :", err)
|
|
return
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != http.StatusNoContent {
|
|
// 204가 정상 응답
|
|
logger.Println("LeaveVoiceChat failed. status code :", resp.StatusCode)
|
|
}
|
|
}
|