diff --git a/config/config.go b/config/config.go index 91505a3..71ddc89 100644 --- a/config/config.go +++ b/config/config.go @@ -7,6 +7,10 @@ import ( "github.com/spf13/viper" ) +const( + BROWSER_TIME_FORMAT = "2006-01-02T15:04" +) + var config *viper.Viper // Init is an exported method that takes the environment starts the viper diff --git a/controllers/index.go b/controllers/index.go index 90ca28d..766bf5c 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -4,7 +4,6 @@ import ( "net/http" "git.jamesravey.me/ravenscroftj/indiescrobble/models" - "git.jamesravey.me/ravenscroftj/indiescrobble/services/scrobble" "github.com/gin-gonic/gin" ) @@ -24,6 +23,21 @@ func Index(c *gin.Context) { c.HTML(http.StatusOK, "index.tmpl", gin.H{ "title": "test", "user": user, - "scrobbleTypes": scrobble.ScrobbleTypeNames, }) } + +func FAQ(c *gin.Context){ + currentUser, exists := c.Get("user") + + var user *models.BaseUser + + if exists { + user = currentUser.(*models.BaseUser) + }else{ + user = nil + } + + c.HTML(http.StatusOK, "faq.tmpl", gin.H{ + "user": user, + }) +} \ No newline at end of file diff --git a/controllers/posts.go b/controllers/posts.go new file mode 100644 index 0000000..c6b022f --- /dev/null +++ b/controllers/posts.go @@ -0,0 +1,3 @@ +package controllers + +/* Controllers concerning accessing user posts */ \ No newline at end of file diff --git a/controllers/scrobble.go b/controllers/scrobble.go index 5fcac3b..c575380 100644 --- a/controllers/scrobble.go +++ b/controllers/scrobble.go @@ -4,9 +4,10 @@ import ( "net/http" "time" + "git.jamesravey.me/ravenscroftj/indiescrobble/config" "git.jamesravey.me/ravenscroftj/indiescrobble/models" - "git.jamesravey.me/ravenscroftj/indiescrobble/services/scrobble" "git.jamesravey.me/ravenscroftj/indiescrobble/services/micropub" + "git.jamesravey.me/ravenscroftj/indiescrobble/services/scrobble" "github.com/gin-gonic/gin" "gorm.io/gorm" ) @@ -36,7 +37,20 @@ func (s *ScrobbleController) DoScrobble(c *gin.Context){ return } - s.scrobbler.Scrobble(&c.Request.Form, currentUser) + post, err := s.scrobbler.Scrobble(&c.Request.Form, currentUser) + + if err != nil{ + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ + "message": err, + }) + return + } + + c.HTML(http.StatusOK, "scrobble/done.tmpl", gin.H{ + "user": currentUser, + "scrobbleTypeName": scrobble.ScrobbleTypeNames[post.PostType], + "post": post, + }) } @@ -69,13 +83,13 @@ func (s *ScrobbleController) ScrobbleForm(c *gin.Context){ }) return }else{ - c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ + c.HTML(http.StatusOK, "scrobble/compose.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"), + "now": time.Now().Format(config.BROWSER_TIME_FORMAT), }) return } @@ -91,7 +105,7 @@ func (s *ScrobbleController) ScrobbleForm(c *gin.Context){ return } - c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ + c.HTML(http.StatusOK, "scrobble/search.tmpl", gin.H{ "user": currentUser, "scrobbleType": scrobbleType, "scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType], @@ -100,18 +114,25 @@ func (s *ScrobbleController) ScrobbleForm(c *gin.Context){ "searchResults": searchResults, "now": time.Now().Format("2006-01-02T15:04"), }) - }else{ - c.HTML(http.StatusOK, "scrobble.tmpl", gin.H{ + }else if scrobbleType := c.Request.Form.Get("type"); scrobbleType != "" { + c.HTML(http.StatusOK, "scrobble/search.tmpl", gin.H{ "user": currentUser, "scrobbleType": scrobbleType, "scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType], "scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType], "now": time.Now().Format("2006-01-02T15:04"), }) + }else{ + c.HTML(http.StatusOK, "scrobble/begin.tmpl", gin.H{ + "user": currentUser, + "scrobbleTypes": scrobble.ScrobbleTypeNames, + "now": time.Now().Format("2006-01-02T15:04"), + }) } } +/*Preview the content of a scrobble to be submitted to \*/ func (s *ScrobbleController) PreviewScrobble(c *gin.Context){ err := c.Request.ParseForm() @@ -125,21 +146,17 @@ func (s *ScrobbleController) PreviewScrobble(c *gin.Context){ }) } - scrobbleType := c.Request.Form.Get("type") + post, err := s.scrobbler.Preview(&c.Request.Form) - searchEngine := scrobble.NewSearchProvider(scrobbleType, s.db) - - itemID := c.Request.Form.Get("item") - - item, err := searchEngine.SearchProvider.GetItem(itemID) if err != nil{ c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ "message": err, }) - return } + scrobbleType := c.Request.Form.Get("type") + discovery := micropub.MicropubDiscoveryService{} config, err := discovery.Discover(currentUser.Me, currentUser.Token ) @@ -151,15 +168,23 @@ func (s *ScrobbleController) PreviewScrobble(c *gin.Context){ return } - c.HTML(http.StatusOK, "preview.tmpl", gin.H{ + postBody, err := s.scrobbler.BuildMicroPubPayload(post) + + if err != nil{ + c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{ + "message": err, + }) + return + } + + c.HTML(http.StatusOK, "scrobble/preview.tmpl", gin.H{ "user": currentUser, "scrobbleType": scrobbleType, "scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType], - "item": item, - "when": c.Request.Form.Get("when"), - "rating": c.Request.Form.Get("rating"), - "content": c.Request.Form.Get("content"), + "post": post, "config": config, + "summary": s.scrobbler.GenerateSummary(post), + "postBody": string(postBody), }) } \ No newline at end of file diff --git a/models/post.go b/models/post.go index f68d016..dbd7592 100644 --- a/models/post.go +++ b/models/post.go @@ -16,4 +16,5 @@ type Post struct { MediaItem MediaItem ScrobbledAt sql.NullTime Content sql.NullString + Rating sql.NullString } \ No newline at end of file diff --git a/server/router.go b/server/router.go index 4b85a13..0f86c7b 100644 --- a/server/router.go +++ b/server/router.go @@ -24,6 +24,7 @@ func NewRouter(db *gorm.DB) *gin.Engine { router.Use(middlewares.AuthMiddleware(false, iam)) router.GET("/", controllers.Index) + router.GET("/faqs", controllers.FAQ) router.Static("/static", config.GetString("server.static_path")) diff --git a/server/server.go b/server/server.go index 27b2159..b58a4c6 100644 --- a/server/server.go +++ b/server/server.go @@ -32,6 +32,6 @@ func Init() { db.AutoMigrate(&models.User{}, &models.Post{}, &models.MediaItem{}) r := NewRouter(db) - r.LoadHTMLGlob("templates/*.tmpl") + r.LoadHTMLGlob("templates/**/*.tmpl") r.Run(fmt.Sprintf("%v:%v", config.GetString("server.host"), config.GetString("server.port"))) } diff --git a/services/scrobble/scrobbler.go b/services/scrobble/scrobbler.go index a4d2e78..ed9cc7a 100644 --- a/services/scrobble/scrobbler.go +++ b/services/scrobble/scrobbler.go @@ -4,6 +4,7 @@ import ( "database/sql" "encoding/json" "fmt" + "log" "net/url" "time" @@ -67,7 +68,7 @@ func (s *Scrobbler) GetSearchEngineNameForType(scrobbleType string) string { return NewSearchProvider(scrobbleType, s.db).SearchProvider.GetName() } -func (s *Scrobbler) buildMicroPubPayload(post *models.Post) ([]byte, error) { +func (s *Scrobbler) BuildMicroPubPayload(post *models.Post) ([]byte, error) { postObj := make(map[string]interface{}) postObj["type"] = []string{"h-entry"} postObj["visibility"] = []string{"public"} @@ -82,7 +83,7 @@ func (s *Scrobbler) buildMicroPubPayload(post *models.Post) ([]byte, error) { 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) + properties["summary"] = []string{s.GenerateSummary(post)} citationProps := make(map[string]interface{}) @@ -105,7 +106,46 @@ func (s *Scrobbler) buildMicroPubPayload(post *models.Post) ([]byte, error) { postObj["properties"] = properties - return json.Marshal(postObj) + return json.MarshalIndent(postObj, ""," ") +} + +func (s *Scrobbler) GenerateSummary(post *models.Post) string{ + return fmt.Sprintf("%v %v %v and gave it %v/5", + ScrobbleTypeEmojis[post.PostType], + ScrobbleTypeVerbs[post.PostType], + post.MediaItem.DisplayName.String, + post.Rating.String) +} + +func (s *Scrobbler) Preview(form *url.Values) (*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 + } + + post := models.Post{ + MediaItem: item, + PostType: form.Get("type"), + Content: sql.NullString{String: form.Get("content"), Valid: true}, + Rating: sql.NullString{String: form.Get("rating"), Valid: true}, + } + + time, err := time.Parse(config.BROWSER_TIME_FORMAT, form.Get("when")) + + if err == nil{ + post.ScrobbledAt = sql.NullTime{Time: time, Valid: true} + }else{ + log.Printf("Failed to parse time %v because %v",form.Get("when"), err ) + } + + return &post, nil } func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*models.Post, error) { @@ -118,6 +158,7 @@ func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*m result := s.db.Where(&models.MediaItem{MediaID: form.Get("item")}).First(&item) if result.Error != nil{ + log.Printf("Error finding media item with ID %v in db: %v\n", form.Get("item"), result.Error) return nil, result.Error } @@ -138,28 +179,29 @@ func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*m 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 ) + log.Printf("Failed to parse time %v because %v",form.Get("when"), err ) } - postBody, err := s.buildMicroPubPayload(&post) + postBody, err := s.BuildMicroPubPayload(&post) - fmt.Printf("Post body: %v\n", string(postBody)) - if err != nil{ return nil, err } + log.Printf("Send post payload to %v\n", currentUser.Me) resp, err := discovery.SubmitMicropub(currentUser, postBody) if err != nil{ + log.Printf("Error creating user post: %v\n", err) return nil, err } loc, err := resp.Location() if err != nil{ + log.Printf("Error getting Location header from user micropub endpoint: %v\n", err) return nil, err } @@ -167,6 +209,7 @@ func (s *Scrobbler) Scrobble(form *url.Values, currentUser *models.BaseUser) (*m result = s.db.Create(&post) if result.Error != nil{ + log.Printf("Error creating post in database: %v\n", result.Error) return nil, result.Error } diff --git a/services/scrobble/types.go b/services/scrobble/types.go index 3034a8a..7953ab9 100644 --- a/services/scrobble/types.go +++ b/services/scrobble/types.go @@ -7,6 +7,13 @@ const( SCROBBLE_TYPE_READ = "read" ) +var ScrobbleTypeEmojis = map[string]string { + "scrobble" : "🎧", + "tv" : "πŸ“Ί", + "movie": "🎬", + "read": "πŸ“–", +}; + var ScrobbleTypeNames = map[string]string { "scrobble" : "🎧 Listen", "tv" : "πŸ“Ί TV Show", diff --git a/templates/error.tmpl b/templates/error.tmpl deleted file mode 100644 index c7e2bd2..0000000 --- a/templates/error.tmpl +++ /dev/null @@ -1,11 +0,0 @@ - - - {{ template "head.tmpl" . }} - - {{ template "header.tmpl" . }} -
-

