Skip to content

Commit

Permalink
Merge pull request #7 from tphoney/newer_version
Browse files Browse the repository at this point in the history
(feat) add newer version filter
  • Loading branch information
tphoney authored Apr 14, 2024
2 parents 03cfd87 + ed0a67a commit 1bb0ae3
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 26 deletions.
38 changes: 28 additions & 10 deletions amazon/amazon.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/url"
"regexp"
"strings"
"time"

"github.com/tphoney/plex-lookup/types"
"github.com/tphoney/plex-lookup/utils"
Expand All @@ -18,23 +19,32 @@ const (
amazonURL = "https://www.blu-ray.com/movies/search.php?keyword="
)

func ScrapeMovies(movieSearchResult *types.MovieSearchResults) (string, error) {
func ScrapeMovies(movieSearchResult *types.MovieSearchResults) (scrapedResults []types.SearchResult) {
var results []types.SearchResult
for _, searchResult := range movieSearchResult.SearchResults {
date, err := scrapeMovie(searchResult.URL)
if !searchResult.BestMatch {
results = append(results, searchResult)
continue
}
scrapedDate, err := scrapeMovie(searchResult.URL)
if err != nil {
fmt.Println("Error scraping movie:", err)
}
// compare dates
fmt.Printf("%s- Plex: %s, Amazon: %s\n", movieSearchResult.Title, movieSearchResult.PlexMovie.DateAdded, date)
searchResult.ReleaseDate = scrapedDate
if scrapedDate.After(movieSearchResult.DateAdded) {
searchResult.NewRelease = true
}
results = append(results, searchResult)
}
return "", nil
return results
}

func scrapeMovie(movieURL string) (date string, err error) {
func scrapeMovie(movieURL string) (date time.Time, err error) {
req, err := http.NewRequestWithContext(context.Background(), "GET", movieURL, bytes.NewBuffer([]byte{}))
if err != nil {
fmt.Println("Error creating request:", err)
return "", err
return time.Time{}, err
}

req.Header.Set("User-Agent",
Expand All @@ -44,29 +54,37 @@ func scrapeMovie(movieURL string) (date string, err error) {
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return "", err
return time.Time{}, err
}

defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return "", err
return time.Time{}, err
}
rawData := string(body)

date = findMovieDetails(rawData)
return date, nil
}

func findMovieDetails(response string) (releaseDate string) {
func findMovieDetails(response string) (releaseDate time.Time) {
r := regexp.MustCompile(`<a class="grey noline" alt=".*">(.*?)</a></span>`)

match := r.FindStringSubmatch(response)
if match != nil {
releaseDate = match[1]
stringDate := match[1]
var err error
releaseDate, err = time.Parse("Jan 02, 2006", stringDate)
if err != nil {
releaseDate = time.Time{}
}
} else {
releaseDate = time.Time{}
}

return releaseDate
}

Expand Down
7 changes: 4 additions & 3 deletions amazon/amazon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"testing"
"time"

"github.com/tphoney/plex-lookup/types"
)
Expand Down Expand Up @@ -48,8 +49,8 @@ func TestFindMovieDetails(t *testing.T) {
}

processed := findMovieDetails(string(rawdata))

if processed != "Oct 04, 2010" {
t.Errorf("Expected Oct 04, 2010, but got %s", processed)
expected := time.Date(2010, time.October, 4, 0, 0, 0, 0, time.UTC)
if processed.Compare(expected) != 0 {
t.Errorf("Expected %s, but got %s", expected, processed)
}
}
12 changes: 11 additions & 1 deletion plex/plex.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"time"

types "github.com/tphoney/plex-lookup/types"
)
Expand Down Expand Up @@ -242,8 +244,16 @@ func extractMovies(xmlString string) (movieList []types.PlexMovie) {
}

for i := range container.Video {
intTime, err := strconv.ParseInt(container.Video[i].AddedAt, 10, 64)
var parsedDate time.Time
if err != nil {
parsedDate = time.Time{}
} else {
parsedDate = time.Unix(intTime, 0)
}

movieList = append(movieList, types.PlexMovie{
Title: container.Video[i].Title, Year: container.Video[i].Year, DateAdded: container.Video[i].AddedAt})
Title: container.Video[i].Title, Year: container.Video[i].Year, DateAdded: parsedDate})
}
return movieList
}
41 changes: 41 additions & 0 deletions plex/plex_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package plex

