Added duration and tags to videos

This commit is contained in:
hak8or 2018-02-28 18:33:40 -05:00
parent e140cae317
commit ccef5fee0c
7 changed files with 192 additions and 10 deletions

View File

@ -26,6 +26,12 @@ namespace YTManager.Controllers {
// Channel on youtube that owns this video
public string Channel;
// Duration of the video in seconds.
public int Seconds;
// What tags are relevant with this video.
public List<string> Tags;
// Populate this struct using a model video.
public Video_ForAPI(Models.Video video) {
Title = video.Title;
@ -33,6 +39,8 @@ namespace YTManager.Controllers {
ID = video.YoutubeID;
Thumbnail = video.ThumbnailURL;
Channel = video.Channel.Title;
Seconds = (int)video.Duration.TotalSeconds;
Tags = video.Tags?.Select(t => t.Name).ToList();
}
}
@ -50,9 +58,10 @@ namespace YTManager.Controllers {
public async Task<IActionResult> GetVideos() {
// Get all the relevant videos.
var vids = await db.Videos
.Include(v => v.Channel)
.OrderByDescending(i => i.AddedToYT)
.Take(max_per_query)
.Include(v => v.Channel)
.Include(v => v.Tags)
.ToListAsync();
// Convert them to what we will send out.
@ -69,10 +78,11 @@ namespace YTManager.Controllers {
public async Task<IActionResult> Get_Channel_Videos([FromRoute] string channelName) {
// Get all the relevant videos.
var vids = await db.Videos
.Include(v => v.Channel)
.Where(v => v.Channel.Title == channelName)
.OrderByDescending(i => i.AddedToYT)
.Take(max_per_query)
.Include(v => v.Channel)
.Include(v => v.Tags)
.ToListAsync();
// Convert them to what we will send out.

View File

@ -0,0 +1,116 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using System;
using YTManager;
namespace YTManager.Migrations
{
[DbContext(typeof(MediaDB))]
[Migration("20180228202611_added_vid_duration")]
partial class added_vid_duration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.0.1-rtm-125");
modelBuilder.Entity("YTManager.Models.Channel", b =>
{
b.Property<long>("PrimaryKey")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedtoDB");
b.Property<string>("Description")
.IsRequired();
b.Property<DateTime>("Refreshed");
b.Property<string>("ThumbnailURL")
.IsRequired();
b.Property<string>("Title")
.IsRequired();
b.Property<string>("YoutubeID")
.IsRequired();
b.HasKey("PrimaryKey");
b.ToTable("Channels");
});
modelBuilder.Entity("YTManager.Models.Tag", b =>
{
b.Property<long>("PrimaryKey")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.Property<long?>("VideoPrimaryKey");
b.HasKey("PrimaryKey");
b.HasIndex("VideoPrimaryKey");
b.ToTable("Tags");
});
modelBuilder.Entity("YTManager.Models.Video", b =>
{
b.Property<long>("PrimaryKey")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedToYT");
b.Property<DateTime>("AddedtoDB");
b.Property<long>("ChannelPrimaryKey");
b.Property<string>("Description")
.IsRequired();
b.Property<TimeSpan>("Duration");
b.Property<string>("ThumbnailURL")
.IsRequired();
b.Property<string>("Title")
.IsRequired();
b.Property<string>("YoutubeID")
.IsRequired();
b.HasKey("PrimaryKey");
b.HasIndex("ChannelPrimaryKey");
b.ToTable("Videos");
});
modelBuilder.Entity("YTManager.Models.Tag", b =>
{
b.HasOne("YTManager.Models.Video")
.WithMany("Tags")
.HasForeignKey("VideoPrimaryKey");
});
modelBuilder.Entity("YTManager.Models.Video", b =>
{
b.HasOne("YTManager.Models.Channel", "Channel")
.WithMany("Videos")
.HasForeignKey("ChannelPrimaryKey")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace YTManager.Migrations
{
public partial class added_vid_duration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<TimeSpan>(
name: "Duration",
table: "Videos",
nullable: false,
defaultValue: "00:00:00");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Duration",
table: "Videos");
}
}
}

View File

@ -77,6 +77,8 @@ namespace YTManager.Migrations
b.Property<string>("Description")
.IsRequired();
b.Property<TimeSpan>("Duration");
b.Property<string>("ThumbnailURL")
.IsRequired();

View File

@ -32,6 +32,10 @@ namespace YTManager.Models {
[Required]
public DateTime AddedtoDB { get; set; }
// How long the video is
[Required]
public TimeSpan Duration { get; set; }
// What channel this video comes from.
[Required]
public Channel Channel { get; set; }

View File

@ -20,7 +20,7 @@
"commandName": "Project",
"launchUrl": "api/values",
"environmentVariables": {
"POSTGRESQL_DBSTR": "Server=192.168.1.211;Port=32768;Database=postgres;User Id=postgres;",
"POSTGRESQL_DBSTR": "Server=192.168.1.2;Port=32768;Database=postgres;User Id=postgres;",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:62214/"

View File

@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore;
namespace YTManager.Tasks {
public class FetchVideos {
// Get a bunch of videos from youtube that the channel generated.
private static async Task<List<Models.Video>> Get_YTVideos(string channelID) {
public static async Task<List<Models.Video>> Get_YTVideos(string channelID, int max = 50) {
// YT API access key
var youtubeService = new YouTubeService(new Google.Apis.Services.BaseClientService.Initializer()
{
@ -16,15 +16,18 @@ namespace YTManager.Tasks {
ApplicationName = "testingapppp"
});
// Max cannot be larger than 50, so clamp it.
max = max > 50 ? 50 : max;
// Search youtube for all the relevant data of the channel.
var query = youtubeService.Search.List("snippet");
query.ChannelId = channelID;
query.Order = SearchResource.ListRequest.OrderEnum.Date;
query.MaxResults = 50;
var response = await query.ExecuteAsync();
var videos_query = youtubeService.Search.List("snippet");
videos_query.ChannelId = channelID;
videos_query.Order = SearchResource.ListRequest.OrderEnum.Date;
videos_query.MaxResults = max;
var videos_response = await videos_query.ExecuteAsync();
// Convert the response into models.
return response.Items?
var videos = videos_response.Items?
.Where(i => i.Id.Kind == "youtube#video")
.Select(newvid => new Models.Video
{
@ -35,6 +38,28 @@ namespace YTManager.Tasks {
AddedtoDB = DateTime.Now,
ThumbnailURL = newvid.Snippet.Thumbnails.Medium.Url
}).ToList();
// Search youtube to get the length and tags for each video.
var duration_query = youtubeService.Videos.List("contentDetails,snippet");
duration_query.Id = string.Join(',', videos.Select(v => v.YoutubeID));
var duration_response = await duration_query.ExecuteAsync();
// Pair each video with the result.
foreach(var contentdetail in duration_response.Items.Where(i => i.Kind == "youtube#video")){
var vid = videos.Single(v => v.YoutubeID == contentdetail.Id);
// Yes, really, ISO8601 time span => c#'s TimeSpan is not in TimeSpan, it's in xmlconvert! Wtf?!
vid.Duration = System.Xml.XmlConvert.ToTimeSpan(contentdetail.ContentDetails.Duration);
// Copy over all the created tags if any tags were provided.
if (contentdetail.Snippet.Tags == null)
vid.Tags = new List<Models.Tag>();
else
vid.Tags = contentdetail.Snippet.Tags.Select(t => new Models.Tag { Name = t }).ToList();
}
// Send back the parsed vids.
return videos;
}
// Gets some info about a youtube channel.