Error

- {{ .message }} -
- - \ No newline at end of file diff --git a/templates/header.tmpl b/templates/header.tmpl deleted file mode 100644 index 24011e6..0000000 --- a/templates/header.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -{{ define "header.tmpl" }} -
-

- IndieScrobble -

-
-{{end}} \ No newline at end of file diff --git a/templates/pages/error.tmpl b/templates/pages/error.tmpl new file mode 100644 index 0000000..b310769 --- /dev/null +++ b/templates/pages/error.tmpl @@ -0,0 +1,13 @@ +{{ define "error.tmpl" }} + + + {{ template "partial/head.tmpl" . }} + + {{ template "partial/header.tmpl" . }} +
+

Error

+ {{ .message }} +
+ + +{{ end }} \ No newline at end of file diff --git a/templates/pages/faq.tmpl b/templates/pages/faq.tmpl new file mode 100644 index 0000000..21baae1 --- /dev/null +++ b/templates/pages/faq.tmpl @@ -0,0 +1,21 @@ +{{ define "faq.tmpl" }} + + + {{ template "partial/head.tmpl" . }} + + {{ template "partial/header.tmpl" . }} +
+ +

Welcome to indiescrobble! IndieScrobble is a MicroPub compliant tool + for posting about your watches, reads and scrobbles directly back to your site.