import (
"os"
"testing"
"time"

types "github.com/tphoney/plex-lookup/types"
)

func TestFindMovieDetails(t *testing.T) {
rawdata, err := os.ReadFile("testdata/movies.xml")
if err != nil {
t.Errorf("Error reading testdata/movies.xml: %s", err)
}

processed := extractMovies(string(rawdata))
expected := []types.PlexMovie{
{
Title: "Chaos Theory",
Year: "2007",
DateAdded: time.Date(2023, time.January, 21, 15, 03, 10, 0, time.FixedZone("GMT", 0)),
},
}

if len(processed) != 3 {
t.Errorf("Expected 3 movies, but got %d", len(processed))
}

if processed[0].Title != expected[0].Title {
t.Errorf("Expected title %s, but got %s", expected[0].Title, processed[0].Title)
}

if processed[0].Year != expected[0].Year {
t.Errorf("Expected year %s, but got %s", expected[0].Year, processed[0].Year)
}

if processed[0].DateAdded.Compare(expected[0].DateAdded) != 0 {
t.Errorf("Expected date %s, but got %s", expected[0].DateAdded, processed[0].DateAdded)
}
}
43 changes: 43 additions & 0 deletions plex/testdata/movies.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="3" allowSync="1" art="/:/resources/movie-fanart.jpg" content="secondary" identifier="com.plexapp.plugins.library" librarySectionID="3" librarySectionTitle="Films" librarySectionUUID="16803efc-ef61-4648-bf6e-2909c09ebf5b" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1711645865" thumb="/:/resources/movie.png" title1="Films" title2="sd" viewGroup="movie">
<Video ratingKey="60830" key="/library/metadata/60830" guid="plex://movie/5d776cfc51dd69001fe3f2e3" studio="W.I.P." type="movie" title="Chaos Theory" contentRating="PG-13" summary="Frank Allen, a professional speaker who lectures on time management has a perfectly ordered and scheduled life, down to the minute. When his wife sets his clock forward 10 minutes as a joke, his day is thrown off. Deciding that his strictly ordered life has done him little good, he begins to make multiple choice index cards, choosing one at random and doing what is written on the card." rating="3.0" audienceRating="5.8" viewCount="1" lastViewedAt="1628768050" year="2007" tagline="This man will bring order to the universe...or not." thumb="/library/metadata/60830/thumb/1696026335" art="/library/metadata/60830/art/1696026335" duration="5244480" originallyAvailableAt="2007-10-26" addedAt="1674313390" updatedAt="1696026335" audienceRatingImage="rottentomatoes://image.rating.spilled" primaryExtraKey="/library/metadata/60838" ratingImage="rottentomatoes://image.rating.rotten">
<Media id="68612" duration="5244480" bitrate="1110" width="704" height="288" aspectRatio="2.35" audioChannels="2" audioCodec="ac3" videoCodec="mpeg4" videoResolution="sd" container="avi" videoFrameRate="24p" videoProfile="advanced simple">
<Part id="131819" key="/library/parts/131819/1296320862/file.avi" duration="5244480" file="/fourteena/Chaos Theory (2008)/Chaos Theory (2008).avi" size="733784064" container="avi" videoProfile="advanced simple" />
</Media>
<Genre tag="Comedy" />
<Genre tag="Drama" />
<Country tag="United States of America" />
<Director tag="Marcos Siega" />
<Writer tag="Daniel Taplitz" />
<Role tag="Ryan Reynolds" />
<Role tag="Emily Mortimer" />
<Role tag="Stuart Townsend" />
</Video>
<Video ratingKey="62982" key="/library/metadata/62982" guid="plex://movie/5d9f352ad74e670020021175" studio="Independent Pictures (II)" type="movie" title="Gummo" contentRating="gb/18" summary="Lonely residents of a tornado-stricken Ohio town wander the deserted landscape trying to fulfill their boring, nihilistic lives." rating="3.8" audienceRating="7.3" viewCount="1" lastViewedAt="1628768116" year="1997" tagline="Prepare to visit a town you&#39;d never want to call home." thumb="/library/metadata/62982/thumb/1696026480" art="/library/metadata/62982/art/1696026480" duration="5178595" originallyAvailableAt="1997-11-24" addedAt="1674313570" updatedAt="1696026480" audienceRatingImage="rottentomatoes://image.rating.upright" ratingImage="rottentomatoes://image.rating.rotten">
<Media id="73317" duration="5178595" bitrate="1119" width="640" height="352" aspectRatio="1.85" audioChannels="2" audioCodec="mp3" videoCodec="msmpeg4v3" videoResolution="sd" container="avi" videoFrameRate="24p">
<Part id="132094" key="/library/parts/132094/1296323449/file.avi" duration="5178595" file="/fourteena/Gummo (1997)/Gummo (1997).avi" size="732266496" container="avi" />
</Media>
<Genre tag="Drama" />
<Genre tag="Comedy" />
<Country tag="United States of America" />
<Director tag="Harmony Korine" />
<Writer tag="Harmony Korine" />
<Role tag="Jacob Reynolds" />
<Role tag="Nick Sutton" />
<Role tag="Linda Manz" />
</Video>
<Video ratingKey="63904" key="/library/metadata/63904" guid="plex://movie/5d776bf723d5a3001f515f5f" studio="GSP Studios" type="movie" title="Mad to Be Normal" contentRating="gb/15" summary="During the 1960s, a renegade Scottish psychiatrist courts controversy within his profession for his approach to the field, and for the unique community he creates for his patients to inhabit." rating="6.1" audienceRating="6.3" viewCount="1" lastViewedAt="1710441486" year="2017" thumb="/library/metadata/63904/thumb/1696026573" art="/library/metadata/63904/art/1696026573" duration="6329526" originallyAvailableAt="2017-04-06" addedAt="1676229015" updatedAt="1696026573" audienceRatingImage="rottentomatoes://image.rating.upright" primaryExtraKey="/library/metadata/63905" ratingImage="rottentomatoes://image.rating.ripe">
<Media id="78173" duration="6329526" bitrate="1888" width="720" height="304" aspectRatio="2.35" audioChannels="2" audioCodec="ac3" videoCodec="mpeg4" videoResolution="sd" container="avi" videoFrameRate="24p" videoProfile="advanced simple">
<Part id="132241" key="/library/parts/132241/1676227500/file.avi" duration="6329526" file="/toshix/Mad to Be Normal (2017)/Mad to Be Normal (2017).avi" size="1498359130" container="avi" videoProfile="advanced simple" />
</Media>
<Genre tag="Biography" />
<Genre tag="Drama" />
<Country tag="United Kingdom" />
<Director tag="Robert Mullan" />
<Writer tag="Robert Mullan" />
<Writer tag="Tracy Moreton" />
<Role tag="David Tennant" />
<Role tag="Elisabeth Moss" />
<Role tag="Michael Gambon" />
</Video>
</MediaContainer>
18 changes: 11 additions & 7 deletions types/types.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package types

