Skip to content

Commit

Permalink
Implemented deleting non-existing YouTube videos worker task
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayIT committed Sep 7, 2018
1 parent c476823 commit fffa0e4
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 18 deletions.
137 changes: 137 additions & 0 deletions research/YouTube/SongQueryResultExample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/cc8LgDS2hbwSNWMuUs5HbzmLrU8\"",
"eventId": null,
"items": [
{
"ageGating": null,
"contentDetails": {
"caption": "false",
"contentRating": null,
"countryRestriction": null,
"definition": "sd",
"dimension": "2d",
"duration": "PT8M10S",
"hasCustomThumbnail": null,
"licensedContent": true,
"projection": "rectangular",
"regionRestriction": null,
"ETag": null
},
"etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/4kozuWKvk4OF11WJLNKFA-kNhHQ\"",
"fileDetails": null,
"id": "gOMhN-hfMtY",
"kind": "youtube#video",
"liveStreamingDetails": null,
"localizations": null,
"monetizationDetails": null,
"player": {
"embedHeight": null,
"embedHtml": "<iframe width=\"480\" height=\"270\" src=\"//www.youtube.com/embed/gOMhN-hfMtY\" frameborder=\"0\" allow=\"autoplay; encrypted-media\" allowfullscreen></iframe>",
"embedWidth": null,
"ETag": null
},
"processingDetails": null,
"projectDetails": null,
"recordingDetails": null,
"snippet": {
"categoryId": "10",
"channelId": "UC20vb-R_px4CguHzzBPhoyQ",
"channelTitle": "EminemVEVO",
"defaultAudioLanguage": "en-US",
"defaultLanguage": null,
"description": "Music video by Eminem performing Stan. YouTube view counts pre-VEVO: 3,965,564. (C) 2002 Aftermath Entertainment/Interscope Records",
"liveBroadcastContent": "none",
"localized": {
"description": "Music video by Eminem performing Stan. YouTube view counts pre-VEVO: 3,965,564. (C) 2002 Aftermath Entertainment/Interscope Records",
"title": "Eminem - Stan (Long Version) ft. Dido",
"ETag": null
},
"publishedAt": "2009-12-25T06:54:41.000Z",
"tags": [
"Eminem",
"Aftermath",
"Pop"
],
"thumbnails": {
"default": {
"height": 90,
"url": "https://i.ytimg.com/vi/gOMhN-hfMtY/default.jpg",
"width": 120,
"ETag": null
},
"high": {
"height": 360,
"url": "https://i.ytimg.com/vi/gOMhN-hfMtY/hqdefault.jpg",
"width": 480,
"ETag": null
},
"maxres": {
"height": 720,
"url": "https://i.ytimg.com/vi/gOMhN-hfMtY/maxresdefault.jpg",
"width": 1280,
"ETag": null
},
"medium": {
"height": 180,
"url": "https://i.ytimg.com/vi/gOMhN-hfMtY/mqdefault.jpg",
"width": 320,
"ETag": null
},
"standard": {
"height": 480,
"url": "https://i.ytimg.com/vi/gOMhN-hfMtY/sddefault.jpg",
"width": 640,
"ETag": null
},
"ETag": null
},
"title": "Eminem - Stan (Long Version) ft. Dido",
"ETag": null
},
"statistics": {
"commentCount": 87044,
"dislikeCount": 46908,
"favoriteCount": 0,
"likeCount": 1156974,
"viewCount": 206912088,
"ETag": null
},
"status": {
"embeddable": true,
"failureReason": null,
"license": "youtube",
"privacyStatus": "public",
"publicStatsViewable": true,
"publishAt": null,
"rejectionReason": null,
"uploadStatus": "processed",
"ETag": null
},
"suggestions": null,
"topicDetails": {
"relevantTopicIds": [
"/m/0glt670",
"/m/04rlf",
"/m/04rlf",
"/m/0glt670"
],
"topicCategories": [
"https://en.wikipedia.org/wiki/Hip_hop_music",
"https://en.wikipedia.org/wiki/Music"
],
"topicIds": null,
"ETag": null
}
}
],
"kind": "youtube#videoListResponse",
"nextPageToken": null,
"pageInfo": {
"resultsPerPage": 1,
"totalResults": 1,
"ETag": null
},
"prevPageToken": null,
"tokenPagination": null,
"visitorId": null
}
2 changes: 2 additions & 0 deletions src/MusicX.Common/GlobalConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{
public static class GlobalConstants
{
public const string ApplicationName = "MusicX";

public const string AdministratorRoleName = "Administrator";

public const string JsonContentType = "application/json";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.35.1.1226" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta009" PrivateAssets="all">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
Expand Down
36 changes: 36 additions & 0 deletions src/Services/MusicX.Services.DataProviders/YouTubeDataProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace MusicX.Services.DataProviders
{
using System;
using System.Threading.Tasks;

using Google.Apis.Services;
using Google.Apis.YouTube.v3;

using MusicX.Common;

public class YouTubeDataProvider
{
// TODO: Extract to config or DB. The API key is limited by IP so its OK to be publicly visible.
private const string ApiKey = "AIzaSyACdUSMzCxCknVFZoJPAenh6nakrGj1eug";

public async Task<bool> CheckIfVideoExists(string youtubeId)
{
var youtubeService = new YouTubeService(
new BaseClientService.Initializer
{
ApiKey = ApiKey, ApplicationName = GlobalConstants.ApplicationName, GZipEnabled = true,
});

var searchVideoRequest = youtubeService.Videos.List("snippet");
searchVideoRequest.Id = youtubeId;
var result = await searchVideoRequest.ExecuteAsync();
return result.Items.Count != 0;
}
}
}

// Queryable data for video: snippet,contentDetails,player,recordingDetails,statistics,status,topicDetails

//// var searchListRequest = youtubeService.Search.List("snippet");
//// searchListRequest.Q = "Google"; // Replace with your search term.
//// searchListRequest.MaxResults = 50;
24 changes: 8 additions & 16 deletions src/Tests/Sandbox/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

using CommandLine;

using Google.Apis.Services;
using Google.Apis.YouTube.v3;

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
Expand All @@ -25,6 +28,7 @@
using MusicX.Services.Data.WorkerTasks;
using MusicX.Services.DataProviders;
using MusicX.Worker.Common;
using MusicX.Worker.Tasks;

using Newtonsoft.Json;

Expand Down Expand Up @@ -65,24 +69,12 @@ private static int SandboxCode(SandboxOptions options, IServiceProvider serviceP
var sw = Stopwatch.StartNew();

var songsRepository = serviceProvider.GetService<IDeletableEntityRepository<Song>>();
var songMetadataRepository = serviceProvider.GetService<IDeletableEntityRepository<SongMetadata>>();
var songsService = serviceProvider.GetService<ISongsService>();
var metadataService = serviceProvider.GetService<ISongMetadataService>();
var provider = new Top40ChartsDataProvider();
var splitter = new SongNameSplitter();

var songIds = songsRepository.All().Select(x => x.Id).ToList();
for (var index = 0; index < songIds.Count; index++)
{
var songId = songIds[index];
songsService.UpdateSongsSystemData(songId).GetAwaiter().GetResult();
Console.WriteLine($"System data updated for: {songId}");

// For better performance
if (index % 100 == 0)
{
songsRepository.DetachAll();
}
}
var youTubeDataProvider = new YouTubeDataProvider();

Console.WriteLine(sw.Elapsed);
return 0;
Expand Down Expand Up @@ -144,7 +136,7 @@ private static int RunTask(RunTaskOptions options, IServiceProvider serviceProvi
{
var typeName = $"MusicX.Worker.Tasks.{options.TaskName}";

var type = typeof(BaseTask).Assembly.GetType(typeName);
var type = typeof(DbCleanupTask).Assembly.GetType(typeName);
try
{
if (!(Activator.CreateInstance(type, serviceProvider) is BaseTask task))
Expand All @@ -154,7 +146,7 @@ private static int RunTask(RunTaskOptions options, IServiceProvider serviceProvi
}

var sw = Stopwatch.StartNew();
task.DoWork(options.Parameters);
task.DoWork(options.Parameters).GetAwaiter().GetResult();
Console.WriteLine($"Time elapsed: {sw.Elapsed}");
}
catch (Exception ex)
Expand Down
7 changes: 5 additions & 2 deletions src/Web/MusicX.Web.Client/Pages/Songs/SongsList.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
{
<p><em>Loading...</em></p>
}
else if (!this.response.Data.Songs.Any())
{
<p><em>No songs found.</em></p>
}
else
{
foreach (var song in this.response.Data.Songs)
Expand Down Expand Up @@ -43,12 +47,11 @@ else
}

@functions {

[Parameter]
private int PageNumber { get; set; } = 1;

[Parameter]
private string SearchTerms { get; set; } = null;
private string SearchTerms { get; set; } = string.Empty;

ApiResponse<SongsListResponseModel> response;

Expand Down
84 changes: 84 additions & 0 deletions src/Worker/MusicX.Worker.Tasks/CheckForDeletedVideosTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
namespace MusicX.Worker.Tasks
{
using System;
using System.Linq;
using System.Threading.Tasks;

using Microsoft.Extensions.DependencyInjection;

using MusicX.Common.Models;
using MusicX.Data.Common.Repositories;
using MusicX.Data.Models;
using MusicX.Services.DataProviders;
using MusicX.Worker.Common;

public class CheckForDeletedVideosTask : BaseTask
{
private readonly IDeletableEntityRepository<SongMetadata> songMetadataRepository;

private readonly YouTubeDataProvider youTubeDataProvider;

public CheckForDeletedVideosTask(IServiceProvider serviceProvider)
: base(serviceProvider)
{
this.songMetadataRepository = serviceProvider.GetService<IDeletableEntityRepository<SongMetadata>>();
this.youTubeDataProvider = new YouTubeDataProvider();
}

public override Task<string> DoWork(string parameters)
{
return this.DoWork<Input, Output>(parameters, this.DoWork);
}

public override WorkerTask Recreate(WorkerTask currentTask)
{
var runAfter = (currentTask.RunAfter ?? DateTime.UtcNow).AddDays(7).Date.AddHours(20); // 20:00 after 7 days

var workerTask = new WorkerTask
{
TypeName = currentTask.TypeName,
Parameters = currentTask.Parameters,
Priority = currentTask.Priority,
RunAfter = runAfter,
};
return workerTask;
}

private async Task<Output> DoWork(Input input)
{
try
{
var youtubeIds = this.songMetadataRepository.All().Where(x => x.Type == SongMetadataType.YouTubeVideoId).ToList();
foreach (var songMetadata in youtubeIds)
{
Console.Write($"Checking video for song #{songMetadata.SongId} ({songMetadata.Value}) => ");
if (!await this.youTubeDataProvider.CheckIfVideoExists(songMetadata.Value))
{
this.songMetadataRepository.Delete(songMetadata);
await this.songMetadataRepository.SaveChangesAsync();
Console.WriteLine("DELETED");
}
else
{
Console.WriteLine("OK");
}
}

return new Output { Success = true };
}
catch (Exception e)
{
Console.WriteLine(e);
return new Output { Success = false, Exception = e.ToString() };
}
}

public class Input
{
}

public class Output : BaseTaskOutput
{
}
}
}
1 change: 1 addition & 0 deletions src/Worker/MusicX.Worker.Tasks/MusicX.Worker.Tasks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

<ItemGroup>
<ProjectReference Include="..\..\Data\MusicX.Data.Models\MusicX.Data.Models.csproj" />
<ProjectReference Include="..\..\Services\MusicX.Services.DataProviders\MusicX.Services.DataProviders.csproj" />
<ProjectReference Include="..\..\Services\MusicX.Services.Data\MusicX.Services.Data.csproj" />
<ProjectReference Include="..\MusicX.Worker.Common\MusicX.Worker.Common.csproj" />
</ItemGroup>
Expand Down

0 comments on commit fffa0e4

Please sign in to comment.