implemented scrobbling of movies
This commit is contained in:
parent
3b7d937df5
commit
781c003bad
|
@ -42,6 +42,8 @@ func NewRouter(db *gorm.DB) *gin.Engine {
|
|||
|
||||
authed.POST("/scrobble/preview", scrobbleController.PreviewScrobble)
|
||||
|
||||
authed.POST("/scrobble/do", scrobbleController.DoScrobble)
|
||||
|
||||
// v1 := router.Group("v1")
|
||||
// {
|
||||
// userGroup := v1.Group("user")
|
||||
|
|
|
@ -29,8 +29,7 @@ func Init() {
|
|||
log.Fatalf("%v\n", err)
|
||||
}
|
||||
|
||||
db.AutoMigrate(&models.User{})
|
||||
db.AutoMigrate(&models.Post{})
|
||||
db.AutoMigrate(&models.User{}, &models.Post{}, &models.MediaItem{})
|
||||
|
||||
r := NewRouter(db)
|
||||
r.LoadHTMLGlob("templates/*.tmpl")
|
||||
|
|
|
@ -159,64 +159,27 @@ func (m *MicropubDiscoveryService) Discover(me string, authToken string) (*Micro
|
|||
}
|
||||
|
||||
/* Send micropub to endpoint */
|
||||
func (m *MicropubDiscoveryService) SubmitScrobble(currentUser *models.BaseUser, post *models.Post) (error) {
|
||||
func (m *MicropubDiscoveryService) SubmitMicropub(currentUser *models.BaseUser, payload []byte) (*http.Response, error) {
|
||||
|
||||
endpoint, err := m.findMicropubEndpoint(currentUser.Me)
|
||||
|
||||
if err != nil{
|
||||
return err
|
||||
return nil, 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)
|
||||
body := bytes.NewReader(payload)
|
||||
|
||||
req, err := http.NewRequest("POST", endpoint, body)
|
||||
|
||||
if err != nil{
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Add("User-Agent", USER_AGENT_STRING)
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %v", currentUser.Token))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
return http.DefaultClient.Do(req)
|
||||
|
||||
if err != nil{
|
||||
return err
|
||||
}
|
||||
|
||||
loc, err := resp.Location()
|
||||
|
||||
if err != nil{
|
||||
return err
|
||||
}
|
||||
|
||||
post.URL = loc.String()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,9 +1,13 @@
|
|||
package scrobble
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"git.jamesravey.me/ravenscroftj/indiescrobble/config"
|
||||
"git.jamesravey.me/ravenscroftj/indiescrobble/models"
|
||||
"git.jamesravey.me/ravenscroftj/indiescrobble/services/micropub"
|
||||
"gorm.io/gorm"
|
||||
|
@ -21,7 +25,7 @@ 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 fmt.Errorf("unknown/invalid scrobble type %v", scrobbleType)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -63,6 +67,47 @@ func (s *Scrobbler) GetSearchEngineNameForType(scrobbleType string) string {
|
|||
return NewSearchProvider(scrobbleType, s.db).SearchProvider.GetName()
|
||||
}
|
||||
|
||||
func (s *Scrobbler) buildMicroPubPayload(post *models.Post) ([]byte, error) {
|
||||
postObj := make(map[string]interface{})
|
||||
postObj["type"] = []string{"h-entry"}
|
||||
postObj["visibility"] = []string{"public"}
|
||||
|
||||
properties := make(map[string]interface{})
|
||||
|
||||
if post.MediaItem.ThumbnailURL.Valid{
|
||||
properties["photo"] = []string{post.MediaItem.ThumbnailURL.String}
|
||||
}
|
||||
|
||||
if post.Rating.Valid{
|
||||
properties["rating"] = []string{post.Rating.String}
|
||||
}
|
||||
|
||||
properties["summary"] = fmt.Sprintf("%v %v and gave it %v/5", ScrobbleTypeVerbs[post.PostType], post.MediaItem.DisplayName.String, post.Rating.String)
|
||||
|
||||
|
||||
citationProps := make(map[string]interface{})
|
||||
citationProps["name"] = []string{post.MediaItem.DisplayName.String}
|
||||
citationProps["uid"] = []string{post.MediaItem.MediaID}
|
||||
citationProps["url"] = []string{post.MediaItem.CanonicalURL.String}
|
||||
citationProps["indiescrobble-id"] = post.MediaItem.ID
|
||||
|
||||
citation := make(map[string]interface{})
|
||||
citation["type"] = []string{"h-cite"}
|
||||
citation["properties"] = citationProps
|
||||
|
||||
// use the appropriate citation property e.g. read-of or watch-of
|
||||
properties[ScrobbleCitationProperties[post.PostType]] = citation
|
||||
|
||||
if post.Content.Valid{
|
||||
properties["content"] = []string{post.Content.String}
|
||||
}
|
||||
|
||||
postObj["properties"] = properties
|
||||
|
||||
|
||||
return json.Marshal(postObj)
|
||||
}
|
||||
|
||||
func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*models.Post, error) {
|
||||
|
||||
if err := s.ValidateType(form); err != nil{
|
||||
|
@ -79,12 +124,53 @@ func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*m
|
|||
discovery := micropub.MicropubDiscoveryService{}
|
||||
|
||||
|
||||
post := models.Post{
|
||||
MediaItem: item,
|
||||
User: *currentUser.UserRecord,
|
||||
PostType: form.Get("type"),
|
||||
Content: sql.NullString{String: form.Get("content"), Valid: true},
|
||||
Rating: sql.NullString{String: form.Get("rating"), Valid: true},
|
||||
}
|
||||
|
||||
mediaItem := models.MediaItem{}
|
||||
|
||||
post := models.Post{MediaItem: mediaItem, User: *currentUser.UserRecord, PostType: form.Get("type") }
|
||||
time, err := time.Parse(config.BROWSER_TIME_FORMAT, form.Get("when"))
|
||||
|
||||
discovery.SubmitScrobble(currentUser, &post)
|
||||
if err == nil{
|
||||
post.ScrobbledAt = sql.NullTime{Time: time, Valid: true}
|
||||
}else{
|
||||
fmt.Errorf("Failed to parse time %v because %v",form.Get("when"), err )
|
||||
}
|
||||
|
||||
postBody, err := s.buildMicroPubPayload(&post)
|
||||
|
||||
|
||||
fmt.Printf("Post body: %v\n", string(postBody))
|
||||
|
||||
if err != nil{
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
resp, err := discovery.SubmitMicropub(currentUser, postBody)
|
||||
|
||||
if err != nil{
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loc, err := resp.Location()
|
||||
|
||||
if err != nil{
|
||||
return nil, err
|
||||
}
|
||||
|
||||
post.URL = loc.String()
|
||||
result = s.db.Create(&post)
|
||||
|
||||
if result.Error != nil{
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,13 @@ var ScrobbleTypeNames = map[string]string {
|
|||
"read": "📖 Read",
|
||||
};
|
||||
|
||||
var ScrobbleTypeVerbs = map[string]string {
|
||||
"scrobble" : "listened to",
|
||||
"tv" : "watched",
|
||||
"movie": "watched",
|
||||
"read": "read",
|
||||
};
|
||||
|
||||
var ScrobblePlaceholders = map[string]string {
|
||||
"scrobble" : "Jump Van Halen",
|
||||
"tv" : "Schitt's Creek",
|
||||
|
@ -21,6 +28,13 @@ var ScrobblePlaceholders = map[string]string {
|
|||
"read": "Three Body Problem Cixin Liu",
|
||||
};
|
||||
|
||||
var ScrobbleCitationProperties = map[string]string {
|
||||
"scrobble" : "listen-of",
|
||||
"tv" : "watch-of",
|
||||
"movie": "watch-of",
|
||||
"read": "read-of",
|
||||
};
|
||||
|
||||
|
||||
type ScrobbleMetaRecord interface{
|
||||
GetID() string
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{{end}}
|
||||
|
||||
|
||||
<form method="POST" action="/scrobble/preview">
|
||||
<form method="POST" action="/scrobble/do">
|
||||
|
||||
<p><a href="/">Add A Post</a> > <a href="/scrobble?type={{ .scrobbleType }}">Add {{ .scrobbleTypeName }}</a> > {{.item.GetDisplayName}}</p>
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="item" value="{{.item.GetID}}"/>
|
||||
<input type="hidden" name="type" value="{{ .scrobbleType }}"/>
|
||||
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{{ define "scrobbled.tmpl" }}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{{ template "head.tmpl" . }}
|
||||
<body>
|
||||
{{ template "header.tmpl" . }}
|
||||
<main>
|
||||
|
||||
{{ $scrobbleType := .scrobbleType }}
|
||||
|
||||
{{ if .user }}
|
||||
Logged in as {{.user.Me}} <a href="/logout"><button>Log Out</button></a>
|
||||
{{end}}
|
||||
|
||||
|
||||
<p><a href="/">Add A Post</a> > <a href="/scrobble?type={{ .scrobbleType }}">Add {{ .scrobbleTypeName }}</a> > {{.post.MediaItem.DisplayName.String}}</p>
|
||||
|
||||
<h3>Post Complete: <a href="{{.post.URL}}">{{.post.URL}}</a></h3>
|
||||
|
||||
</main>
|
||||
{{ template "footer.tmpl" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
Loading…
Reference in New Issue