mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 07:46:05 -07:00
Basic search working for #32
This commit is contained in:
parent
f49e67da83
commit
1596dce629
7 changed files with 296 additions and 15 deletions
152
PlexRequests.Api.Models/Music/MusicBrainzSearchResults.cs
Normal file
152
PlexRequests.Api.Models/Music/MusicBrainzSearchResults.cs
Normal file
|
@ -0,0 +1,152 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: MusicBrainzSearchResults.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PlexRequests.Api.Models.Music
|
||||
{
|
||||
public class TextRepresentation
|
||||
{
|
||||
public string language { get; set; }
|
||||
public string script { get; set; }
|
||||
}
|
||||
|
||||
public class Alias
|
||||
{
|
||||
[JsonProperty(PropertyName = "sort-name")]
|
||||
public string SortName { get; set; }
|
||||
public string name { get; set; }
|
||||
public object locale { get; set; }
|
||||
public string type { get; set; }
|
||||
public object primary { get; set; }
|
||||
[JsonProperty(PropertyName = "begin-date")]
|
||||
public object BeginDate { get; set; }
|
||||
[JsonProperty(PropertyName = "end-date")]
|
||||
public object EndDate { get; set; }
|
||||
}
|
||||
|
||||
public class Artist
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string name { get; set; }
|
||||
[JsonProperty(PropertyName = "sort-date")]
|
||||
public string SortName { get; set; }
|
||||
public string disambiguation { get; set; }
|
||||
public List<Alias> aliases { get; set; }
|
||||
}
|
||||
|
||||
public class ArtistCredit
|
||||
{
|
||||
public Artist artist { get; set; }
|
||||
}
|
||||
|
||||
public class ReleaseGroup
|
||||
{
|
||||
public string id { get; set; }
|
||||
[JsonProperty(PropertyName = "primary-type")]
|
||||
public string PrimaryType { get; set; }
|
||||
[JsonProperty(PropertyName = "secondary-types")]
|
||||
public List<string> SecondaryTypes { get; set; }
|
||||
}
|
||||
|
||||
public class Area
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string name { get; set; }
|
||||
[JsonProperty(PropertyName = "sort-name")]
|
||||
public string SortName { get; set; }
|
||||
[JsonProperty(PropertyName = "iso-3166-1-codes")]
|
||||
public List<string> ISO31661Codes { get; set; }
|
||||
}
|
||||
|
||||
public class ReleaseEvent
|
||||
{
|
||||
public string date { get; set; }
|
||||
public Area area { get; set; }
|
||||
}
|
||||
|
||||
public class Label
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
public class LabelInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "catalog-number")]
|
||||
public string CatalogNumber { get; set; }
|
||||
public Label label { get; set; }
|
||||
}
|
||||
|
||||
public class Medium
|
||||
{
|
||||
public string format { get; set; }
|
||||
[JsonProperty(PropertyName = "disc-count")]
|
||||
public int DiscCount { get; set; }
|
||||
[JsonProperty(PropertyName = "catalog-number")]
|
||||
public int CatalogNumber { get; set; }
|
||||
}
|
||||
|
||||
public class Release
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string score { get; set; }
|
||||
public int count { get; set; }
|
||||
public string title { get; set; }
|
||||
public string status { get; set; }
|
||||
public string disambiguation { get; set; }
|
||||
public string packaging { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "text-representation")]
|
||||
public TextRepresentation TextRepresentation { get; set; }
|
||||
[JsonProperty(PropertyName = "artist-credit")]
|
||||
public List<ArtistCredit> ArtistCredit { get; set; }
|
||||
[JsonProperty(PropertyName = "release-group")]
|
||||
public ReleaseGroup ReleaseGroup { get; set; }
|
||||
public string date { get; set; }
|
||||
public string country { get; set; }
|
||||
[JsonProperty(PropertyName = "release-events")]
|
||||
public List<ReleaseEvent> ReleaseEvents { get; set; }
|
||||
public string barcode { get; set; }
|
||||
public string asin { get; set; }
|
||||
[JsonProperty(PropertyName = "label-info")]
|
||||
public List<LabelInfo> LabelInfo { get; set; }
|
||||
[JsonProperty(PropertyName = "track-count")]
|
||||
public int TrackCount { get; set; }
|
||||
public List<Medium> media { get; set; }
|
||||
}
|
||||
|
||||
public class MusicBrainzSearchResults
|
||||
{
|
||||
public string created { get; set; }
|
||||
public int count { get; set; }
|
||||
public int offset { get; set; }
|
||||
public List<Release> releases { get; set; }
|
||||
}
|
||||
|
||||
}
|
|
@ -50,6 +50,7 @@
|
|||
<Compile Include="Movie\CouchPotatoStatus.cs" />
|
||||
<Compile Include="Music\HeadphonesAlbumSearchResult.cs" />
|
||||
<Compile Include="Music\HeadphonesArtistSearchResult.cs" />
|
||||
<Compile Include="Music\MusicBrainzSearchResults.cs" />
|
||||
<Compile Include="Notifications\PushbulletPush.cs" />
|
||||
<Compile Include="Notifications\PushbulletResponse.cs" />
|
||||
<Compile Include="Notifications\PushoverResponse.cs" />
|
||||
|
|
70
PlexRequests.Api/MusicBrainzApi.cs
Normal file
70
PlexRequests.Api/MusicBrainzApi.cs
Normal file
|
@ -0,0 +1,70 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: MusicBrainzApi.cs
|
||||
// Created By: Jamie Rees
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ************************************************************************/
|
||||
#endregion
|
||||
using System;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using NLog;
|
||||
|
||||
using PlexRequests.Api.Models.Music;
|
||||
|
||||
using RestSharp;
|
||||
|
||||
namespace PlexRequests.Api
|
||||
{
|
||||
public class MusicBrainsApi
|
||||
{
|
||||
public MusicBrainsApi()
|
||||
{
|
||||
Api = new ApiRequest();
|
||||
}
|
||||
private ApiRequest Api { get; }
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private readonly Uri BaseUri = new Uri("http://musicbrainz.org/ws/2/");
|
||||
|
||||
public MusicBrainzSearchResults SearchAlbum(string searchTerm)
|
||||
{
|
||||
Log.Trace("Searching for album: {0}", searchTerm);
|
||||
var request = new RestRequest
|
||||
{
|
||||
Resource = "release/?query={searchTerm}&fmt=json",
|
||||
Method = Method.GET
|
||||
};
|
||||
request.AddUrlSegment("searchTerm", searchTerm);
|
||||
|
||||
try
|
||||
{
|
||||
return Api.ExecuteJson<MusicBrainzSearchResults>(request, BaseUri);
|
||||
}
|
||||
catch (JsonSerializationException jse)
|
||||
{
|
||||
Log.Warn(jse);
|
||||
return new MusicBrainzSearchResults(); // If there is no matching result we do not get returned a JSON string, it just returns "false".
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ApiRequest.cs" />
|
||||
<Compile Include="MusicBrainzApi.cs" />
|
||||
<Compile Include="MockApiData.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
|
|
|
@ -6,19 +6,22 @@
|
|||
});
|
||||
|
||||
var searchSource = $("#search-template").html();
|
||||
var musicSource = $("#music-template").html();
|
||||
var searchTemplate = Handlebars.compile(searchSource);
|
||||
var musicTemplate = Handlebars.compile(musicSource);
|
||||
var noResultsHtml = "<div class='no-search-results'>" +
|
||||
"<i class='fa fa-film no-search-results-icon'></i><div class='no-search-results-text'>Sorry, we didn't find any results!</div></div>";
|
||||
var movieTimer = 0;
|
||||
var tvimer = 0;
|
||||
var noResultsMusic = "<div class='no-search-results'>" +
|
||||
"<i class='fa fa-headphones no-search-results-icon'></i><div class='no-search-results-text'>Sorry, we didn't find any results!</div></div>";
|
||||
var searchTimer = 0;
|
||||
|
||||
// Type in movie search
|
||||
$("#movieSearchContent").on("input", function () {
|
||||
if (movieTimer) {
|
||||
clearTimeout(movieTimer);
|
||||
if (searchTimer) {
|
||||
clearTimeout(searchTimer);
|
||||
}
|
||||
$('#movieSearchButton').attr("class","fa fa-spinner fa-spin");
|
||||
movieTimer = setTimeout(movieSearch, 400);
|
||||
searchTimer = setTimeout(movieSearch, 400);
|
||||
|
||||
});
|
||||
|
||||
|
@ -34,11 +37,11 @@ $('#moviesInTheaters').on('click', function (e) {
|
|||
|
||||
// Type in TV search
|
||||
$("#tvSearchContent").on("input", function () {
|
||||
if (tvimer) {
|
||||
clearTimeout(tvimer);
|
||||
if (searchTimer) {
|
||||
clearTimeout(searchTimer);
|
||||
}
|
||||
$('#tvSearchButton').attr("class", "fa fa-spinner fa-spin");
|
||||
tvimer = setTimeout(tvSearch, 400);
|
||||
searchTimer = setTimeout(tvSearch, 400);
|
||||
});
|
||||
|
||||
// Click TV dropdown option
|
||||
|
@ -72,6 +75,16 @@ $(document).on("click", ".dropdownTv", function (e) {
|
|||
sendRequestAjax(data, type, url, buttonId);
|
||||
});
|
||||
|
||||
// Search Music
|
||||
$("#musicSearchContent").on("input", function () {
|
||||
if (searchTimer) {
|
||||
clearTimeout(searchTimer);
|
||||
}
|
||||
$('#musicSearchButton').attr("class", "fa fa-spinner fa-spin");
|
||||
searchTimer = setTimeout(musicSearch, 400);
|
||||
|
||||
});
|
||||
|
||||
// Click Request for movie
|
||||
$(document).on("click", ".requestMovie", function (e) {
|
||||
e.preventDefault();
|
||||
|
@ -133,7 +146,7 @@ function moviesComingSoon() {
|
|||
}
|
||||
|
||||
function moviesInTheaters() {
|
||||
getMovies("/search/movie/playing")
|
||||
getMovies("/search/movie/playing");
|
||||
}
|
||||
|
||||
function getMovies(url) {
|
||||
|
@ -179,6 +192,29 @@ function getTvShows(url) {
|
|||
});
|
||||
};
|
||||
|
||||
function musicSearch() {
|
||||
var query = $("#musicSearchContent").val();
|
||||
getMusic("/search/music/" + query);
|
||||
}
|
||||
|
||||
function getMusic(url) {
|
||||
$("#musicList").html("");
|
||||
|
||||
$.ajax(url).success(function (results) {
|
||||
if (results.count > 0) {
|
||||
results.releases.forEach(function (result) {
|
||||
var context = buildMusicContext(result);
|
||||
|
||||
var html = musicTemplate(context);
|
||||
$("#musicList").append(html);
|
||||
});
|
||||
}
|
||||
else {
|
||||
$("#musicList").html(noResultsMusic);
|
||||
}
|
||||
$('#musicSearchButton').attr("class", "fa fa-search");
|
||||
});
|
||||
};
|
||||
|
||||
function buildMovieContext(result) {
|
||||
var date = new Date(result.releaseDate);
|
||||
|
@ -212,3 +248,16 @@ function buildTvShowContext(result) {
|
|||
};
|
||||
return context;
|
||||
}
|
||||
|
||||
function buildMusicContext(result) {
|
||||
|
||||
var context = {
|
||||
id: result.id,
|
||||
title: result.title,
|
||||
overview: result.disambiguation,
|
||||
year: result.date,
|
||||
type: "music"
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace PlexRequests.UI.Modules
|
|||
|
||||
Get["movie/{searchTerm}"] = parameters => SearchMovie((string)parameters.searchTerm);
|
||||
Get["tv/{searchTerm}"] = parameters => SearchTvShow((string)parameters.searchTerm);
|
||||
Get["music/{searchTerm}"] = parameters => SearchMusic((string)parameters.searchTerm);
|
||||
|
||||
Get["movie/upcoming"] = parameters => UpcomingMovies();
|
||||
Get["movie/playing"] = parameters => CurrentlyPlayingMovies();
|
||||
|
@ -152,6 +153,13 @@ namespace PlexRequests.UI.Modules
|
|||
return Response.AsJson(model);
|
||||
}
|
||||
|
||||
private Response SearchMusic(string searchTerm)
|
||||
{
|
||||
var api = new MusicBrainsApi();
|
||||
var albums = api.SearchAlbum(searchTerm);
|
||||
return Response.AsJson(albums);
|
||||
}
|
||||
|
||||
private Response UpcomingMovies() // TODO : Not used
|
||||
{
|
||||
var movies = MovieApi.GetUpcomingMovies();
|
||||
|
@ -174,7 +182,7 @@ namespace PlexRequests.UI.Modules
|
|||
{
|
||||
var movieApi = new TheMovieDbApi();
|
||||
var movieInfo = movieApi.GetMovieInformation(movieId).Result;
|
||||
string fullMovieName = string.Format("{0}{1}", movieInfo.Title, movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty);
|
||||
var fullMovieName = $"{movieInfo.Title}{(movieInfo.ReleaseDate.HasValue ? $" ({movieInfo.ReleaseDate.Value.Year})" : string.Empty)}";
|
||||
Log.Trace("Getting movie info from TheMovieDb");
|
||||
Log.Trace(movieInfo.DumpJson);
|
||||
//#if !DEBUG
|
||||
|
@ -192,6 +200,7 @@ namespace PlexRequests.UI.Modules
|
|||
existingRequest.RequestedUsers.Add(Username);
|
||||
RequestService.UpdateRequest(existingRequest);
|
||||
}
|
||||
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = settings.UsersCanViewOnlyOwnRequests ? $"{fullMovieName} was successfully added!" : $"{fullMovieName} has already been requested!" });
|
||||
}
|
||||
|
||||
|
|
|
@ -161,17 +161,16 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
|
||||
<img class="img-responsive" src="http://image.tmdb.org/t/p/w150/{{posterPath}}" alt="poster">
|
||||
@*<img class="img-responsive" src="http://image.tmdb.org/t/p/w150/{{posterPath}}" alt="poster">*@
|
||||
|
||||
<img class="img-responsive" width="150" src="{{posterPath}}" alt="poster">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-5 ">
|
||||
<div>
|
||||
|
||||
<a href="http://www.imdb.com/title/{{imdb}}/" target="_blank">
|
||||
@*<a href="http://www.imdb.com/title/{{imdb}}/" target="_blank">*@
|
||||
<h4>{{title}} ({{year}})</h4>
|
||||
</a>
|
||||
@*</a>*@
|
||||
</div>
|
||||
<p>{{overview}}</p>
|
||||
</div>
|
||||
|
@ -179,7 +178,7 @@
|
|||
<form method="POST" action="/search/request/{{type}}" id="form{{id}}">
|
||||
<input name="{{type}}Id" type="text" value="{{id}}" hidden="hidden" />
|
||||
|
||||
<button id="{{id}}" style="text-align: right" class="btn btn-primary-outline requestMovie" type="submit"><i class="fa fa-plus"></i> Request</button>
|
||||
<button id="{{id}}" style="text-align: right" class="btn btn-primary-outline requestMusic" type="submit"><i class="fa fa-plus"></i> Request</button>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue