Skip to content

Commit

Permalink
Add support for sync endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
oxtyped committed Apr 8, 2024
1 parent 113bfc7 commit 5995254
Show file tree
Hide file tree
Showing 6 changed files with 623 additions and 38 deletions.
5 changes: 5 additions & 0 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var serveCmd = &cobra.Command{
subscriptionAPI := apis.SubscriptionAPI{Data: dataInterface}
episodeAPI := apis.EpisodeAPI{Data: dataInterface}
userAPI := apis.NewUserAPI(dataInterface, verifierSecretKey)
syncAPI := apis.NewSyncAPI(dataInterface, verifierSecretKey)

// TODO: Add the authentication middlewares for the various places

Expand All @@ -79,6 +80,10 @@ var serveCmd = &cobra.Command{
r.Get("/subscriptions/{username}/{deviceid}.{format}", subscriptionAPI.HandleGetDeviceSubscription)
r.Get("/subscriptions/{username}.{format}", subscriptionAPI.HandleGetSubscription)

// sync
r.Get("/api/2/sync-devices/{username}.json", syncAPI.HandleGetSync)
r.Post("/api/2/sync-devices/{username}.json", syncAPI.HandlePostSync)

// episodes
r.Get("/api/2/episodes/{username}.{format}", episodeAPI.HandleEpisodeAction)
r.Post("/api/2/episodes/{username}.{format}", episodeAPI.HandleUploadEpisodeAction)
Expand Down
140 changes: 126 additions & 14 deletions pkg/apis/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
Expand Down Expand Up @@ -132,23 +133,20 @@ func (d *DeviceAPI) HandleUpdateDevice(w http.ResponseWriter, r *http.Request) {
}

log.Printf("DDR is %#v and %#v %#v", ddr, username, deviceName)
err = d.Data.AddDevice(username, deviceName, ddr.Caption, ddr.Type)

_, err = d.Data.UpdateOrCreateDevice(username, deviceName, ddr.Caption, ddr.Type)
if err != nil {
log.Printf("error adding device: %#v", err)
w.WriteHeader(400)
return
}

// 200
// 401
// 404
// 400
w.WriteHeader(200)
}

func (d *DeviceAPI) HandleGetDevices(w http.ResponseWriter, r *http.Request) {
type GetDevicesOutput struct {
Name string `json:"id"`
Id int `json:"id"`
Caption string `json:"caption"`
Type string `json:"type"`
Subscriptions int `json:"subscriptions"`
Expand All @@ -174,7 +172,7 @@ func (d *DeviceAPI) HandleGetDevices(w http.ResponseWriter, r *http.Request) {
// calculate what's the diff
add, _ := data.SubscriptionDiff(subs)
device := GetDevicesOutput{
Name: v.Name,
Id: v.Id,
Caption: v.Caption,
Type: v.Type,
Subscriptions: len(add),
Expand Down Expand Up @@ -288,16 +286,23 @@ func (s *SubscriptionAPI) HandleUploadDeviceSubscriptionChange(w http.ResponseWr
// add (slice)
// remove (slice)
username := chi.URLParam(r, "username")
deviceId := chi.URLParam(r, "deviceid")
deviceIdStr := chi.URLParam(r, "deviceid")
format := chi.URLParam(r, "format")

if format != "json" {
log.Printf("error uploading device subscription changes as format is expecting JSON but got %#v", format)
w.WriteHeader(400)
return
}

deviceId, err := s.Data.GetDeviceIdFromName(deviceIdStr, username)
if err != nil {
log.Printf("error parsing device id: %s", err)
w.WriteHeader(500)
return
}
subscriptionChanges := &SubscriptionChanges{}
err := json.NewDecoder(r.Body).Decode(&subscriptionChanges)
err = json.NewDecoder(r.Body).Decode(&subscriptionChanges)
if err != nil {

log.Printf("error decoding json payload: %#v", err)
Expand All @@ -313,11 +318,18 @@ func (s *SubscriptionAPI) HandleUploadDeviceSubscriptionChange(w http.ResponseWr

db := s.Data

syncDevices, err := db.GetDevicesInSyncGroupFromDeviceId(deviceId)
if err != nil {
log.Printf("error trying to retrieve devices in sync_group: %s", err)
w.WriteHeader(500)
return
}

pairz := []Pair{}
for _, v := range addSlice {
sub := data.Subscription{
User: username,
Device: deviceId,
Devices: syncDevices,
Podcast: v,
Timestamp: ts,
Action: "SUBSCRIBE",
Expand All @@ -333,7 +345,7 @@ func (s *SubscriptionAPI) HandleUploadDeviceSubscriptionChange(w http.ResponseWr
for _, v := range removeSlice {
sub := data.Subscription{
User: username,
Device: deviceId,
Devices: syncDevices,
Podcast: v,
Timestamp: ts,
Action: "UNSUBSCRIBE",
Expand Down Expand Up @@ -388,7 +400,14 @@ func (s *SubscriptionAPI) HandleGetDeviceSubscription(w http.ResponseWriter, r *
// API Endpoint: POST and PUT /subscriptions/{username}/{deviceid}.{format}
func (s *SubscriptionAPI) HandleUploadDeviceSubscription(w http.ResponseWriter, r *http.Request) {
username := chi.URLParam(r, "username")
deviceId := chi.URLParam(r, "deviceid")
deviceIdStr := chi.URLParam(r, "deviceid")
deviceId, err := s.Data.GetDeviceIdFromName(deviceIdStr, username)
if err != nil {
log.Printf("error parsing device id: %s", err)
w.WriteHeader(500)
return
}

format := chi.URLParam(r, "format")
ts := data.CustomTimestamp{}
ts.Time = time.Now()
Expand All @@ -409,7 +428,9 @@ func (s *SubscriptionAPI) HandleUploadDeviceSubscription(w http.ResponseWriter,
var arr []string
err := json.Unmarshal(b, &arr)
if err != nil {
log.Fatal(err)
log.Printf("error unmarshalling payload to json: %s", err)
w.WriteHeader(400)
return
}

f, err := os.Create(fmt.Sprintf("%s-%s.%s", username, deviceId, format))
Expand All @@ -425,7 +446,7 @@ func (s *SubscriptionAPI) HandleUploadDeviceSubscription(w http.ResponseWriter,

sub := data.Subscription{
User: username,
Device: deviceId,
Devices: []int{deviceId},
Podcast: v,
Action: "SUBSCRIBE",
Timestamp: ts,
Expand Down Expand Up @@ -520,3 +541,94 @@ func (e *EpisodeAPI) HandleUploadEpisodeAction(w http.ResponseWriter, r *http.Re
log.Printf("outputbytes is %#v", string(outputBytes))
w.Write(outputBytes)
}

// GET /api/2/sync-devices/{username}.json
func (s *SyncAPI) HandleGetSync(w http.ResponseWriter, r *http.Request) {

// username := chi.URLParam(r, "username")
w.Write([]byte(`{}`))
}

// POST /api/2/sync-devices/{username}.json
// This endpoints takes in a SyncDeviceRequest to link up devices together
func (s *SyncAPI) HandlePostSync(w http.ResponseWriter, r *http.Request) {

username := chi.URLParam(r, "username")
log.Printf("error getting username: %#v", username)

syncReq := &SyncDeviceRequest{}
syncResp := &SyncDeviceStatus{}

respBody, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("error reading request body: %#v", err)
w.WriteHeader(400)
return
}

err = json.Unmarshal(respBody, &syncReq)
if err != nil {
log.Printf("error unmarshalling sync device request: %#v", err)
w.WriteHeader(400)
return
}

for _, syncgroups := range syncReq.Synchronize {
err := s.Data.AddSyncGroup(syncgroups, username)
if err != nil {
log.Printf("errors adding sync group: %#v", err)
w.WriteHeader(500)
return
}

}

for _, device := range syncReq.StopSynchronize {

s.Data.StopDeviceSync(device, username)

}

// start preparing the response back to the user

// get all the device_sync group_id belonging to user
ids, err := s.Data.GetDeviceSyncGroupIds(username)
if err != nil {
log.Printf("error getting devices sync groups id from username: %#v", err)
w.WriteHeader(500)
return
}

for _, deviceSyncGroupId := range ids {
devices, err := s.Data.GetDeviceNameFromDeviceSyncGroupId(deviceSyncGroupId)
if err != nil {
log.Printf("error getting device names from device sync id: %#v", err)
w.WriteHeader(500)
return
}

syncResp.Synchronized = append(syncResp.Synchronized, devices)

}

notSyncedDevices, err := s.Data.GetNotSyncedDevices(username)
if err != nil {
log.Printf("error getting devices that are not synced: %#v", err)
w.WriteHeader(500)
return
}

syncResp.NotSynchronize = notSyncedDevices

respBytes, err := json.Marshal(syncResp)
if err != nil {
log.Printf("error marshalling json for sync response: %#v", err)
w.WriteHeader(500)
return
}

w.WriteHeader(200)
w.Write(respBytes)
return

}
22 changes: 22 additions & 0 deletions pkg/apis/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,25 @@ type UserAPI struct {
verifierSecretKey string
}

type SyncAPI struct {
Data data.DataInterface
verifierSecretKey string
}

func NewUserAPI(data data.DataInterface, verifierSecretKey string) *UserAPI {
return &UserAPI{
Data: data,
verifierSecretKey: verifierSecretKey,
}
}

func NewSyncAPI(data data.DataInterface, verifierSecretKey string) *SyncAPI {
return &SyncAPI{
Data: data,
verifierSecretKey: verifierSecretKey,
}
}

// Incoming Payload

type DeviceDataRequest struct {
Expand All @@ -49,6 +61,11 @@ type SubscriptionChanges struct {
Timestamp *timestamp.Timestamp `json:"timestamp"`
}

type SyncDeviceRequest struct {
Synchronize [][]string `json:"synchronize"`
StopSynchronize []string `json:"stop-synchronize"`
}

// Outgoing Payload

type SubscriptionChangeOutput struct {
Expand All @@ -60,3 +77,8 @@ type EpisodeActionOutput struct {
Actions []data.EpisodeAction `json:"actions"`
Timestamp *timestamp.Timestamp `json:"timestamp"`
}

type SyncDeviceStatus struct {
Synchronized [][]string `json:"synchronized"`
NotSynchronize []string `json:"not-synchronize"`
}
Loading

0 comments on commit 5995254

Please sign in to comment.