mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-01 18:28:59 +01:00
139 lines
3.8 KiB
Go
139 lines
3.8 KiB
Go
package pcloud
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/scripthaus-dev/sh2-server/pkg/scbase"
|
|
"github.com/scripthaus-dev/sh2-server/pkg/sstore"
|
|
)
|
|
|
|
const PCloudEndpoint = "https://api.getprompt.dev/central"
|
|
const PCloudEndpointVarName = "PCLOUD_ENDPOINT"
|
|
const APIVersion = 1
|
|
|
|
type NoTelemetryInputType struct {
|
|
ClientId string `json:"clientid"`
|
|
Value bool `json:"value"`
|
|
}
|
|
|
|
type TelemetryInputType struct {
|
|
UserId string `json:"userid"`
|
|
ClientId string `json:"clientid"`
|
|
CurDay string `json:"curday"`
|
|
Activity []*sstore.ActivityType `json:"activity"`
|
|
}
|
|
|
|
func GetEndpoint() string {
|
|
if !scbase.IsDevMode() {
|
|
return PCloudEndpoint
|
|
}
|
|
endpoint := os.Getenv(PCloudEndpointVarName)
|
|
if endpoint == "" || !strings.HasPrefix(endpoint, "https://") {
|
|
panic("Invalid PCloud dev endpoint, PCLOUD_ENDPOINT not set or invalid")
|
|
}
|
|
return endpoint
|
|
}
|
|
|
|
func makePostReq(ctx context.Context, apiUrl string, data interface{}) (*http.Request, error) {
|
|
var dataReader io.Reader
|
|
if data != nil {
|
|
byteArr, err := json.Marshal(data)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error marshaling json for %s request: %v", apiUrl, err)
|
|
}
|
|
dataReader = bytes.NewReader(byteArr)
|
|
}
|
|
fullUrl := GetEndpoint() + apiUrl
|
|
req, err := http.NewRequestWithContext(ctx, "POST", fullUrl, dataReader)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error creating %s request: %v", apiUrl, err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("X-PromptAPIVersion", strconv.Itoa(APIVersion))
|
|
req.Header.Set("X-PromptAPIUrl", apiUrl)
|
|
req.Close = true
|
|
return req, nil
|
|
}
|
|
|
|
func doRequest(req *http.Request, outputObj interface{}) (*http.Response, error) {
|
|
apiUrl := req.Header.Get("X-PromptAPIUrl")
|
|
log.Printf("sending request %v\n", req.URL)
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error contacting pcloud %q service: %v", apiUrl, err)
|
|
}
|
|
defer resp.Body.Close()
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return resp, fmt.Errorf("error reading %q response body: %v", apiUrl, err)
|
|
}
|
|
if resp.StatusCode != http.StatusOK {
|
|
return resp, fmt.Errorf("error contacting pcloud %q service: %s", apiUrl, resp.Status)
|
|
}
|
|
if outputObj != nil && resp.Header.Get("Content-Type") == "application/json" {
|
|
err = json.Unmarshal(bodyBytes, outputObj)
|
|
if err != nil {
|
|
return resp, fmt.Errorf("error decoding json: %v", err)
|
|
}
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func SendTelemetry(ctx context.Context, force bool) error {
|
|
clientData, err := sstore.EnsureClientData(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot retrieve client data: %v", err)
|
|
}
|
|
if !force && clientData.ClientOpts.NoTelemetry {
|
|
return nil
|
|
}
|
|
activity, err := sstore.GetNonUploadedActivity(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot get activity: %v", err)
|
|
}
|
|
if len(activity) == 0 {
|
|
return nil
|
|
}
|
|
log.Printf("sending telemetry data\n")
|
|
dayStr := sstore.GetCurDayStr()
|
|
input := TelemetryInputType{UserId: clientData.UserId, ClientId: clientData.ClientId, CurDay: dayStr, Activity: activity}
|
|
req, err := makePostReq(ctx, "/telemetry", input)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = doRequest(req, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = sstore.MarkActivityAsUploaded(ctx, activity)
|
|
if err != nil {
|
|
return fmt.Errorf("error marking activity as uploaded: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SendNoTelemetryUpdate(ctx context.Context, noTelemetryVal bool) error {
|
|
clientData, err := sstore.EnsureClientData(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot retrieve client data: %v", err)
|
|
}
|
|
req, err := makePostReq(ctx, "/no-telemetry", NoTelemetryInputType{ClientId: clientData.ClientId, Value: noTelemetryVal})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = doRequest(req, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|