+ +

Is it copyright infringement to display movie/tv posters, book covers, album covers on my website?

+

I am not a lawyer however, it is my understanding that review is an example of "fair usage" of related promotional material + as per this legal thread

+ +
+ {{ template "partial/footer.tmpl" . }} + + +{{end}} + diff --git a/templates/pages/index.tmpl b/templates/pages/index.tmpl new file mode 100644 index 0000000..9beb1b6 --- /dev/null +++ b/templates/pages/index.tmpl @@ -0,0 +1,32 @@ +{{ define "index.tmpl" }} + + + {{ template "partial/head.tmpl" . }} + + {{ template "partial/header.tmpl" . }} +
+ +

Welcome to indiescrobble! IndieScrobble is a MicroPub compliant tool + for posting about your watches, reads and scrobbles directly back to your site.

+ {{ if .user }} + + + + {{else}} + +
+

+ + + +

+
+ {{ end }} +
+ {{ template "partial/footer.tmpl" . }} + + +{{end}} \ No newline at end of file diff --git a/templates/footer.tmpl b/templates/partial/footer.tmpl similarity index 78% rename from templates/footer.tmpl rename to templates/partial/footer.tmpl index 5164d3a..57fae02 100644 --- a/templates/footer.tmpl +++ b/templates/partial/footer.tmpl @@ -1,4 +1,4 @@ -{{ define "footer.tmpl" }} +{{ define "partial/footer.tmpl" }} diff --git a/templates/head.tmpl b/templates/partial/head.tmpl similarity index 81% rename from templates/head.tmpl rename to templates/partial/head.tmpl index c35cce1..80358c0 100644 --- a/templates/head.tmpl +++ b/templates/partial/head.tmpl @@ -1,4 +1,4 @@ -{{ define "head.tmpl" }} +{{ define "partial/head.tmpl" }} diff --git a/templates/partial/header.tmpl b/templates/partial/header.tmpl new file mode 100644 index 0000000..586ef24 --- /dev/null +++ b/templates/partial/header.tmpl @@ -0,0 +1,23 @@ +{{ define "partial/header.tmpl" }} +
+ + +

