pull/1350/head^2
tidusjar 8 years ago
parent 9e004dc57b
commit 1c301f2c54

@ -0,0 +1,29 @@
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Ombi.Api
{
public class Api
{
public static JsonSerializerSettings Settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
public async Task<T> Get<T>(Uri uri)
{
var h = new HttpClient();
var response = await h.GetAsync(uri);
if (!response.IsSuccessStatusCode)
{
// Logging
}
var receiveString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(receiveString, Settings);
}
}
}

@ -0,0 +1,78 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: ApiHelper.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;
namespace Ombi.Api
{
public static class ApiHelper
{
public static Uri ChangePath(this Uri uri, string path, params string[] args)
{
var builder = new UriBuilder(uri);
if (args != null && args.Length > 0)
{
builder.Path = builder.Path + string.Format(path, args);
}
else
{
builder.Path += path;
}
return builder.Uri;
}
public static Uri ChangePath(this Uri uri, string path)
{
return ChangePath(uri, path, null);
}
public static Uri AddQueryParameter(this Uri uri, string parameter, string value)
{
if (string.IsNullOrEmpty(parameter) || string.IsNullOrEmpty(value)) return uri;
var builder = new UriBuilder(uri);
var startingTag = string.Empty;
var hasQuery = false;
if (string.IsNullOrEmpty(builder.Query))
{
startingTag = "?";
}
else
{
hasQuery = true;
startingTag = builder.Query.Contains("?") ? "&" : "?";
}
builder.Query = hasQuery
? $"{builder.Query}{startingTag}{parameter}={value}"
: $"{startingTag}{parameter}={value}";
return builder.Uri;
}
}
}

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
</ItemGroup>
</Project>

@ -0,0 +1,8 @@
using System;
namespace Ombi.Core
{
public class MovieProcessor
{
}
}

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
</Project>

@ -0,0 +1,33 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: IMovieDbApi.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
namespace Ombi.TheMovieDbApi
{
public interface IMovieDbApi
{
}
}

@ -0,0 +1,10 @@
namespace Ombi.TheMovieDbApi.Models
{
public class BelongsToCollection
{
public int id { get; set; }
public string name { get; set; }
public string poster_path { get; set; }
public string backdrop_path { get; set; }
}
}

@ -0,0 +1,8 @@
namespace Ombi.TheMovieDbApi.Models
{
public class Genre
{
public int id { get; set; }
public string name { get; set; }
}
}

@ -0,0 +1,58 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: MovieResponse.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
namespace Ombi.TheMovieDbApi.Models
{
public class MovieResponse
{
public bool adult { get; set; }
public string backdrop_path { get; set; }
public BelongsToCollection belongs_to_collection { get; set; }
public int budget { get; set; }
public Genre[] genres { get; set; }
public string homepage { get; set; }
public int id { get; set; }
public string imdb_id { get; set; }
public string original_language { get; set; }
public string original_title { get; set; }
public string overview { get; set; }
public float popularity { get; set; }
public string poster_path { get; set; }
public ProductionCompanies[] production_companies { get; set; }
public ProductionCountries[] production_countries { get; set; }
public string release_date { get; set; }
public int revenue { get; set; }
public int runtime { get; set; }
public SpokenLanguages[] spoken_languages { get; set; }
public string status { get; set; }
public string tagline { get; set; }
public string title { get; set; }
public bool video { get; set; }
public float vote_average { get; set; }
public int vote_count { get; set; }
}
}

@ -0,0 +1,8 @@
namespace Ombi.TheMovieDbApi.Models
{
public class ProductionCompanies
{
public string name { get; set; }
public int id { get; set; }
}
}

@ -0,0 +1,8 @@
namespace Ombi.TheMovieDbApi.Models
{
public class ProductionCountries
{
public string iso_3166_1 { get; set; }
public string name { get; set; }
}
}

@ -0,0 +1,46 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: SearchResult.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
namespace Ombi.TheMovieDbApi.Models
{
public class SearchResult
{
public string poster_path { get; set; }
public bool adult { get; set; }
public string overview { get; set; }
public string release_date { get; set; }
public int?[] genre_ids { get; set; }
public int id { get; set; }
public string original_title { get; set; }
public string original_language { get; set; }
public string title { get; set; }
public string backdrop_path { get; set; }
public float popularity { get; set; }
public int vote_count { get; set; }
public bool video { get; set; }
public float vote_average { get; set; }
}
}

