implement pulling data from IMDB and caching

This commit is contained in:
James Ravenscroft 2022-02-05 21:52:46 +00:00
parent cdda8b2119
commit b9498c66f7
10 changed files with 261 additions and 6 deletions

View File

@ -21,9 +21,44 @@ func Scrobble(c *gin.Context){
// TODO: add validation of type
scrobbleType := c.Request.Form.Get("type")
searchEngine := scrobble.NewSearchProvider(scrobbleType)
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 = searchEngine.SearchProvider.GetItem(itemID)
if err != nil{
c.HTML(http.StatusBadRequest, "error.tmpl", gin.H{
"message": err,
})
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": c.GetString("user"),
"scrobbleType": scrobble.ScrobbleTypeNames[scrobbleType],
"scrobbleType": scrobbleType,
"scrobblePlaceholder": scrobble.ScrobblePlaceholders[scrobbleType],
"scrobbleTypeName": scrobble.ScrobbleTypeNames[scrobbleType],
"searchEngine": searchEngine.SearchProvider.GetName(),
"searchResults": searchResults,
"item": item,
})
}

4
go.mod
View File

@ -4,6 +4,7 @@ go 1.17
require (
github.com/0xAX/notificator v0.0.0-20210731104411-c42e3d4a43ee // indirect
github.com/StalkR/imdb v1.0.7 // indirect
github.com/codegangsta/envy v0.0.0-20141216192214-4b78388c8ce4 // indirect
github.com/codegangsta/gin v0.0.0-20211113050330-71f90109db02 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
@ -17,6 +18,8 @@ require (
github.com/go-playground/validator/v10 v10.10.0 // indirect
github.com/goccy/go-json v0.9.4 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.0 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hacdias/indieauth v1.7.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@ -34,6 +37,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect

8
go.sum
View File

@ -40,6 +40,9 @@ github.com/0xAX/notificator v0.0.0-20210731104411-c42e3d4a43ee h1:LgokYDTCpaZBHt
github.com/0xAX/notificator v0.0.0-20210731104411-c42e3d4a43ee/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/StalkR/httpcache v1.0.0/go.mod h1:yvbaYwH6w1USHPqgspMSwumbLwWE+B7jIZgfLYkTw1M=
github.com/StalkR/imdb v1.0.7 h1:T9ra3IObhWoNB2I2CNT6EFe8sTQH56adKJdEQi1q0Ig=
github.com/StalkR/imdb v1.0.7/go.mod h1:nxQmP4/nGtTVICl2+UmwhCnosVwVClmksdyptjE5Lj8=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@ -121,6 +124,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -152,6 +156,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hacdias/indieauth v1.7.1 h1:gIIVrUozSTbTEOpqSYs884y37UWeFnVwX3KVT3sm/94=
github.com/hacdias/indieauth v1.7.1/go.mod h1:NHpFIYe4d5vl+hZY+16XsneVmD6usNcZdrSIpP5blqM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -207,6 +213,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

76
scrobble/imdb.go Normal file
View File

@ -0,0 +1,76 @@
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
}

23
scrobble/meta.go Normal file
View File

@ -0,0 +1,23 @@
package scrobble
type MetaSearchProvider struct{
ScrobbleType string
SearchProvider ScrobbleMetaProvider
}
func NewSearchProvider(scrobbleType string) *MetaSearchProvider{
provider := &MetaSearchProvider{ScrobbleType: scrobbleType}
if scrobbleType == SCROBBLE_TYPE_MOVIE {
provider.SearchProvider = NewIMDBProvider()
}
return provider
}
func (m *MetaSearchProvider) search(query string) {
}

View File

@ -1,8 +1,37 @@
package scrobble
const(
SCROBBLE_TYPE_LISTEN = "listen"
SCROBBLE_TYPE_TV = "tv"
SCROBBLE_TYPE_MOVIE = "movie"
SCROBBLE_TYPE_READ = "read"
)
var ScrobbleTypeNames = map[string]string {
"scrobble" : "🎧 Listen",
"tv" : "📺 TV Show",
"movie": "🎬 Movie",
"read": "📖 Read",
};
};
var ScrobblePlaceholders = map[string]string {
"scrobble" : "Jump Van Halen",
"tv" : "Schitt's Creek",
"movie": "Ferris Bueller's Day Off",
"read": "Three Body Problem Cixin Liu",
};
type ScrobbleMetaRecord interface{
GetID() string
GetDisplayName() string
GetCanonicalURL() string
GetThumbnailURL() string
}
type ScrobbleMetaProvider interface{
GetName() string
Search(query string) ([]ScrobbleMetaRecord, error)
GetItem(id string) (ScrobbleMetaRecord, error)
}

View File

@ -40,7 +40,6 @@ func NewRouter() *gin.Engine {
// v1 := router.Group("v1")
// {
// userGroup := v1.Group("user")

View File

@ -0,0 +1,17 @@
.thumbnail{
max-width: 256px;
}
.float-right{
float: right;
display: inline;
}
.float-right {
float: left;
display: inline;
}
.clear-both {
clear: both;
}

View File

@ -1,6 +1,7 @@
{{ define "head.tmpl" }}
<head>
<link rel="stylesheet" href="/static/css/simple-v1.css" />
<link rel="stylesheet" href="/static/css/indiescrobble.css" />
<title>IndieScrobble</title>
</head>
{{end}}

View File

@ -1,3 +1,4 @@
{{ define "scrobble.tmpl" }}
<!DOCTYPE html>
<html lang="en">
{{ template "head.tmpl" . }}
@ -5,17 +6,79 @@
{{ template "header.tmpl" . }}
<main>
{{ $scrobbleType := .scrobbleType }}
{{ if .user }}
Logged in as {{.user}} <a href="/logout"><button>Log Out</button></a>
{{end}}
<h2>Add A Post &gt; Add {{ .scrobbleType }}</h2>
<form method="GET" action="/scrobble">
{{if .searchResults}}
<p><a href="/">Add A Post</a> &gt; <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> &gt; {{.searchEngine}} Results</p>
<ul>
{{ $scrobbleType := .scrobbleType }}
{{range $result := .searchResults}}
<li>
<a href="/scrobble?type={{$scrobbleType}}&item={{$result.GetID}}">{{$result.GetDisplayName}}</a>
<a href="{{$result.GetCanonicalURL}}" target="_blank">(🔍more info)</a>
</li>
{{end}}
</ul>
{{ else if .item}}
<p><a href="/">Add A Post</a> &gt; <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> &gt; {{.item.GetDisplayName}}</p>
<h3>{{.item.GetDisplayName}}</h3>
<div class="float-left">
{{if .item.GetThumbnailURL}}
<img class="thumbnail" src="{{.item.GetThumbnailURL}}"/>
{{end}}
</div>
<div>
<label>When: </label> <input type="datetime-local" name='datetime'/><br/>
<label>Rating: (out of 5)</label> <input type="number" name='datetime'/><br/>
<label>Note/Content: </label> <br>
<textarea rows="6" name='content'></textarea>
<br/>
<button type="submit">Preview &gt; &gt;</button>
</div>
<button type="submit">Next &gt;&gt;</button>
{{ else }}
<h2><a href="/">Add A Post</a> Add {{ .scrobbleTypeName }}</h2>
<p>Search <b>{{.searchEngine}}</b> for items to scrobble<p>
<input type="text" name="q" placeholder="{{.scrobblePlaceholder}}">
<button type="submit">Next &gt;&gt;</button>
{{end}}
<input type="hidden" name="type" value="{{.scrobbleType}}"/>
</form>
</main>
</body>
</html>
</html>
{{end}}