implement pulling data from IMDB and caching
This commit is contained in:
parent
cdda8b2119
commit
b9498c66f7
|
@ -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
4
go.mod
|
@ -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
8
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -40,7 +40,6 @@ func NewRouter() *gin.Engine {
|
|||
|
||||
|
||||
|
||||
|
||||
// v1 := router.Group("v1")
|
||||
// {
|
||||
// userGroup := v1.Group("user")
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
.thumbnail{
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
.float-right{
|
||||
float: right;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: left;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.clear-both {
|
||||
clear: both;
|
||||
}
|
|
@ -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}}
|
|
@ -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 > Add {{ .scrobbleType }}</h2>
|
||||
|
||||
|
||||
<form method="GET" action="/scrobble">
|
||||
|
||||
{{if .searchResults}}
|
||||
|
||||
<p><a href="/">Add A Post</a> > <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> > {{.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> > <a href="/scrobble?type=movie">Add {{ .scrobbleTypeName }}</a> > {{.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 > ></button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{{ 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 >></button>
|
||||
|
||||
{{end}}
|
||||
|
||||
<input type="hidden" name="type" value="{{.scrobbleType}}"/>
|
||||
</form>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
Loading…
Reference in New Issue