import "time"

const (
DiskBluray = "Blu-ray"
DiskDVD = "DVD"
Expand All @@ -15,18 +17,20 @@ type MovieSearchResults struct {
}

type SearchResult struct {
FoundTitle string
UITitle string
BestMatch bool
URL string
Format string
Year string
FoundTitle string
UITitle string
BestMatch bool
URL string
Format string
Year string
ReleaseDate time.Time
NewRelease bool
}

type PlexMovie struct {
Title string
Year string
DateAdded string
DateAdded time.Time
}

type PlexLibrary struct {
Expand Down
11 changes: 8 additions & 3 deletions web/movies.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,16 @@ func processMoviesHTML(w http.ResponseWriter, r *http.Request) {
}
// if we are filtering by newer version, we need to search again
if newerVersion == stringTrue {
_, _ = amazon.ScrapeMovies(&searchResult)
scrapedResults := amazon.ScrapeMovies(&searchResult)
searchResult.SearchResults = scrapedResults
}
}
searchResults = append(searchResults, searchResult)
numberOfMoviesProcessed = i
}
jobRunning = false
fmt.Fprintf(w,
`<h2 class="container">Results</h2><table class="table-sortable">%s</tbody></table>
`<table class="table-sortable">%s</tbody></table>
<script>function getCellIndex(t){var a=t.parentNode,r=Array.from(a.parentNode.children).indexOf(a);let s=0;for(let e=0;e<a.cells.length;e++){var l=a.cells[e].colSpan;if(s+=l,0===r){if(e===t.cellIndex)return s-1}else if(!isNaN(parseInt(t.dataset.sortCol)))return parseInt(t.dataset.sortCol)}return s-1}let is_sorting_process_on=!1,delay=100;
function tablesort(e){if(is_sorting_process_on)return!1;is_sorting_process_on=!0;var t=e.currentTarget.closest("table"),a=getCellIndex(e.currentTarget),r=e.currentTarget.dataset.sort,s=t.querySelector("th[data-dir]"),s=(s&&s!==e.currentTarget&&delete s.dataset.dir,e.currentTarget.dataset.dir?"asc"===e.currentTarget.dataset.dir?"desc":"asc":e.currentTarget.dataset.sortDefault||"asc"),l=(e.currentTarget.dataset.dir=s,[]),o=t.querySelectorAll("tbody tr");let n,u,c,d,v;for(j=0,jj=o.length;j<jj;j++)for(n=o[j],l.push({tr:n,values:[]}),v=l[j],c=n.querySelectorAll("th, td"),i=0,ii=c.length;i<ii;i++)u=c[i],d=u.dataset.sortValue||u.innerText,"int"===r?d=parseInt(d):"float"===r?d=parseFloat(d):"date"===r&&(d=new Date(d)),v.values.push(d);l.sort("string"===r?"asc"===s?(e,t)=>(""+e.values[a]).localeCompare(t.values[a]):(e,t)=>-(""+e.values[a]).localeCompare(t.values[a]):"asc"===s?(e,t)=>isNaN(e.values[a])||isNaN(t.values[a])?isNaN(e.values[a])?isNaN(t.values[a])?0:-1:1:e.values[a]<t.values[a]?-1:e.values[a]>t.values[a]?1:0:(e,t)=>isNaN(e.values[a])||isNaN(t.values[a])?isNaN(e.values[a])?isNaN(t.values[a])?0:1:-1:e.values[a]<t.values[a]?1:e.values[a]>t.values[a]?-1:0);const N=document.createDocumentFragment();return l.forEach(e=>N.appendChild(e.tr)),t.querySelector("tbody").replaceChildren(N),setTimeout(()=>is_sorting_process_on=!1,delay),!0}Node.prototype.tsortable=function(){this.querySelectorAll("thead th[data-sort], thead td[data-sort]").forEach(e=>e.onclick=tablesort)};
</script><script>document.querySelector('.table-sortable').tsortable()</script>`,
Expand All @@ -107,8 +108,12 @@ func renderTable(movieCollection []types.MovieSearchResults) (tableRows string)
for _, result := range movie.SearchResults {
if result.BestMatch && (result.Format == types.DiskBluray || result.Format == types.Disk4K) {
tableRows += fmt.Sprintf(
`<a href=%q target="_blank">%v</a> `,
`<a href=%q target="_blank">%v`,
result.URL, result.UITitle)
if result.NewRelease {
tableRows += "(new)"
}
tableRows += " </a>"
}
}
tableRows += "</td>"
Expand Down
4 changes: 2 additions & 2 deletions web/movies.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ <h1 class="container">Movies</h1>
German audio
</label>
<label for="newerVersion">
<input type="checkbox" id="newerVersion" name="newerVersion" value="true" disabled="true">
Newer Version, release date is after when the movie was added to Plex
<input type="checkbox" id="newerVersion" name="newerVersion" value="true">
Newer Version. Disc release date > Plex added date. (slower search)
</label>
</fieldset>
<button type="submit">Submit</button>
Expand Down

0 comments on commit 1bb0ae3

Please sign in to comment.