@ -0,0 +1,8 @@
namespace Ombi.TheMovieDbApi.Models
{
public class SpokenLanguages
{
public string iso_639_1 { get; set; }
public string name { get; set; }
}
}

@ -0,0 +1,39 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: TheMovieDbContainer.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;
namespace Ombi.TheMovieDbApi.Models
{
public class TheMovieDbContainer<T>
{
public int page { get; set; }
public List<T> results { get; set; }
public int total_results { get; set; }
public int total_pages { get; set; }
}
}

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Api;
using Ombi.TheMovieDbApi.Models;
namespace Ombi.TheMovieDbApi
{
public class TheMovieDbApi
{
public TheMovieDbApi()
{
Api = new Api.Api();
}
private const string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00";
private static readonly Uri BaseUri = new Uri("https://api.themoviedb.org/3/");
public Api.Api Api { get; }
public async Task<MovieResponse> GetMovieInformation(int movieId)
{
var url = BaseUri.ChangePath("movie/{0}", movieId.ToString());
AddHeaders(url);
return await Api.Get<MovieResponse>(url);
}
public async Task<TheMovieDbContainer<SearchResult>> SearchMovie(string searchTerm)
{
var url = BaseUri.ChangePath("search/movie/");
url = AddHeaders(url);
url = url.AddQueryParameter("query", searchTerm);
return await Api.Get<TheMovieDbContainer<SearchResult>>(url);
}
private Uri AddHeaders(Uri url)
{
return url.AddQueryParameter("api_key", ApiToken);
}
}
}

@ -12,6 +12,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Build\publish.bat = Build\publish.bat Build\publish.bat = Build\publish.bat
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Core", "Ombi.Core\Ombi.Core.csproj", "{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{9293CA11-360A-4C20-A674-B9E794431BF5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.TheMovieDbApi", "Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj", "{132DA282-5894-4570-8916-D8C18ED2CE84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api", "Ombi.Api\Ombi.Api.csproj", "{EA31F915-31F9-4318-B521-1500CDF40DDF}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -22,8 +30,24 @@ Global
{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}.Debug|Any CPU.Build.0 = Debug|Any CPU {C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}.Release|Any CPU.ActiveCfg = Release|Any CPU {C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}.Release|Any CPU.Build.0 = Release|Any CPU {C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}.Release|Any CPU.Build.0 = Release|Any CPU
{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}.Release|Any CPU.Build.0 = Release|Any CPU
{132DA282-5894-4570-8916-D8C18ED2CE84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{132DA282-5894-4570-8916-D8C18ED2CE84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{132DA282-5894-4570-8916-D8C18ED2CE84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{132DA282-5894-4570-8916-D8C18ED2CE84}.Release|Any CPU.Build.0 = Release|Any CPU
{EA31F915-31F9-4318-B521-1500CDF40DDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA31F915-31F9-4318-B521-1500CDF40DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA31F915-31F9-4318-B521-1500CDF40DDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA31F915-31F9-4318-B521-1500CDF40DDF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{132DA282-5894-4570-8916-D8C18ED2CE84} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{EA31F915-31F9-4318-B521-1500CDF40DDF} = {9293CA11-360A-4C20-A674-B9E794431BF5}
EndGlobalSection
EndGlobal EndGlobal

@ -29,8 +29,8 @@ using Microsoft.AspNetCore.Mvc;
namespace Ombi.Controllers namespace Ombi.Controllers
{ {
[Route("api/[controller]")]
public class BaseApiController : Controller public class BaseApiController : Controller
{ {
overr
} }
} }

@ -3,15 +3,18 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Ombi.TheMovieDbApi.Models;
namespace Ombi.Controllers namespace Ombi.Controllers
{ {
public class SearchController : Controller public class SearchController : BaseApiController
{ {
[Route()] [HttpGet("movie/{searchTerm}")]
public IActionResult Index() public async Task<List<SearchResult>> SearchMovie(string searchTerm)
{ {
return View(); var api = new TheMovieDbApi.TheMovieDbApi();
var result = await api.SearchMovie(searchTerm);
return result.results;
} }

@ -19,4 +19,8 @@
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\**" /> <Folder Include="wwwroot\**" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj" />
</ItemGroup>
</Project> </Project>

@ -11,6 +11,8 @@ import { HttpModule } from '@angular/http';
import { SearchComponent } from './search/search.component'; import { SearchComponent } from './search/search.component';
import { PageNotFoundComponent } from './errors/not-found.component'; import { PageNotFoundComponent } from './errors/not-found.component';
// Services
import { SearchService } from './services/search.service';
import { ButtonModule } from 'primeng/primeng'; import { ButtonModule } from 'primeng/primeng';
import { MenubarModule } from 'primeng/components/menubar/menubar'; import { MenubarModule } from 'primeng/components/menubar/menubar';
@ -38,7 +40,7 @@ const routes: Routes = [
SearchComponent SearchComponent
], ],
providers: [ providers: [
//Services SearchService
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

@ -0,0 +1,16 @@
export interface IMovieResult {
poster_path: string,
adult: boolean,
overview: string,
release_date: string,
genre_ids: number[],
id: number,
original_title: string,
original_language: string,
title: string,
backdrop_path: string,
popularity: number,
vote_count: number,
video: boolean,
vote_average:number
}

@ -33,7 +33,7 @@
<!-- Movie tab --> <!-- Movie tab -->
<div role="tabpanel" class="tab-pane active" id="MoviesTab"> <div role="tabpanel" class="tab-pane active" id="MoviesTab">
<div class="input-group"> <div class="input-group">
<input id="movieSearchContent" [ngModel]="searchText" type="text" class="form-control form-control-custom form-control-search form-control-withbuttons"> <input id="movieSearchContent" type="text" class="form-control form-control-custom form-control-search form-control-withbuttons" (change)="search($event)">
<div class="input-group-addon"> <div class="input-group-addon">
<div class="btn-group"> <div class="btn-group">
<a href="#" class="btn btn-sm btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> <a href="#" class="btn btn-sm btn-primary-outline dropdown-toggle" data-toggle="dropdown" aria-expanded="false">

@ -1,14 +1,43 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/map';
import { SearchService } from '../services/search.service';
import { IMovieResult } from './interfaces/IMovieResult';
@Component({ @Component({
selector: 'ombi', selector: 'ombi',
moduleId: module.id, moduleId: module.id,
templateUrl: './search.component.html' templateUrl: './search.component.html',
providers: [SearchService]
}) })
export class SearchComponent implements OnInit{ export class SearchComponent implements OnInit {
searchText: string;
searchChanged: Subject<string> = new Subject<string>();
movieResults: IMovieResult[];
constructor(private searchService: SearchService) {
//this.searchChanged
// .debounceTime(300) // wait 300ms after the last event before emitting last event
// .distinctUntilChanged() // only emit if value is different from previous value
// .subscribe(x => {
// this.searchText = x as string;
//
// });
}
ngOnInit(): void { ngOnInit(): void {
this.searchText = ""; this.searchText = "";
this.movieResults = [];
}
search(text: any) {
//this.searchChanged.next(text);
this.searchService.searchMovie(text.target.value).subscribe(x => this.movieResults = x);
} }
searchText : string;
} }

@ -0,0 +1,16 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { ServiceHelpers } from './service.helpers';
import { IMovieResult } from '../search/interfaces/IMovieResult';
@Injectable()
export class SearchService {
constructor(private http: Http) {
}
searchMovie(searchTerm: string): Observable<IMovieResult[]> {
return this.http.get('/api/Search/Movie/' + searchTerm).map(ServiceHelpers.extractData);
}
}

@ -0,0 +1,15 @@
import { Headers, RequestOptions, Response } from '@angular/http';
export class ServiceHelpers {
public static Headers = new Headers({ 'Content-Type': 'application/json' });
public static RequestOptions = new RequestOptions({
headers: ServiceHelpers.Headers
});
public static extractData(res: Response) {
console.log(res);
return res.json();
}
}
Loading…
Cancel
Save