+ IndieScrobble +

+ {{ if .user.Me }} + Logged in as {{.user.Me}} + {{end}} + +
+{{end}} \ No newline at end of file diff --git a/templates/preview.tmpl b/templates/preview.tmpl deleted file mode 100644 index 2284bbc..0000000 --- a/templates/preview.tmpl +++ /dev/null @@ -1,65 +0,0 @@ -{{ define "preview.tmpl" }} - - - {{ template "head.tmpl" . }} - - {{ template "header.tmpl" . }} -
- - {{ $scrobbleType := .scrobbleType }} - - {{ if .user }} - Logged in as {{.user.Me}} - {{end}} - - -
- -

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

- -

Preview Post: {{.item.GetDisplayName}}

- -
- - {{if .item.GetThumbnailURL}} - - {{end}} - - -
- -
- -
- - {{.rating}}
- -
-
{{.content}}
- - - {{if .config.SyndicateTargets}} -

Syndication Options

- {{ range $target := .config.SyndicateTargets}} -
- {{end}} - {{end}} - -
- - -
- - - - -
- - - - -
- {{ template "footer.tmpl" . }} - - -{{end}} \ No newline at end of file diff --git a/templates/index.tmpl b/templates/scrobble/begin.tmpl similarity index 87% rename from templates/index.tmpl rename to templates/scrobble/begin.tmpl index 6b3f65a..da384d9 100644 --- a/templates/index.tmpl +++ b/templates/scrobble/begin.tmpl @@ -1,8 +1,9 @@ +{{ define "scrobble/begin.tmpl" }} - {{ template "head.tmpl" . }} + {{ template "partial/head.tmpl" . }} - {{ template "header.tmpl" . }} + {{ template "partial/header.tmpl" . }}
{{ if .user }} @@ -34,4 +35,5 @@
{{ template "footer.tmpl" . }} - \ No newline at end of file + +{{end}} \ No newline at end of file diff --git a/templates/scrobble/compose.tmpl b/templates/scrobble/compose.tmpl new file mode 100644 index 0000000..240d6ab --- /dev/null +++ b/templates/scrobble/compose.tmpl @@ -0,0 +1,47 @@ +{{ define "scrobble/compose.tmpl" }} + + + {{ template "partial/head.tmpl" . }} + + {{ template "partial/header.tmpl" . }} +
+ + {{ $scrobbleType := .scrobbleType }} + +
+ +

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

