diff --git a/server/apiLinstromAccounts.go b/server/apiLinstromAccounts.go index e47a6a0..996fc14 100644 --- a/server/apiLinstromAccounts.go +++ b/server/apiLinstromAccounts.go @@ -66,7 +66,7 @@ func linstromGetAccount(w http.ResponseWriter, r *http.Request) { Msg("Failed to convert storage account (and attached data) into linstrom API representation") other.HttpErr( w, - HttpErrIdConverionFailure, + HttpErrIdConversionFailure, "Failed to convert storage account and attached data into API representation", http.StatusInternalServerError, ) @@ -154,7 +154,7 @@ func linstromUpdateAccount(w http.ResponseWriter, r *http.Request) { log.Error().Err(err).Msg("Failed to convert updated account back into api form") other.HttpErr( w, - HttpErrIdConverionFailure, + HttpErrIdConversionFailure, "Failed to convert updated account back into api form", http.StatusInternalServerError, ) diff --git a/server/apiLinstromNotes.go b/server/apiLinstromNotes.go index 5fc20ce..41ebe60 100644 --- a/server/apiLinstromNotes.go +++ b/server/apiLinstromNotes.go @@ -2,16 +2,61 @@ package server import ( "net/http" + + "github.com/google/jsonapi" + "github.com/rs/zerolog/hlog" + "gitlab.com/mstarongitlab/goutils/other" + "gitlab.com/mstarongitlab/linstrom/storage" ) // Notes func linstromGetNote(w http.ResponseWriter, r *http.Request) { store := StorageFromRequest(r) noteId := NoteIdFromRequest(r) - note, err := store.FindNoteById(noteId) - _ = note - _ = err + log := hlog.FromRequest(r) + sNote, err := store.FindNoteById(noteId) + switch err { + case nil: + // Found, progress past switch statement + case storage.ErrEntryNotFound: + other.HttpErr(w, HttpErrIdNotFound, "Note not found", http.StatusNotFound) + return + default: + log.Error().Err(err).Str("note-id", noteId).Msg("Failed to get note from db") + other.HttpErr( + w, + HttpErrIdDbFailure, + "Failed to get note from db", + http.StatusInternalServerError, + ) + return + } + note, err := convertNoteStorageToLinstrom(sNote, store) + if err != nil { + log.Error(). + Err(err). + Str("note-id", noteId). + Msg("Failed to convert note into linstrom api form") + other.HttpErr( + w, + HttpErrIdConversionFailure, + "Failed to convert note", + http.StatusInternalServerError, + ) + return + } + err = jsonapi.MarshalPayload(w, note) + if err != nil { + log.Error().Err(err).Any("note", note).Msg("Failed to marshal and send note") + other.HttpErr( + w, + HttpErrIdJsonMarshalFail, + "Failed to convert note", + http.StatusInternalServerError, + ) + } } + func linstromUpdateNote(w http.ResponseWriter, r *http.Request) {} func linstromNewNote(w http.ResponseWriter, r *http.Request) {} func linstromDeleteNote(w http.ResponseWriter, r *http.Request) {} diff --git a/server/apiLinstromTypeHelpers.go b/server/apiLinstromTypeHelpers.go index 3ca673b..e02c282 100644 --- a/server/apiLinstromTypeHelpers.go +++ b/server/apiLinstromTypeHelpers.go @@ -125,3 +125,60 @@ func convertInfoFieldStorageToLinstrom(field storage.UserInfoField) *linstromCus BelongsToId: field.BelongsTo, } } + +func convertNoteStorageToLinstrom( + note *storage.Note, + store *storage.Storage, +) (*linstromNote, error) { + panic("Not implemented") +} + +func convertEmoteStorageToLinstrom( + emote *storage.Emote, + store *storage.Storage, +) (*linstromEmote, error) { + storageServer, err := store.FindRemoteServerById(emote.ServerId) + if err != nil { + return nil, fmt.Errorf("server: %w", err) + } + server, err := convertServerStorageToLinstrom(storageServer, store) + if err != nil { + return nil, fmt.Errorf("server conversion: %w", err) + } + storageMedia, err := store.GetMediaMetadataById(emote.MetadataId) + if err != nil { + return nil, fmt.Errorf("media metadata: %w", err) + } + media := convertMediaMetadataStorageToLinstrom(storageMedia) + + return &linstromEmote{ + Id: emote.ID, + MetadataId: emote.MetadataId, + Metadata: media, + Name: emote.Name, + ServerId: emote.ServerId, + Server: server, + }, nil +} + +func convertReactionStorageToLinstrom( + reaction *storage.Reaction, + store *storage.Storage, +) (*linstromReaction, error) { + storageEmote, err := store.GetEmoteById(reaction.EmoteId) + if err != nil { + return nil, fmt.Errorf("emote: %w", err) + } + emote, err := convertEmoteStorageToLinstrom(storageEmote, store) + if err != nil { + return nil, fmt.Errorf("emote conversion: %w", err) + } + + return &linstromReaction{ + Id: reaction.ID, + NoteId: reaction.NoteId, + ReactorId: reaction.ReactorId, + EmoteId: reaction.EmoteId, + Emote: emote, + }, nil +} diff --git a/server/apiLinstromTypes.go b/server/apiLinstromTypes.go index df0863d..3dd3ddd 100644 --- a/server/apiLinstromTypes.go +++ b/server/apiLinstromTypes.go @@ -5,7 +5,6 @@ package server import "time" var ( - _ = linstromNote{} _ = linstromRole{} _ = linstromRelation{} ) @@ -29,6 +28,7 @@ type linstromNote struct { AccessLevel uint8 `jsonapi:"attr,access-level"` Pings []*linstromAccount `jsonapi:"relation,pings,omitempty"` PingIds []string `jsonapi:"attr,ping-ids,omitempty"` + ReactionIds []uint `jsonapi:"attr,reaction-ids"` } type linstromOriginServer struct { @@ -100,6 +100,23 @@ type linstromRelation struct { Accepted bool `jsonapi:"attr,accepted"` } +type linstromReaction struct { + Id uint `jsonapi:"primary,reactions"` + NoteId string `jsonapi:"attr,note-id"` + ReactorId string `jsonapi:"attr,reactor-id"` + EmoteId uint `jsonapi:"attr,emote-id"` + Emote *linstromEmote `jsonapi:"relation,emote"` +} + +type linstromEmote struct { + Id uint `jsonapi:"primary,emotes"` + MetadataId string `jsonapi:"attr,metadata-id"` + Metadata *linstromMediaMetadata `jsonapi:"relation,metadata"` + Name string `jsonapi:"attr,name"` + ServerId uint `jsonapi:"attr,server-id"` + Server *linstromOriginServer `jsonapi:"relation,server"` +} + // Role is essentially just a carbon copy of storage/roles.go type linstromRole struct { Id uint `jsonapi:"primary,roles"` diff --git a/server/constants.go b/server/constants.go index 5a2c304..49d6f85 100644 --- a/server/constants.go +++ b/server/constants.go @@ -18,5 +18,5 @@ const ( HttpErrIdBadRequest HttpErrIdAlreadyExists HttpErrIdNotFound - HttpErrIdConverionFailure + HttpErrIdConversionFailure ) diff --git a/server/server.go b/server/server.go index 91cedff..a1b325f 100644 --- a/server/server.go +++ b/server/server.go @@ -78,7 +78,7 @@ func buildRootHandler( ) mux.HandleFunc("/placeholder-file", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, placeholderFile) + fmt.Fprint(w, *placeholderFile) }) return mux diff --git a/storage/emote.go b/storage/emote.go index 53242bd..6f0bb6e 100644 --- a/storage/emote.go +++ b/storage/emote.go @@ -8,5 +8,18 @@ type Emote struct { MetadataId string Name string // Server RemoteServer // `gorm:"foreignKey:ServerId;references:ID"` - ServerId string + ServerId uint +} + +func (s *Storage) GetEmoteById(id uint) (*Emote, error) { + out := Emote{} + err := s.db.First(&out, id).Error + switch err { + case nil: + return &out, nil + case gorm.ErrRecordNotFound: + return nil, ErrEntryNotFound + default: + return nil, err + } } diff --git a/storage/reactions.go b/storage/reactions.go new file mode 100644 index 0000000..db5ff4c --- /dev/null +++ b/storage/reactions.go @@ -0,0 +1,10 @@ +package storage + +import "gorm.io/gorm" + +type Reaction struct { + gorm.Model + NoteId string + ReactorId string + EmoteId uint +} diff --git a/storage/user.go b/storage/user.go index b11dfa2..c205b42 100644 --- a/storage/user.go +++ b/storage/user.go @@ -168,8 +168,8 @@ func (s *Storage) FindAccountById(id string) (*Account, error) { } log.Debug().Str("account-id", id).Msg("Didn't hit account in cache, checking db") - acc = &Account{ID: id} - res := s.db.First(acc) + acc = &Account{} + res := s.db.Where(Account{ID: id}).First(acc) if res.Error != nil { if errors.Is(res.Error, gorm.ErrRecordNotFound) { log.Warn().Str("account-id", id).Msg("Account not found")