From 3b7d937df5d67743b478b5766ea0f6d310e4a5d8 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Sat, 19 Feb 2022 15:47:25 +0000 Subject: [PATCH] refactor of controllers for scrobbling --- controllers/index.go | 2 +- controllers/scrobble.go | 111 ++++++++---- models/media.go | 16 ++ models/post.go | 19 ++ models/user.go | 33 ++++ scrobble/imdb.go | 76 -------- server/router.go | 7 +- server/server.go | 1 + services/micropub/config.go | 17 ++ services/micropub/microformat.go | 6 + services/micropub/service.go | 222 +++++++++++++++++++++++ services/scrobble/imdb.go | 136 ++++++++++++++ {scrobble => services/scrobble}/meta.go | 11 +- services/scrobble/scrobbler.go | 90 +++++++++ {scrobble => services/scrobble}/types.go | 0 templates/preview.tmpl | 4 +- templates/scrobble.tmpl | 2 +- 17 files changed, 631 insertions(+), 122 deletions(-) create mode 100644 models/media.go create mode 100644 models/post.go create mode 100644 models/user.go delete mode 100644 scrobble/imdb.go create mode 100644 services/micropub/config.go create mode 100644 services/micropub/microformat.go create mode 100644 services/micropub/service.go create mode 100644 services/scrobble/imdb.go rename {scrobble => services/scrobble}/meta.go (59%) create mode 100644 services/scrobble/scrobbler.go rename {scrobble => services/scrobble}/types.go (100%) diff --git a/controllers/index.go b/controllers/index.go index cdf701f..90ca28d 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -4,7 +4,7 @@ import ( "net/http" "git.jamesravey.me/ravenscroftj/indiescrobble/models" - "git.jamesravey.me/ravenscroftj/indiescrobble/scrobble" + "git.jamesravey.me/ravenscroftj/indiescrobble/services/scrobble" "github.com/gin-gonic/gin" ) diff --git a/controllers/scrobble.go b/controllers/scrobble.go index 7aa08ce..5fcac3b 100644 --- a/controllers/scrobble.go +++ b/controllers/scrobble.go @@ -2,15 +2,27 @@ package controllers import ( "net/http" + "time" "git.jamesravey.me/ravenscroftj/indiescrobble/models" - "git.jamesravey.me/ravenscroftj/indiescrobble/scrobble" + "git.jamesravey.me/ravenscroftj/indiescrobble/services/scrobble" "git.jamesravey.me/ravenscroftj/indiescrobble/services/micropub" "github.com/gin-gonic/gin" + "gorm.io/gorm" ) -func Scrobble(c *gin.Context){ +type ScrobbleController struct{ + db *gorm.DB + scrobbler *scrobble.Scrobbler +} + +func NewScrobbleController(db *gorm.DB) *ScrobbleController{ + return &ScrobbleController{db, scrobble.NewScrobbler(db)} +} + +/*Do the actual post to the user's site*/ +func (s *ScrobbleController) DoScrobble(c *gin.Context){ err := c.Request.ParseForm() @@ -21,22 +33,56 @@ func Scrobble(c *gin.Context){ c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ "message": err, }) + return } - // TODO: add validation of type + s.scrobbler.Scrobble(&c.Request.Form, currentUser) +} + + + +/*Display the scrobble form and allow user to search for and add media*/ +func (s *ScrobbleController) ScrobbleForm(c *gin.Context){ + + err := c.Request.ParseForm() + + // this is an authed endpoint so 'user' must be set and if not panicking is fair + currentUser := c.MustGet("user").(*models.BaseUser) + + if err != nil{ + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ + "message": err, + }) + return + } + scrobbleType := c.Request.Form.Get("type") - searchEngine := scrobble.NewSearchProvider(scrobbleType) + if c.Request.Form.Get("item") != "" { - var searchResults []scrobble.ScrobbleMetaRecord = nil - var item scrobble.ScrobbleMetaRecord = nil - - query := c.Request.Form.Get("q") - itemID := c.Request.Form.Get("item") - - if itemID != "" { + item, err := s.scrobbler.GetItemByID(&c.Request.Form) - item, err = searchEngine.SearchProvider.GetItem(itemID) + + if err != nil { + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ + "message": err, + }) + return + }else{ + c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ + "user": currentUser, + "scrobbleType": scrobbleType, + "scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType], + "scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType], + "item": item, + "now": time.Now().Format("2006-01-02T15:04"), + }) + return + } + + }else if query := c.Request.Form.Get("q"); query != "" { + + searchResults, err := s.scrobbler.Search(&c.Request.Form) if err != nil{ c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ @@ -44,32 +90,29 @@ func Scrobble(c *gin.Context){ }) return } - }else if query != "" { - var err error = nil - searchResults, err = searchEngine.SearchProvider.Search(query) - if err != nil{ - c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ - "message": err, - }) - return - } + c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ + "user": currentUser, + "scrobbleType": scrobbleType, + "scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType], + "scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType], + "searchEngine": s.scrobbler.GetSearchEngineNameForType(scrobbleType), + "searchResults": searchResults, + "now": time.Now().Format("2006-01-02T15:04"), + }) + }else{ + c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ + "user": currentUser, + "scrobbleType": scrobbleType, + "scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType], + "scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType], + "now": time.Now().Format("2006-01-02T15:04"), + }) } - - c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ - "user": currentUser, - "scrobbleType": scrobbleType, - "scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType], - "scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType], - "searchEngine": searchEngine.SearchProvider.GetName(), - "searchResults": searchResults, - "item": item, - }) - } -func PreviewScrobble(c *gin.Context){ +func (s *ScrobbleController) PreviewScrobble(c *gin.Context){ err := c.Request.ParseForm() @@ -84,7 +127,7 @@ func PreviewScrobble(c *gin.Context){ scrobbleType := c.Request.Form.Get("type") - searchEngine := scrobble.NewSearchProvider(scrobbleType) + searchEngine := scrobble.NewSearchProvider(scrobbleType, s.db) itemID := c.Request.Form.Get("item") diff --git a/models/media.go b/models/media.go new file mode 100644 index 0000000..cb144bf --- /dev/null +++ b/models/media.go @@ -0,0 +1,16 @@ +package models + +import ( + "database/sql" + + "gorm.io/gorm" +) + +type MediaItem struct{ + gorm.Model + MediaID string `gorm:"not null uniqueIndex"` + ThumbnailURL sql.NullString + DisplayName sql.NullString + CanonicalURL sql.NullString + Data sql.NullString +} \ No newline at end of file diff --git a/models/post.go b/models/post.go new file mode 100644 index 0000000..f68d016 --- /dev/null +++ b/models/post.go @@ -0,0 +1,19 @@ +package models + +import ( + "database/sql" + + "gorm.io/gorm" +) + +type Post struct { + gorm.Model + URL string `gorm:"uniqueIndex"` + PostType string `gorm:"index"` + UserID int `gorm:"foreignKey"` + User User + MediaItemID int `gorm:"index"` + MediaItem MediaItem + ScrobbledAt sql.NullTime + Content sql.NullString +} \ No newline at end of file diff --git a/models/user.go b/models/user.go new file mode 100644 index 0000000..a591896 --- /dev/null +++ b/models/user.go @@ -0,0 +1,33 @@ +package models + +import ( + "math/rand" + + "gorm.io/gorm" +) + +var alphanum = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") + +func randSeq(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = alphanum[rand.Intn(len(alphanum))] + } + return string(b) +} + +type BaseUser struct { + Me string + Token string + UserRecord *User +} + +type User struct { + gorm.Model + Me string `gorm:"uniqueIndex"` + APIKey string +} + +func (u *User) GenerateRandomKey() { + u.APIKey = randSeq(16) +} diff --git a/scrobble/imdb.go b/scrobble/imdb.go deleted file mode 100644 index a4ea395..0000000 --- a/scrobble/imdb.go +++ /dev/null @@ -1,76 +0,0 @@ -package scrobble - -import ( - "fmt" - "net/http" - - "github.com/StalkR/imdb" - "github.com/gregjones/httpcache" - "github.com/gregjones/httpcache/diskcache" -) - -type IMDBMetaRecord struct{ - title imdb.Title -} - -func (r *IMDBMetaRecord) GetID() string{ - return r.title.ID -} - -func (r *IMDBMetaRecord) GetDisplayName() string{ - return fmt.Sprintf("%v (%v)", r.title.Name, r.title.Year) -} - - -func (r *IMDBMetaRecord) GetCanonicalURL() string{ - return r.title.URL -} - -func (r *IMDBMetaRecord) GetThumbnailURL() string{ - return r.title.Poster.ContentURL -} - - -type IMDBScrobbleMetadataProvider struct { - client *http.Client -} - -func NewIMDBProvider() *IMDBScrobbleMetadataProvider { - - cache := diskcache.New("cache") - client := &http.Client{Transport: httpcache.NewTransport(cache)} - return &IMDBScrobbleMetadataProvider{client:client} -} - - -func (i *IMDBScrobbleMetadataProvider) GetName() string { return "IMDB" } - - -func (i *IMDBScrobbleMetadataProvider) GetItem(id string) (ScrobbleMetaRecord, error) { - - title, err := imdb.NewTitle(i.client, id) - - if err != nil{ - return nil, err - } - - return &IMDBMetaRecord{title: *title}, nil - -} - -func (i *IMDBScrobbleMetadataProvider) Search(query string) ([]ScrobbleMetaRecord, error) { - - titles, err := imdb.SearchTitle(i.client, query) - - if err != nil{ - return nil, err - } - - records := make([]ScrobbleMetaRecord, len(titles)) - - for i, title := range titles { - records[i] = &IMDBMetaRecord{title: title} - } - - return records, nil -} \ No newline at end of file diff --git a/server/router.go b/server/router.go index 3e1aeb2..9c92ec9 100644 --- a/server/router.go +++ b/server/router.go @@ -36,8 +36,11 @@ func NewRouter(db *gorm.DB) *gin.Engine { authed := router.Use(middlewares.AuthMiddleware(true, iam)) // add scrobble endpoints - authed.GET("/scrobble", controllers.Scrobble) - authed.POST("/scrobble/preview", controllers.PreviewScrobble) + scrobbleController := controllers.NewScrobbleController(db) + + authed.GET("/scrobble", scrobbleController.ScrobbleForm) + + authed.POST("/scrobble/preview", scrobbleController.PreviewScrobble) // v1 := router.Group("v1") // { diff --git a/server/server.go b/server/server.go index 93e935c..aafed0c 100644 --- a/server/server.go +++ b/server/server.go @@ -30,6 +30,7 @@ func Init() { } db.AutoMigrate(&models.User{}) + db.AutoMigrate(&models.Post{}) r := NewRouter(db) r.LoadHTMLGlob("templates/*.tmpl") diff --git a/services/micropub/config.go b/services/micropub/config.go new file mode 100644 index 0000000..6277f2e --- /dev/null +++ b/services/micropub/config.go @@ -0,0 +1,17 @@ +package micropub + +type MicroPubPostType struct{ + Name string + Type string +} + +type MicroPubSyndicateTarget struct{ + Name string + Uid string +} + +type MicroPubConfig struct{ + MediaEndpoint string `json:"media-endpoint"` + PostTypes []MicroPubPostType `json:"post-types"` + SyndicateTargets []MicroPubSyndicateTarget `json:"syndicate-to"` +} \ No newline at end of file diff --git a/services/micropub/microformat.go b/services/micropub/microformat.go new file mode 100644 index 0000000..e1b52db --- /dev/null +++ b/services/micropub/microformat.go @@ -0,0 +1,6 @@ +package micropub + +type HEntry struct{ + Type []string + Properties map[string]interface{} +} \ No newline at end of file diff --git a/services/micropub/service.go b/services/micropub/service.go new file mode 100644 index 0000000..0238511 --- /dev/null +++ b/services/micropub/service.go @@ -0,0 +1,222 @@ +package micropub + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "net/url" + "strings" + + "git.jamesravey.me/ravenscroftj/indiescrobble/models" + "github.com/PuerkitoBio/goquery" +) + +const(USER_AGENT_STRING="IndieScrobble (indiescrobble.club)") + +type MicropubDiscoveryService struct { +} + +func (m *MicropubDiscoveryService) doGet(url string ) (*http.Response, error) { + client := http.Client{} + req, err := http.NewRequest("GET", url, nil) + + req.Header.Add("User-Agent", USER_AGENT_STRING) + + if err != nil { + return nil, err + } + + return client.Do(req) +} + + +func (m *MicropubDiscoveryService) doAuthGet(url string, bearerToken string ) (*http.Response, error) { + client := http.Client{} + req, err := http.NewRequest("GET", url, nil) + + req.Header.Add("User-Agent", USER_AGENT_STRING) + req.Header.Add("Authorization", fmt.Sprintf("Bearer %v",bearerToken)) + + if err != nil { + return nil, err + } + + return client.Do(req) +} + +func (m *MicropubDiscoveryService) findMicropubEndpoint(me string) (string, error) { + + res, err := m.doGet(me) + + if err != nil { + return "", err + } + + defer res.Body.Close() + + if res.StatusCode != 200 { + log.Fatalf("status code error: %d %s", res.StatusCode, res.Status) + } + + // Load the HTML document + doc, err := goquery.NewDocumentFromReader(res.Body) + if err != nil { + return "", err + } + + // Find the review items + s := doc.Find("link[rel=micropub]") + + if s.Length() < 1 { + return "", fmt.Errorf("no micropub endpoint found for %v", me) + } + + // parse the returned URL + endpointUrl, err := url.Parse(s.AttrOr("href","")) + + if err != nil{ + return "", err + } + + if !endpointUrl.IsAbs(){ + + if(strings.HasPrefix(endpointUrl.Path, "/")) { + + newUrl := *res.Request.URL + newUrl.Path = endpointUrl.Path + + return newUrl.String(), nil + }else{ + return res.Request.URL.String() + endpointUrl.Path, nil + } + + }else{ + return endpointUrl.String(), nil + } +} + +func (m *MicropubDiscoveryService) getMicropubConfig(endpoint string, authToken string) (*MicroPubConfig, error) { + + configUrl, err := url.Parse(endpoint) + + if err != nil{ + return nil, err + } + + q := configUrl.Query() + q.Set("q","config") + configUrl.RawQuery = q.Encode() + + res, err := m.doAuthGet(configUrl.String(), authToken) + + if err != nil{ + return nil, err + } + + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + + if err != nil { + return nil, err + } + + config := MicroPubConfig{} + + err = json.Unmarshal(body, &config) + + if err != nil { + return nil, err + } + + return &config, nil +} + +/* Discover endpoints for given me/domain identifier */ +func (m *MicropubDiscoveryService) Discover(me string, authToken string) (*MicroPubConfig, error) { + + endpoint, err := m.findMicropubEndpoint(me) + + if err != nil{ + log.Printf("Failed to get endpoint: %v\n", err) + return nil, err + } + + // get endpoint config + config, err := m.getMicropubConfig(endpoint, authToken) + + + if err != nil{ + log.Printf("Failed to get configuration: %v\n", err) + return nil, err + } + + return config, nil + +} + +/* Send micropub to endpoint */ +func (m *MicropubDiscoveryService) SubmitScrobble(currentUser *models.BaseUser, post *models.Post) (error) { + endpoint, err := m.findMicropubEndpoint(currentUser.Me) + + if err != nil{ + return err + } + + postObj := make(map[string]interface{}) + postObj["type"] = []string{"h-entry"} + postObj["visibility"] = []string{"public"} + + properties := make(map[string]interface{}) + properties["media-type"] = []string{post.PostType} + properties["media-item-id"] = []string{post.MediaItem.MediaID} + properties["media-item-url"] = []string{post.MediaItem.CanonicalURL.String} + + properties["indiescrobble-id"] = post.MediaItem.ID + + if post.MediaItem.ThumbnailURL.Valid{ + properties["photo"] = []string{post.MediaItem.ThumbnailURL.String} + } + + if post.Content.Valid{ + postObj["content"] = post.Content.String + } + + postObj["properties"] = properties + + bodyBytes, err := json.Marshal(postObj) + + if err != nil{ + return err + } + + body := bytes.NewReader(bodyBytes) + + req, err := http.NewRequest("POST", endpoint, body) + + if err != nil{ + return err + } + + req.Header.Add("User-Agent", USER_AGENT_STRING) + req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", currentUser.Token)) + + resp, err := http.DefaultClient.Do(req) + + if err != nil{ + return err + } + + loc, err := resp.Location() + + if err != nil{ + return err + } + + post.URL = loc.String() + + return nil +} \ No newline at end of file diff --git a/services/scrobble/imdb.go b/services/scrobble/imdb.go new file mode 100644 index 0000000..3cfd6ae --- /dev/null +++ b/services/scrobble/imdb.go @@ -0,0 +1,136 @@ +package scrobble + +import ( + "database/sql" + "encoding/json" + "fmt" + "net/http" + + "git.jamesravey.me/ravenscroftj/indiescrobble/models" + "github.com/StalkR/imdb" + "github.com/gregjones/httpcache" + "github.com/gregjones/httpcache/diskcache" + "gorm.io/gorm" +) + +type IMDBMetaRecord struct{ + title imdb.Title +} + +func (r *IMDBMetaRecord) GetID() string{ + return r.title.ID +} + +func (r *IMDBMetaRecord) GetDisplayName() string{ + return fmt.Sprintf("%v (%v)", r.title.Name, r.title.Year) +} + + +func (r *IMDBMetaRecord) GetCanonicalURL() string{ + return r.title.URL +} + +func (r *IMDBMetaRecord) GetThumbnailURL() string{ + return r.title.Poster.ContentURL +} + + +type IMDBScrobbleMetadataProvider struct { + client *http.Client + db *gorm.DB +} + +func NewIMDBProvider(db *gorm.DB) *IMDBScrobbleMetadataProvider { + + cache := diskcache.New("cache") + client := &http.Client{Transport: httpcache.NewTransport(cache)} + return &IMDBScrobbleMetadataProvider{client:client, db:db} +} + + +func (i *IMDBScrobbleMetadataProvider) GetName() string { return "IMDB" } + + +func titleFromMediaItem(mediaItem *models.MediaItem) imdb.Title { + title := imdb.Title{ID: mediaItem.MediaID, } + return title +} + +func imdbRecordFromMediaItem(mediaItem *models.MediaItem) IMDBMetaRecord { + title := imdb.Title{} + json.Unmarshal([]byte(mediaItem.Data.String), &title) + return IMDBMetaRecord{title:title} +} + +func imdbRecordToMediaItem(record *IMDBMetaRecord) (*models.MediaItem, error){ + + marshalledTitle, err := json.Marshal(record.title) + + if err != nil{ + return nil, err + } + + item := models.MediaItem{ + MediaID: record.title.ID, + ThumbnailURL: sql.NullString{String: record.GetThumbnailURL(), Valid:true}, + CanonicalURL: sql.NullString{String: record.GetCanonicalURL(), Valid: true}, + DisplayName: sql.NullString{String: record.GetDisplayName(), Valid: true}, + Data: sql.NullString{String: string(marshalledTitle), Valid: true}, + } + + return &item, nil +} + + +func (i *IMDBScrobbleMetadataProvider) GetItem(id string) (ScrobbleMetaRecord, error) { + + // see if item is in db first + item := models.MediaItem{} + + result := i.db.Where(&models.MediaItem{MediaID: id}).First(&item) + + if result.Error == nil{ + record := imdbRecordFromMediaItem(&item) + return &record, nil + } + + title, err := imdb.NewTitle(i.client, id) + + if err != nil{ + return nil, err + } + + // cache the title in db and store + record := IMDBMetaRecord{title: *title} + mediaItem, err := imdbRecordToMediaItem(&record) + + result = i.db.Create(mediaItem) + + if result.Error != nil{ + return nil, result.Error + } + + if err != nil{ + return nil, err + } + + return &record, nil + +} + +func (i *IMDBScrobbleMetadataProvider) Search(query string) ([]ScrobbleMetaRecord, error) { + + titles, err := imdb.SearchTitle(i.client, query) + + if err != nil{ + return nil, err + } + + records := make([]ScrobbleMetaRecord, len(titles)) + + for i, title := range titles { + records[i] = &IMDBMetaRecord{title: title} + } + + return records, nil +} \ No newline at end of file diff --git a/scrobble/meta.go b/services/scrobble/meta.go similarity index 59% rename from scrobble/meta.go rename to services/scrobble/meta.go index 4073e92..5116ef2 100644 --- a/scrobble/meta.go +++ b/services/scrobble/meta.go @@ -1,23 +1,20 @@ package scrobble +import "gorm.io/gorm" + type MetaSearchProvider struct{ ScrobbleType string SearchProvider ScrobbleMetaProvider } -func NewSearchProvider(scrobbleType string) *MetaSearchProvider{ +func NewSearchProvider(scrobbleType string, db *gorm.DB) *MetaSearchProvider{ provider := &MetaSearchProvider{ScrobbleType: scrobbleType} if scrobbleType == SCROBBLE_TYPE_MOVIE { - provider.SearchProvider = NewIMDBProvider() + provider.SearchProvider = NewIMDBProvider(db) } return provider } - - -func (m *MetaSearchProvider) search(query string) { - -} \ No newline at end of file diff --git a/services/scrobble/scrobbler.go b/services/scrobble/scrobbler.go new file mode 100644 index 0000000..72fe762 --- /dev/null +++ b/services/scrobble/scrobbler.go @@ -0,0 +1,90 @@ +package scrobble + +import ( + "fmt" + "net/url" + + "git.jamesravey.me/ravenscroftj/indiescrobble/models" + "git.jamesravey.me/ravenscroftj/indiescrobble/services/micropub" + "gorm.io/gorm" +) + +type Scrobbler struct { + db *gorm.DB +} + +func NewScrobbler(db *gorm.DB) *Scrobbler{ + return &Scrobbler{db:db} +} + +func (s *Scrobbler) ValidateType(form *url.Values) error { + + scrobbleType := form.Get("type") + if _, ok := ScrobbleTypeNames[scrobbleType]; !ok{ + return fmt.Errorf("Unknown/invalid scrobble type %v", scrobbleType) + } + + return nil +} + +func (s *Scrobbler) GetItemByID(form *url.Values) (ScrobbleMetaRecord, error) { + + if err := s.ValidateType(form); err != nil { + return nil, err + } + + searchEngine := NewSearchProvider(form.Get("type"), s.db) + + item, err := searchEngine.SearchProvider.GetItem(form.Get("item")) + + if err != nil{ + return nil, err + } + + return item, nil + +} + +func (s *Scrobbler) Search(form *url.Values) ([]ScrobbleMetaRecord, error) { + + if err := s.ValidateType(form); err != nil { + return nil, err + } + + searchEngine := NewSearchProvider(form.Get("type"), s.db) + + query := form.Get("q") + + return searchEngine.SearchProvider.Search(query) + +} + +func (s *Scrobbler) GetSearchEngineNameForType(scrobbleType string) string { + return NewSearchProvider(scrobbleType, s.db).SearchProvider.GetName() +} + +func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*models.Post, error) { + + if err := s.ValidateType(form); err != nil{ + return nil, err + } + + item := models.MediaItem{} + result := s.db.Where(&models.MediaItem{MediaID: form.Get("item")}).First(&item) + + if result.Error != nil{ + return nil, result.Error + } + + discovery := micropub.MicropubDiscoveryService{} + + + + mediaItem := models.MediaItem{} + + post := models.Post{MediaItem: mediaItem, User: *currentUser.UserRecord, PostType: form.Get("type") } + + discovery.SubmitScrobble(currentUser, &post) + + return &post, nil +} \ No newline at end of file diff --git a/scrobble/types.go b/services/scrobble/types.go similarity index 100% rename from scrobble/types.go rename to services/scrobble/types.go diff --git a/templates/preview.tmpl b/templates/preview.tmpl index 8baa4d0..108926a 100644 --- a/templates/preview.tmpl +++ b/templates/preview.tmpl @@ -15,7 +15,7 @@
-

Add A Post > Add {{ .scrobbleTypeName }} > {{.item.GetDisplayName}}

+

Add A Post > Add {{ .scrobbleTypeName }} > {{.item.GetDisplayName}}

Preview Post: {{.item.GetDisplayName}}

@@ -50,6 +50,8 @@ + +
diff --git a/templates/scrobble.tmpl b/templates/scrobble.tmpl index a992df1..b0cddfc 100644 --- a/templates/scrobble.tmpl +++ b/templates/scrobble.tmpl @@ -49,7 +49,7 @@
-
+