+ +

{{.item.GetDisplayName}}

+ +
+ + {{if .item.GetThumbnailURL}} + + {{end}} + + +
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + +
+ +
+ {{ template "partial/footer.tmpl" . }} + + +{{end}} \ No newline at end of file diff --git a/templates/scrobbled.tmpl b/templates/scrobble/done.tmpl similarity index 59% rename from templates/scrobbled.tmpl rename to templates/scrobble/done.tmpl index 260a40b..2c55c88 100644 --- a/templates/scrobbled.tmpl +++ b/templates/scrobble/done.tmpl @@ -1,24 +1,20 @@ -{{ define "scrobbled.tmpl" }} +{{ define "scrobble/done.tmpl" }} - {{ template "head.tmpl" . }} + {{ template "partial/head.tmpl" . }} - {{ template "header.tmpl" . }} + {{ template "partial/header.tmpl" . }}
{{ $scrobbleType := .scrobbleType }} - {{ if .user }} - Logged in as {{.user.Me}} - {{end}} -

Add A Post > Add {{ .scrobbleTypeName }} > {{.post.MediaItem.DisplayName.String}}

Post Complete: {{.post.URL}}

- {{ template "footer.tmpl" . }} + {{ template "partial/footer.tmpl" . }} {{end}} \ No newline at end of file diff --git a/templates/scrobble/preview.tmpl b/templates/scrobble/preview.tmpl new file mode 100644 index 0000000..0fec34f --- /dev/null +++ b/templates/scrobble/preview.tmpl @@ -0,0 +1,73 @@ +{{ define "scrobble/preview.tmpl" }} + + + {{ template "partial/head.tmpl" . }} + + {{ template "partial/header.tmpl" . }} +
+ + {{ $scrobbleType := .scrobbleType }} + + +
+ +

Add A Post > Add {{ .scrobbleTypeName }} > {{.post.MediaItem.DisplayName.String}}

+ +

Preview Post: {{.post.MediaItem.DisplayName.String}}

+ +

Summary

+

{{.summary}}

+ +

Thumbnail

+
+ + {{if .post.MediaItem.ThumbnailURL.Valid}} + + {{end}} + + +
+ +
+

Details

+
+ + {{.post.Rating.String}}
+ +
+
{{.post.Content.String}}
+ + + {{if .config.SyndicateTargets}} +

Syndication Options

+ {{ range $target := .config.SyndicateTargets}} +
+ {{end}} + {{end}} + +
+ + +
+ Micropub Payload Details +
{{.postBody}}
+
+ + + + + +
+ + + +
+ + + + +
+ {{ template "partial/footer.tmpl" . }} + + +{{end}} \ No newline at end of file diff --git a/templates/scrobble/search.tmpl b/templates/scrobble/search.tmpl new file mode 100644 index 0000000..19c499b --- /dev/null +++ b/templates/scrobble/search.tmpl @@ -0,0 +1,46 @@ +{{ define "scrobble/search.tmpl" }} + + + {{ template "partial/head.tmpl" . }} + + {{ template "partial/header.tmpl" . }} +
+ + {{ $scrobbleType := .scrobbleType }} + + + {{if .searchResults}} + +

Add A Post > Add {{ .scrobbleTypeName }} > {{.searchEngine}} Results

+ + + + {{ else }} +
+

Add A Post Add {{ .scrobbleTypeName }}

+ +

Search {{.searchEngine}} for items to scrobble

+ + + + + + +

+ + {{end}} +
+ {{ template "partial/footer.tmpl" . }} + + +{{end}} \ No newline at end of file