mirror of
https://github.com/fergalmoran/podnoms.git
synced 2025-12-22 09:18:08 +00:00
YouTube working, Mixcloud is a cunt
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
<div class="block-content">
|
<div class="block-content">
|
||||||
<button class="btn btn-primary" (click)="processOrphans()">Process Orphans</button>
|
<button class="btn btn-primary" (click)="processOrphans()">Process Orphans</button>
|
||||||
<button class="btn btn-primary" (click)="processPlaylists()">Process Playlists</button>
|
<button class="btn btn-primary" (click)="processPlaylists()">Process Playlists</button>
|
||||||
|
<button class="btn btn-primary" (click)="processPlaylistItems()">Process Playlist Items</button>
|
||||||
<button class="btn btn-primary" (click)="updateYouTubeDl()">Update Youtube Downloader</button>
|
<button class="btn btn-primary" (click)="updateYouTubeDl()">Update Youtube Downloader</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ export class DebugComponent implements OnInit {
|
|||||||
console.log('debug.component.ts', 'processPlaylists', e)
|
console.log('debug.component.ts', 'processPlaylists', e)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
processPlaylistItems() {
|
||||||
|
this._jobsService
|
||||||
|
.processPlaylistItems()
|
||||||
|
.subscribe((e) =>
|
||||||
|
console.log('debug.component.ts', 'processPlaylists', e)
|
||||||
|
);
|
||||||
|
}
|
||||||
updateYouTubeDl() {
|
updateYouTubeDl() {
|
||||||
this._jobsService
|
this._jobsService
|
||||||
.updateYouTubeDl()
|
.updateYouTubeDl()
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ export class JobsService {
|
|||||||
environment.API_HOST + '/job/processplaylists'
|
environment.API_HOST + '/job/processplaylists'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
processPlaylistItems(): Observable<Response> {
|
||||||
|
return this._http.get<Response>(
|
||||||
|
environment.API_HOST + '/job/processplaylistitems'
|
||||||
|
);
|
||||||
|
}
|
||||||
updateYouTubeDl(): Observable<Response> {
|
updateYouTubeDl(): Observable<Response> {
|
||||||
return this._http.get<Response>(
|
return this._http.get<Response>(
|
||||||
environment.API_HOST + '/job/updateyoutubedl'
|
environment.API_HOST + '/job/updateyoutubedl'
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@@ -32,6 +33,7 @@ namespace PodNoms.Api.Controllers {
|
|||||||
private readonly IUnitOfWork _unitOfWork;
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private readonly IUrlProcessService _processor;
|
private readonly IUrlProcessService _processor;
|
||||||
|
private readonly IHostingEnvironment _hostingEnvironment;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly AudioFileStorageSettings _audioFileStorageSettings;
|
private readonly AudioFileStorageSettings _audioFileStorageSettings;
|
||||||
private readonly StorageSettings _storageSettings;
|
private readonly StorageSettings _storageSettings;
|
||||||
@@ -43,6 +45,7 @@ namespace PodNoms.Api.Controllers {
|
|||||||
IConfiguration options,
|
IConfiguration options,
|
||||||
IUrlProcessService processor, ILoggerFactory logger,
|
IUrlProcessService processor, ILoggerFactory logger,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
|
IHostingEnvironment hostingEnvironment,
|
||||||
IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) {
|
IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) {
|
||||||
this._logger = logger.CreateLogger<EntryController>();
|
this._logger = logger.CreateLogger<EntryController>();
|
||||||
this._podcastRepository = podcastRepository;
|
this._podcastRepository = podcastRepository;
|
||||||
@@ -53,6 +56,7 @@ namespace PodNoms.Api.Controllers {
|
|||||||
this._audioFileStorageSettings = audioFileStorageSettings.Value;
|
this._audioFileStorageSettings = audioFileStorageSettings.Value;
|
||||||
this._mapper = mapper;
|
this._mapper = mapper;
|
||||||
this._processor = processor;
|
this._processor = processor;
|
||||||
|
this._hostingEnvironment = hostingEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _processEntry(PodcastEntry entry) {
|
private void _processEntry(PodcastEntry entry) {
|
||||||
@@ -111,7 +115,7 @@ namespace PodNoms.Api.Controllers {
|
|||||||
var result = _mapper.Map<PodcastEntry, PodcastEntryViewModel>(entry);
|
var result = _mapper.Map<PodcastEntry, PodcastEntryViewModel>(entry);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} else if (status == AudioType.Playlist) {
|
} else if (status == AudioType.Playlist && _hostingEnvironment.IsDevelopment()) {
|
||||||
entry.ProcessingStatus = ProcessingStatus.Deferred;
|
entry.ProcessingStatus = ProcessingStatus.Deferred;
|
||||||
return Accepted(entry);
|
return Accepted(entry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ namespace PodNoms.Api.Controllers {
|
|||||||
var infoJobId = BackgroundJob.Enqueue<ProcessPlaylistsJob>(service => service.Execute());
|
var infoJobId = BackgroundJob.Enqueue<ProcessPlaylistsJob>(service => service.Execute());
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
[HttpGet("processplaylistitems")]
|
||||||
|
public IActionResult ProcessPlaylistItems() {
|
||||||
|
var infoJobId = BackgroundJob.Enqueue<ProcessPlaylistItemJob>(service => service.Execute());
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
[HttpGet("updateyoutubedl")]
|
[HttpGet("updateyoutubedl")]
|
||||||
public IActionResult UpdateYouTubeDl() {
|
public IActionResult UpdateYouTubeDl() {
|
||||||
var infoJobId = BackgroundJob.Enqueue<UpdateYouTubeDlJob>(service => service.Execute());
|
var infoJobId = BackgroundJob.Enqueue<UpdateYouTubeDlJob>(service => service.Execute());
|
||||||
|
|||||||
390
server/Migrations/20180507153433_ParsedPlaylistVideos.Designer.cs
generated
Normal file
390
server/Migrations/20180507153433_ParsedPlaylistVideos.Designer.cs
generated
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using PodNoms.Api.Persistence;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(PodnomsDbContext))]
|
||||||
|
[Migration("20180507153433_ParsedPlaylistVideos")]
|
||||||
|
partial class ParsedPlaylistVideos
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.0-preview2-30571")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistVideo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<bool>("IsProcessed");
|
||||||
|
|
||||||
|
b.Property<int>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.Property<string>("VideoId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("ParsedPlaylistVideos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<int>("PodcastId");
|
||||||
|
|
||||||
|
b.Property<string>("SourceUrl");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PodcastId");
|
||||||
|
|
||||||
|
b.ToTable("Playlists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("AppUserId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Slug");
|
||||||
|
|
||||||
|
b.Property<string>("TemporaryImageUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AppUserId");
|
||||||
|
|
||||||
|
b.ToTable("Podcasts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("AudioFileSize");
|
||||||
|
|
||||||
|
b.Property<float>("AudioLength");
|
||||||
|
|
||||||
|
b.Property<string>("AudioUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Author");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl");
|
||||||
|
|
||||||
|
b.Property<int?>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<int>("PodcastId");
|
||||||
|
|
||||||
|
b.Property<bool>("Processed");
|
||||||
|
|
||||||
|
b.Property<string>("ProcessingPayload");
|
||||||
|
|
||||||
|
b.Property<int>("ProcessingStatus");
|
||||||
|
|
||||||
|
b.Property<string>("SourceUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.HasIndex("PodcastId");
|
||||||
|
|
||||||
|
b.ToTable("PodcastEntries");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<long?>("FacebookId");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName");
|
||||||
|
|
||||||
|
b.Property<string>("LastName");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("PictureUrl");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<string>("Slug");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistVideo", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist", "Playlist")
|
||||||
|
.WithMany("ParsedPlaylistVideos")
|
||||||
|
.HasForeignKey("PlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PodcastId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "AppUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AppUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist")
|
||||||
|
.WithMany("PodcastEntries")
|
||||||
|
.HasForeignKey("PlaylistId");
|
||||||
|
|
||||||
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
.WithMany("PodcastEntries")
|
||||||
|
.HasForeignKey("PodcastId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
server/Migrations/20180507153433_ParsedPlaylistVideos.cs
Normal file
75
server/Migrations/20180507153433_ParsedPlaylistVideos.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Migrations
|
||||||
|
{
|
||||||
|
public partial class ParsedPlaylistVideos : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "CreateDate",
|
||||||
|
table: "Podcasts",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldDefaultValueSql: "getdate()");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "CreateDate",
|
||||||
|
table: "PodcastEntries",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldDefaultValueSql: "getdate()");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ParsedPlaylistVideos",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
CreateDate = table.Column<DateTime>(nullable: false),
|
||||||
|
UpdateDate = table.Column<DateTime>(nullable: false),
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
VideoId = table.Column<string>(nullable: true),
|
||||||
|
IsProcessed = table.Column<bool>(nullable: false),
|
||||||
|
PlaylistId = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ParsedPlaylistVideos", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ParsedPlaylistVideos_Playlists_PlaylistId",
|
||||||
|
column: x => x.PlaylistId,
|
||||||
|
principalTable: "Playlists",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ParsedPlaylistVideos_PlaylistId",
|
||||||
|
table: "ParsedPlaylistVideos",
|
||||||
|
column: "PlaylistId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ParsedPlaylistVideos");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "CreateDate",
|
||||||
|
table: "Podcasts",
|
||||||
|
nullable: false,
|
||||||
|
defaultValueSql: "getdate()",
|
||||||
|
oldClrType: typeof(DateTime));
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "CreateDate",
|
||||||
|
table: "PodcastEntries",
|
||||||
|
nullable: false,
|
||||||
|
defaultValueSql: "getdate()",
|
||||||
|
oldClrType: typeof(DateTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
390
server/Migrations/20180507155436_Rename_ParsedPlaylistVideos.Designer.cs
generated
Normal file
390
server/Migrations/20180507155436_Rename_ParsedPlaylistVideos.Designer.cs
generated
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using PodNoms.Api.Persistence;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(PodnomsDbContext))]
|
||||||
|
[Migration("20180507155436_Rename_ParsedPlaylistVideos")]
|
||||||
|
partial class Rename_ParsedPlaylistVideos
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.0-preview2-30571")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<bool>("IsProcessed");
|
||||||
|
|
||||||
|
b.Property<int>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.Property<string>("VideoId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("ParsedPlaylistItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<int>("PodcastId");
|
||||||
|
|
||||||
|
b.Property<string>("SourceUrl");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PodcastId");
|
||||||
|
|
||||||
|
b.ToTable("Playlists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("AppUserId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Slug");
|
||||||
|
|
||||||
|
b.Property<string>("TemporaryImageUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AppUserId");
|
||||||
|
|
||||||
|
b.ToTable("Podcasts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("AudioFileSize");
|
||||||
|
|
||||||
|
b.Property<float>("AudioLength");
|
||||||
|
|
||||||
|
b.Property<string>("AudioUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Author");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl");
|
||||||
|
|
||||||
|
b.Property<int?>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<int>("PodcastId");
|
||||||
|
|
||||||
|
b.Property<bool>("Processed");
|
||||||
|
|
||||||
|
b.Property<string>("ProcessingPayload");
|
||||||
|
|
||||||
|
b.Property<int>("ProcessingStatus");
|
||||||
|
|
||||||
|
b.Property<string>("SourceUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.HasIndex("PodcastId");
|
||||||
|
|
||||||
|
b.ToTable("PodcastEntries");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<long?>("FacebookId");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName");
|
||||||
|
|
||||||
|
b.Property<string>("LastName");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("PictureUrl");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<string>("Slug");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist", "Playlist")
|
||||||
|
.WithMany("ParsedPlaylistItems")
|
||||||
|
.HasForeignKey("PlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PodcastId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "AppUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AppUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist")
|
||||||
|
.WithMany("PodcastEntries")
|
||||||
|
.HasForeignKey("PlaylistId");
|
||||||
|
|
||||||
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
.WithMany("PodcastEntries")
|
||||||
|
.HasForeignKey("PodcastId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Migrations
|
||||||
|
{
|
||||||
|
public partial class Rename_ParsedPlaylistVideos : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ParsedPlaylistVideos");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ParsedPlaylistItems",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
CreateDate = table.Column<DateTime>(nullable: false),
|
||||||
|
UpdateDate = table.Column<DateTime>(nullable: false),
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
VideoId = table.Column<string>(nullable: true),
|
||||||
|
IsProcessed = table.Column<bool>(nullable: false),
|
||||||
|
PlaylistId = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ParsedPlaylistItems", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ParsedPlaylistItems_Playlists_PlaylistId",
|
||||||
|
column: x => x.PlaylistId,
|
||||||
|
principalTable: "Playlists",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ParsedPlaylistItems_PlaylistId",
|
||||||
|
table: "ParsedPlaylistItems",
|
||||||
|
column: "PlaylistId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ParsedPlaylistItems");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ParsedPlaylistVideos",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||||
|
CreateDate = table.Column<DateTime>(nullable: false),
|
||||||
|
IsProcessed = table.Column<bool>(nullable: false),
|
||||||
|
PlaylistId = table.Column<int>(nullable: false),
|
||||||
|
UpdateDate = table.Column<DateTime>(nullable: false),
|
||||||
|
VideoId = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ParsedPlaylistVideos", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ParsedPlaylistVideos_Playlists_PlaylistId",
|
||||||
|
column: x => x.PlaylistId,
|
||||||
|
principalTable: "Playlists",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ParsedPlaylistVideos_PlaylistId",
|
||||||
|
table: "ParsedPlaylistVideos",
|
||||||
|
column: "PlaylistId");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
392
server/Migrations/20180507162159_AddVideoTypeToPlaylistItem.Designer.cs
generated
Normal file
392
server/Migrations/20180507162159_AddVideoTypeToPlaylistItem.Designer.cs
generated
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using PodNoms.Api.Persistence;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(PodnomsDbContext))]
|
||||||
|
[Migration("20180507162159_AddVideoTypeToPlaylistItem")]
|
||||||
|
partial class AddVideoTypeToPlaylistItem
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.0-preview2-30571")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<bool>("IsProcessed");
|
||||||
|
|
||||||
|
b.Property<int>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.Property<string>("VideoId");
|
||||||
|
|
||||||
|
b.Property<string>("VideoType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("ParsedPlaylistItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<int>("PodcastId");
|
||||||
|
|
||||||
|
b.Property<string>("SourceUrl");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PodcastId");
|
||||||
|
|
||||||
|
b.ToTable("Playlists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("AppUserId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("Slug");
|
||||||
|
|
||||||
|
b.Property<string>("TemporaryImageUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AppUserId");
|
||||||
|
|
||||||
|
b.ToTable("Podcasts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<long>("AudioFileSize");
|
||||||
|
|
||||||
|
b.Property<float>("AudioLength");
|
||||||
|
|
||||||
|
b.Property<string>("AudioUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Author");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl");
|
||||||
|
|
||||||
|
b.Property<int?>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<int>("PodcastId");
|
||||||
|
|
||||||
|
b.Property<bool>("Processed");
|
||||||
|
|
||||||
|
b.Property<string>("ProcessingPayload");
|
||||||
|
|
||||||
|
b.Property<int>("ProcessingStatus");
|
||||||
|
|
||||||
|
b.Property<string>("SourceUrl");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Uid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.HasIndex("PodcastId");
|
||||||
|
|
||||||
|
b.ToTable("PodcastEntries");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<long?>("FacebookId");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName");
|
||||||
|
|
||||||
|
b.Property<string>("LastName");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("PictureUrl");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<string>("Slug");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist", "Playlist")
|
||||||
|
.WithMany("ParsedPlaylistItems")
|
||||||
|
.HasForeignKey("PlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PodcastId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "AppUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AppUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist")
|
||||||
|
.WithMany("PodcastEntries")
|
||||||
|
.HasForeignKey("PlaylistId");
|
||||||
|
|
||||||
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
.WithMany("PodcastEntries")
|
||||||
|
.HasForeignKey("PodcastId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddVideoTypeToPlaylistItem : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "VideoType",
|
||||||
|
table: "ParsedPlaylistItems",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "VideoType",
|
||||||
|
table: "ParsedPlaylistItems");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -127,6 +127,30 @@ namespace PodNoms.Api.Migrations
|
|||||||
b.ToTable("AspNetUserTokens");
|
b.ToTable("AspNetUserTokens");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateDate");
|
||||||
|
|
||||||
|
b.Property<bool>("IsProcessed");
|
||||||
|
|
||||||
|
b.Property<int>("PlaylistId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdateDate");
|
||||||
|
|
||||||
|
b.Property<string>("VideoId");
|
||||||
|
|
||||||
|
b.Property<string>("VideoType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlaylistId");
|
||||||
|
|
||||||
|
b.ToTable("ParsedPlaylistItems");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -154,14 +178,11 @@ namespace PodNoms.Api.Migrations
|
|||||||
|
|
||||||
b.Property<string>("AppUserId");
|
b.Property<string>("AppUserId");
|
||||||
|
|
||||||
b.Property<DateTime>("CreateDate")
|
b.Property<DateTime>("CreateDate");
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValueSql("getdate()");
|
|
||||||
|
|
||||||
b.Property<string>("Description");
|
b.Property<string>("Description");
|
||||||
|
|
||||||
b.Property<string>("Slug")
|
b.Property<string>("Slug");
|
||||||
.IsUnicode(true);
|
|
||||||
|
|
||||||
b.Property<string>("TemporaryImageUrl");
|
b.Property<string>("TemporaryImageUrl");
|
||||||
|
|
||||||
@@ -191,9 +212,7 @@ namespace PodNoms.Api.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Author");
|
b.Property<string>("Author");
|
||||||
|
|
||||||
b.Property<DateTime>("CreateDate")
|
b.Property<DateTime>("CreateDate");
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasDefaultValueSql("getdate()");
|
|
||||||
|
|
||||||
b.Property<string>("Description");
|
b.Property<string>("Description");
|
||||||
|
|
||||||
@@ -332,6 +351,14 @@ namespace PodNoms.Api.Migrations
|
|||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("PodNoms.Api.Models.Playlist", "Playlist")
|
||||||
|
.WithMany("ParsedPlaylistItems")
|
||||||
|
.HasForeignKey("PlaylistId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ namespace PodNoms.Api.Models {
|
|||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
public string SiteUrl { get; set; }
|
public string SiteUrl { get; set; }
|
||||||
public string RssUrl { get; set; }
|
public string RssUrl { get; set; }
|
||||||
|
public string GoogleApiKey { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,5 +7,17 @@ namespace PodNoms.Api.Models {
|
|||||||
public string SourceUrl { get; set; }
|
public string SourceUrl { get; set; }
|
||||||
public Podcast Podcast { get; set; }
|
public Podcast Podcast { get; set; }
|
||||||
public List<PodcastEntry> PodcastEntries { get; set; }
|
public List<PodcastEntry> PodcastEntries { get; set; }
|
||||||
|
public List<ParsedPlaylistItem> ParsedPlaylistItems { get; set; }
|
||||||
|
public Playlist() {
|
||||||
|
ParsedPlaylistItems = new List<ParsedPlaylistItem>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class ParsedPlaylistItem : BaseModel {
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string VideoId { get; set; }
|
||||||
|
public string VideoType { get; set; }
|
||||||
|
public bool IsProcessed { get; set; }
|
||||||
|
public int PlaylistId { get; set; }
|
||||||
|
public Playlist Playlist { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,5 +7,7 @@ namespace PodNoms.Api.Persistence {
|
|||||||
Task<Playlist> GetAsync(int id);
|
Task<Playlist> GetAsync(int id);
|
||||||
Task<IEnumerable<Playlist>> GetAllAsync();
|
Task<IEnumerable<Playlist>> GetAllAsync();
|
||||||
Task<Playlist> AddOrUpdateAsync(Playlist playlist);
|
Task<Playlist> AddOrUpdateAsync(Playlist playlist);
|
||||||
|
Task<ParsedPlaylistItem> GetParsedItem(string itemId, int playlistId);
|
||||||
|
Task<List<ParsedPlaylistItem>> GetUnprocessedItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using PodNoms.Api.Models;
|
using PodNoms.Api.Models;
|
||||||
@@ -18,7 +19,7 @@ namespace PodNoms.Api.Persistence {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
public async Task<IEnumerable<Playlist>> GetAllAsync() {
|
public async Task<IEnumerable<Playlist>> GetAllAsync() {
|
||||||
return await _context.Playlists.ToListAsync();
|
return await _context.Playlists.Include(p => p.ParsedPlaylistItems).ToListAsync();
|
||||||
}
|
}
|
||||||
public async Task<Playlist> AddOrUpdateAsync(Playlist playlist) {
|
public async Task<Playlist> AddOrUpdateAsync(Playlist playlist) {
|
||||||
if (playlist.Id != 0) {
|
if (playlist.Id != 0) {
|
||||||
@@ -30,5 +31,20 @@ namespace PodNoms.Api.Persistence {
|
|||||||
}
|
}
|
||||||
return playlist;
|
return playlist;
|
||||||
}
|
}
|
||||||
|
public async Task<ParsedPlaylistItem> GetParsedItem(string itemId, int playlistId) {
|
||||||
|
return await _context.ParsedPlaylistItems
|
||||||
|
.Include(i => i.Playlist)
|
||||||
|
.Include(i => i.Playlist.Podcast)
|
||||||
|
.Include(i => i.Playlist.Podcast.AppUser)
|
||||||
|
.SingleOrDefaultAsync(i => i.VideoId == itemId && i.PlaylistId == playlistId);
|
||||||
|
}
|
||||||
|
public async Task<List<ParsedPlaylistItem>> GetUnprocessedItems() {
|
||||||
|
return await _context.ParsedPlaylistItems
|
||||||
|
.Where(p => p.IsProcessed == false)
|
||||||
|
.Include(i => i.Playlist)
|
||||||
|
.Include(i => i.Playlist.Podcast)
|
||||||
|
.Include(i => i.Playlist.Podcast.AppUser)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Design;
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
@@ -15,24 +18,37 @@ namespace PodNoms.Api.Persistence {
|
|||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
|
|
||||||
modelBuilder.Entity<Podcast>()
|
|
||||||
.Property(b => b.CreateDate)
|
|
||||||
.HasDefaultValueSql("getdate()");
|
|
||||||
|
|
||||||
modelBuilder.Entity<Podcast>()
|
|
||||||
.Property(b => b.Slug)
|
|
||||||
.IsUnicode(true);
|
|
||||||
|
|
||||||
modelBuilder.Entity<PodcastEntry>()
|
|
||||||
.Property(b => b.CreateDate)
|
|
||||||
.HasDefaultValueSql("getdate()");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public override int SaveChanges() {
|
||||||
|
_addTimestamps();
|
||||||
|
return base.SaveChanges();
|
||||||
|
}
|
||||||
|
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) {
|
||||||
|
_addTimestamps();
|
||||||
|
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
|
||||||
|
}
|
||||||
|
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) {
|
||||||
|
_addTimestamps();
|
||||||
|
return base.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
void _addTimestamps() {
|
||||||
|
var modifiedEntries = ChangeTracker.Entries()
|
||||||
|
.Where(x => (x.State == EntityState.Added || x.State == EntityState.Modified));
|
||||||
|
|
||||||
|
var now = DateTime.Now;
|
||||||
|
foreach (var entry in modifiedEntries) {
|
||||||
|
var entity = entry.Entity as BaseModel;
|
||||||
|
if (entity != null) {
|
||||||
|
if (entry.State == EntityState.Added) {
|
||||||
|
entity.CreateDate = now;
|
||||||
|
}
|
||||||
|
entity.UpdateDate = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public DbSet<Podcast> Podcasts { get; set; }
|
public DbSet<Podcast> Podcasts { get; set; }
|
||||||
public DbSet<PodcastEntry> PodcastEntries { get; set; }
|
public DbSet<PodcastEntry> PodcastEntries { get; set; }
|
||||||
public DbSet<Playlist> Playlists { get; set; }
|
public DbSet<Playlist> Playlists { get; set; }
|
||||||
|
public DbSet<ParsedPlaylistItem> ParsedPlaylistItems { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<UserSecretsId>aspnet-PodNoms.Api-1E27B6DE-BA4B-4F75-BBF8-CA34FB4D260A</UserSecretsId>
|
<UserSecretsId>aspnet-PodNoms.Api-1E27B6DE-BA4B-4F75-BBF8-CA34FB4D260A</UserSecretsId>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
<RootNamespace>PodNoms.Api</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="wwwroot\" />
|
<Folder Include="wwwroot\" />
|
||||||
@@ -13,10 +14,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentValidation.AspNetCore" Version="7.5.2" />
|
<PackageReference Include="FluentValidation.AspNetCore" Version="7.5.2" />
|
||||||
<PackageReference Include="Google.Apis" Version="1.32.2" />
|
<PackageReference Include="Google.Apis.Plus.v1" Version="1.33.0.1209" />
|
||||||
<PackageReference Include="Google.Apis.Auth" Version="1.32.2" />
|
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.33.0.1217" />
|
||||||
<PackageReference Include="Google.Apis.Core" Version="1.32.2" />
|
|
||||||
<PackageReference Include="Google.Apis.Plus.v1" Version="1.32.2.1182" />
|
|
||||||
<PackageReference Include="Hangfire" Version="1.6.17" />
|
<PackageReference Include="Hangfire" Version="1.6.17" />
|
||||||
<PackageReference Include="Hangfire.MemoryStorage" Version="1.5.2" />
|
<PackageReference Include="Hangfire.MemoryStorage" Version="1.5.2" />
|
||||||
<PackageReference Include="Lib.Net.Http.WebPush" Version="1.3.0" />
|
<PackageReference Include="Lib.Net.Http.WebPush" Version="1.3.0" />
|
||||||
|
|||||||
@@ -54,24 +54,22 @@ namespace PodNoms.Api.Services.Downloader {
|
|||||||
return $"{{\"Error\": \"{ex.Message}\"}}";
|
return $"{{\"Error\": \"{ex.Message}\"}}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<AudioType> GetInfo() {
|
public AudioType GetInfo() {
|
||||||
var ret = AudioType.Invalid;
|
var ret = AudioType.Invalid;
|
||||||
await Task.Run(() => {
|
var yt = new YoutubeDL();
|
||||||
var youtubeDl = new YoutubeDL();
|
yt.VideoUrl = this._url;
|
||||||
youtubeDl.VideoUrl = this._url;
|
var info = yt.GetDownloadInfo();
|
||||||
var info = youtubeDl.GetDownloadInfo();
|
|
||||||
|
|
||||||
if (info != null &&
|
if (info != null &&
|
||||||
(info.Errors.Count == 0 || info.VideoSize != null)) {
|
(info.Errors.Count == 0 || info.VideoSize != null)) {
|
||||||
this._properties = info;
|
this._properties = info;
|
||||||
// have to dump playlist handling for now
|
// have to dump playlist handling for now
|
||||||
if (info is PlaylistDownloadInfo && ((PlaylistDownloadInfo)info).Videos.Count > 0) {
|
if (info is PlaylistDownloadInfo && ((PlaylistDownloadInfo)info).Videos.Count > 0) {
|
||||||
ret = AudioType.Playlist;
|
ret = AudioType.Playlist;
|
||||||
} else if (info is VideoDownloadInfo) {
|
} else if (info is VideoDownloadInfo) {
|
||||||
ret = AudioType.Valid;
|
ret = AudioType.Valid;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +87,12 @@ namespace PodNoms.Api.Services.Downloader {
|
|||||||
yt.StandardOutputEvent += (sender, output) => {
|
yt.StandardOutputEvent += (sender, output) => {
|
||||||
if (output.Contains("%")) {
|
if (output.Contains("%")) {
|
||||||
var progress = _parseProgress(output);
|
var progress = _parseProgress(output);
|
||||||
|
Console.WriteLine($"Processing {progress.CurrentSpeed} {progress.ETA} {progress.Percentage}");
|
||||||
if (DownloadProgress != null) {
|
if (DownloadProgress != null) {
|
||||||
DownloadProgress(this, progress);
|
DownloadProgress(this, progress);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Console.WriteLine(output);
|
||||||
if (PostProcessing != null) {
|
if (PostProcessing != null) {
|
||||||
PostProcessing(this, output);
|
PostProcessing(this, output);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ namespace PodNoms.Api.Services.Jobs {
|
|||||||
public static void BootstrapJobs() {
|
public static void BootstrapJobs() {
|
||||||
RecurringJob.AddOrUpdate<ClearOrphanAudioJob>(x => x.Execute(), Cron.Daily(1));
|
RecurringJob.AddOrUpdate<ClearOrphanAudioJob>(x => x.Execute(), Cron.Daily(1));
|
||||||
RecurringJob.AddOrUpdate<UpdateYouTubeDlJob>(x => x.Execute(), Cron.Daily(1, 30));
|
RecurringJob.AddOrUpdate<UpdateYouTubeDlJob>(x => x.Execute(), Cron.Daily(1, 30));
|
||||||
|
|
||||||
// BackgroundJob.Schedule<ProcessPlaylistsJob>(x => x.Execute(), TimeSpan.FromSeconds(1));
|
// BackgroundJob.Schedule<ProcessPlaylistsJob>(x => x.Execute(), TimeSpan.FromSeconds(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
80
server/Services/Jobs/ProcessPlaylistItemJob.cs
Normal file
80
server/Services/Jobs/ProcessPlaylistItemJob.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Hangfire;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using PodNoms.Api.Models;
|
||||||
|
using PodNoms.Api.Persistence;
|
||||||
|
using PodNoms.Api.Services.Downloader;
|
||||||
|
using PodNoms.Api.Services.Processor;
|
||||||
|
using PodNoms.Api.Utils.RemoteParsers;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Services.Jobs {
|
||||||
|
public class ProcessPlaylistItemJob : IJob {
|
||||||
|
public readonly IPlaylistRepository _playlistRepository;
|
||||||
|
public readonly IEntryRepository _entryRepository;
|
||||||
|
private readonly IAudioUploadProcessService _uploadService;
|
||||||
|
private readonly IConfiguration _options;
|
||||||
|
private readonly IPodcastRepository _podcastRepository;
|
||||||
|
private readonly ApplicationsSettings _applicationsSettings;
|
||||||
|
private readonly ILogger<ProcessPlaylistItemJob> _logger;
|
||||||
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
|
public ProcessPlaylistItemJob(IPlaylistRepository playlistRepository, IEntryRepository entryRepository,
|
||||||
|
IAudioUploadProcessService uploadService, IConfiguration options,
|
||||||
|
IPodcastRepository podcastRepository, IOptions<ApplicationsSettings> applicationsSettings,
|
||||||
|
IUnitOfWork unitOfWork, ILogger<ProcessPlaylistItemJob> logger) {
|
||||||
|
this._unitOfWork = unitOfWork;
|
||||||
|
this._playlistRepository = playlistRepository;
|
||||||
|
this._entryRepository = entryRepository;
|
||||||
|
this._uploadService = uploadService;
|
||||||
|
this._options = options;
|
||||||
|
this._podcastRepository = podcastRepository;
|
||||||
|
this._applicationsSettings = applicationsSettings.Value;
|
||||||
|
this._logger = logger;
|
||||||
|
}
|
||||||
|
public async Task Execute() {
|
||||||
|
var items = await _playlistRepository.GetUnprocessedItems();
|
||||||
|
foreach (var item in items) {
|
||||||
|
await ExecuteForItem(item.VideoId, item.Playlist.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task ExecuteForItem(string itemId, int playlistId) {
|
||||||
|
var item = await _playlistRepository.GetParsedItem(itemId, playlistId);
|
||||||
|
if (item != null && !string.IsNullOrEmpty(item.VideoType) && item.VideoType.Equals("youtube")) {
|
||||||
|
var url = $"https://www.youtube.com/watch?v={item.VideoId}";
|
||||||
|
var downloader = new AudioDownloader(url, _applicationsSettings.Downloader);
|
||||||
|
var info = downloader.GetInfo();
|
||||||
|
if (info == AudioType.Valid) {
|
||||||
|
var podcast = await _podcastRepository.GetAsync(item.Playlist.PodcastId);
|
||||||
|
var uid = System.Guid.NewGuid().ToString();
|
||||||
|
var file = downloader.DownloadAudio(uid);
|
||||||
|
if (System.IO.File.Exists(file)) {
|
||||||
|
//we have the file so lets create the entry and ship to CDN
|
||||||
|
var entry = new PodcastEntry {
|
||||||
|
Title = downloader.Properties?.Title,
|
||||||
|
Uid = uid,
|
||||||
|
Description = downloader.Properties?.Description,
|
||||||
|
ProcessingStatus = ProcessingStatus.Uploading,
|
||||||
|
ImageUrl = downloader.Properties?.Thumbnail
|
||||||
|
};
|
||||||
|
podcast.PodcastEntries.Add(entry);
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
|
var uploaded = await _uploadService.UploadAudio(entry.Id, file);
|
||||||
|
if (uploaded) {
|
||||||
|
item.IsProcessed = true;
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
|
BackgroundJob.Enqueue<INotifyJobCompleteService>(
|
||||||
|
service => service.NotifyUser(entry.Podcast.AppUser.Id, "PodNoms", $"{entry.Title} has finished processing",
|
||||||
|
entry.Podcast.GetThumbnailUrl(
|
||||||
|
this._options.GetSection("Storage")["CdnUrl"],
|
||||||
|
this._options.GetSection("ImageFileStorageSettings")["ContainerName"])
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_logger.LogError($"Processing playlist item {itemId} failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Hangfire;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using NYoutubeDL.Models;
|
using NYoutubeDL.Models;
|
||||||
using PodNoms.Api.Models;
|
using PodNoms.Api.Models;
|
||||||
using PodNoms.Api.Persistence;
|
using PodNoms.Api.Persistence;
|
||||||
using PodNoms.Api.Services.Downloader;
|
using PodNoms.Api.Services.Downloader;
|
||||||
|
using PodNoms.Api.Utils.RemoteParsers;
|
||||||
using static NYoutubeDL.Helpers.Enums;
|
using static NYoutubeDL.Helpers.Enums;
|
||||||
|
|
||||||
namespace PodNoms.Api.Services.Jobs {
|
namespace PodNoms.Api.Services.Jobs {
|
||||||
@@ -16,44 +19,51 @@ namespace PodNoms.Api.Services.Jobs {
|
|||||||
public readonly IEntryRepository _entryRepository;
|
public readonly IEntryRepository _entryRepository;
|
||||||
private readonly ApplicationsSettings _applicationsSettings;
|
private readonly ApplicationsSettings _applicationsSettings;
|
||||||
private readonly ILogger<ProcessPlaylistsJob> _logger;
|
private readonly ILogger<ProcessPlaylistsJob> _logger;
|
||||||
|
private readonly YouTubeParser _youTubeParser;
|
||||||
|
private readonly MixcloudParser _mixcloudParser;
|
||||||
|
private readonly IUnitOfWork _unitOfWork;
|
||||||
|
|
||||||
public ProcessPlaylistsJob(IPlaylistRepository playlistRepository,
|
public ProcessPlaylistsJob(IPlaylistRepository playlistRepository, IEntryRepository entryRepository,
|
||||||
IEntryRepository entryRepository, IOptions<ApplicationsSettings> applicationsSettings, ILoggerFactory logger) {
|
IUnitOfWork unitOfWork, IOptions<ApplicationsSettings> applicationsSettings,
|
||||||
_playlistRepository = playlistRepository;
|
ILoggerFactory logger, YouTubeParser youTubeParser, MixcloudParser mixcloudParser) {
|
||||||
_entryRepository = entryRepository;
|
this._unitOfWork = unitOfWork;
|
||||||
_applicationsSettings = applicationsSettings.Value;
|
this._youTubeParser = youTubeParser;
|
||||||
_logger = logger.CreateLogger<ProcessPlaylistsJob>();
|
this._mixcloudParser = mixcloudParser;
|
||||||
|
this._playlistRepository = playlistRepository;
|
||||||
|
this._entryRepository = entryRepository;
|
||||||
|
this._applicationsSettings = applicationsSettings.Value;
|
||||||
|
this._logger = logger.CreateLogger<ProcessPlaylistsJob>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Execute() {
|
public async Task Execute() {
|
||||||
var playists = await _playlistRepository.GetAllAsync();
|
var playlists = await _playlistRepository.GetAllAsync();
|
||||||
|
var resultList = new List<ParsedItemResult>();
|
||||||
|
|
||||||
foreach (var playlist in playists) {
|
foreach (var playlist in playlists) {
|
||||||
var downloader = new AudioDownloader(playlist.SourceUrl, _applicationsSettings.Downloader);
|
var downloader = new AudioDownloader(playlist.SourceUrl, _applicationsSettings.Downloader);
|
||||||
var info = await downloader.GetInfo();
|
var info = downloader.GetInfo();
|
||||||
|
var id = ((PlaylistDownloadInfo)downloader.RawProperties).Id;
|
||||||
if (info == AudioType.Playlist && downloader.RawProperties is PlaylistDownloadInfo) {
|
if (info == AudioType.Playlist && downloader.RawProperties is PlaylistDownloadInfo) {
|
||||||
var list = ((PlaylistDownloadInfo)downloader.RawProperties).Videos
|
if (_youTubeParser.ValidateUrl(playlist.SourceUrl)) {
|
||||||
.OrderByDescending(x => x.Id)
|
var searchTerm = (playlist.SourceUrl.Contains("/user/")) ? "forUsername" : "id";
|
||||||
.Take(10);
|
resultList = await _youTubeParser.GetPlaylistEntriesForId(id);
|
||||||
StringBuilder br = new StringBuilder();
|
//make sure the items are sorted in ascending date order
|
||||||
foreach (var item in list) {
|
//so they will be processed in the order they were created
|
||||||
_logger.LogDebug($"Processing: {item.Id} - {item.Url}");
|
} else if (_mixcloudParser.ValidateUrl(playlist.SourceUrl)) {
|
||||||
br.Append($"Processing: {item.Id} - {item.Title}\n");
|
resultList = await _mixcloudParser.GetEntries(id);
|
||||||
|
|
||||||
var outputDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
|
||||||
Directory.CreateDirectory(outputDir);
|
|
||||||
|
|
||||||
var yt = new NYoutubeDL.YoutubeDL(playlist.SourceUrl);
|
|
||||||
yt.Options.PostProcessingOptions.ExtractAudio = true;
|
|
||||||
yt.Options.PostProcessingOptions.AudioFormat = AudioFormat.mp3;
|
|
||||||
yt.Options.VideoSelectionOptions.PlaylistItems = "1,2,3";
|
|
||||||
yt.Options.FilesystemOptions.Output = Path.Combine(outputDir, "%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s");
|
|
||||||
|
|
||||||
var p = yt.Download();
|
|
||||||
p.WaitForExit();
|
|
||||||
}
|
}
|
||||||
_logger.LogDebug(br.ToString());
|
|
||||||
}
|
}
|
||||||
|
foreach (var item in resultList?.OrderBy(r => r.UploadDate)) {
|
||||||
|
if (!playlist.ParsedPlaylistItems.Any(p => p.VideoId == item.Id)) {
|
||||||
|
playlist.ParsedPlaylistItems.Add(new ParsedPlaylistItem {
|
||||||
|
VideoId = item.Id,
|
||||||
|
VideoType = item.VideoType
|
||||||
|
});
|
||||||
|
BackgroundJob.Enqueue<ProcessPlaylistItemJob>(service => service.ExecuteForItem(item.Id, playlist.Id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await _unitOfWork.CompleteAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
namespace NYoutubeDL.Models
|
namespace NYoutubeDL.Models {
|
||||||
{
|
|
||||||
#region Using
|
#region Using
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@@ -32,8 +31,7 @@ namespace NYoutubeDL.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class holding data about the current download, which is parsed from youtube-dl's standard output
|
/// Class holding data about the current download, which is parsed from youtube-dl's standard output
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DownloadInfo : NotifyPropertyChangedEx
|
public class DownloadInfo : NotifyPropertyChangedEx {
|
||||||
{
|
|
||||||
protected const string ALREADY = "already";
|
protected const string ALREADY = "already";
|
||||||
|
|
||||||
protected const string DOWNLOADRATESTRING = "iB/s";
|
protected const string DOWNLOADRATESTRING = "iB/s";
|
||||||
@@ -51,7 +49,7 @@ namespace NYoutubeDL.Models
|
|||||||
private string eta;
|
private string eta;
|
||||||
|
|
||||||
private string status = Enums.DownloadStatus.WAITING.ToString();
|
private string status = Enums.DownloadStatus.WAITING.ToString();
|
||||||
|
private string id;
|
||||||
private string title;
|
private string title;
|
||||||
|
|
||||||
private int videoProgress;
|
private int videoProgress;
|
||||||
@@ -61,8 +59,7 @@ namespace NYoutubeDL.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current download rate
|
/// The current download rate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string DownloadRate
|
public string DownloadRate {
|
||||||
{
|
|
||||||
get => this.downloadRate;
|
get => this.downloadRate;
|
||||||
set => this.SetField(ref this.downloadRate, value);
|
set => this.SetField(ref this.downloadRate, value);
|
||||||
}
|
}
|
||||||
@@ -75,8 +72,7 @@ namespace NYoutubeDL.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current download's estimated time remaining
|
/// The current download's estimated time remaining
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Eta
|
public string Eta {
|
||||||
{
|
|
||||||
get => this.eta;
|
get => this.eta;
|
||||||
set => this.SetField(ref this.eta, value);
|
set => this.SetField(ref this.eta, value);
|
||||||
}
|
}
|
||||||
@@ -84,29 +80,30 @@ namespace NYoutubeDL.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The status of the video currently downloading
|
/// The status of the video currently downloading
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Status
|
public string Status {
|
||||||
{
|
|
||||||
get => this.status;
|
get => this.status;
|
||||||
set
|
set {
|
||||||
{
|
|
||||||
if (!this.status.Equals(Enums.DownloadStatus.ERROR.ToString()) &&
|
if (!this.status.Equals(Enums.DownloadStatus.ERROR.ToString()) &&
|
||||||
!this.status.Equals(Enums.DownloadStatus.WARNING.ToString()))
|
!this.status.Equals(Enums.DownloadStatus.WARNING.ToString())) {
|
||||||
{
|
|
||||||
this.SetField(ref this.status, value);
|
this.SetField(ref this.status, value);
|
||||||
}
|
} else if (value.Equals(Enums.DownloadStatus.ERROR.ToString()) &&
|
||||||
else if (value.Equals(Enums.DownloadStatus.ERROR.ToString()) &&
|
this.status.Equals(Enums.DownloadStatus.WARNING.ToString())) {
|
||||||
this.status.Equals(Enums.DownloadStatus.WARNING.ToString()))
|
|
||||||
{
|
|
||||||
this.SetField(ref this.status, value);
|
this.SetField(ref this.status, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The id of the playlist
|
||||||
|
/// </summary>
|
||||||
|
public string Id {
|
||||||
|
get => this.id;
|
||||||
|
set => this.SetField(ref this.id, value);
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The title of the video currently downloading
|
/// The title of the video currently downloading
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Title
|
public string Title {
|
||||||
{
|
|
||||||
get => this.title;
|
get => this.title;
|
||||||
set => this.SetField(ref this.title, value);
|
set => this.SetField(ref this.title, value);
|
||||||
}
|
}
|
||||||
@@ -114,23 +111,16 @@ namespace NYoutubeDL.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current download progresss
|
/// The current download progresss
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int VideoProgress
|
public int VideoProgress {
|
||||||
{
|
|
||||||
get => this.videoProgress;
|
get => this.videoProgress;
|
||||||
set
|
set {
|
||||||
{
|
|
||||||
this.SetField(ref this.videoProgress, value);
|
this.SetField(ref this.videoProgress, value);
|
||||||
|
|
||||||
if (value == 0)
|
if (value == 0) {
|
||||||
{
|
|
||||||
this.Status = Enums.DownloadStatus.WAITING.ToString();
|
this.Status = Enums.DownloadStatus.WAITING.ToString();
|
||||||
}
|
} else if (value == 100) {
|
||||||
else if (value == 100)
|
|
||||||
{
|
|
||||||
this.Status = Enums.DownloadStatus.DONE.ToString();
|
this.Status = Enums.DownloadStatus.DONE.ToString();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
this.Status = Enums.DownloadStatus.DOWNLOADING.ToString();
|
this.Status = Enums.DownloadStatus.DOWNLOADING.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,8 +129,7 @@ namespace NYoutubeDL.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current download's total size
|
/// The current download's total size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string VideoSize
|
public string VideoSize {
|
||||||
{
|
|
||||||
get => this.videoSize;
|
get => this.videoSize;
|
||||||
set => this.SetField(ref this.videoSize, value);
|
set => this.SetField(ref this.videoSize, value);
|
||||||
}
|
}
|
||||||
@@ -150,31 +139,25 @@ namespace NYoutubeDL.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Warnings { get; } = new List<string>();
|
public List<string> Warnings { get; } = new List<string>();
|
||||||
|
|
||||||
internal static DownloadInfo CreateDownloadInfo(string output)
|
internal static DownloadInfo CreateDownloadInfo(string output) {
|
||||||
{
|
if (string.IsNullOrEmpty(output) || output.Equals("null"))
|
||||||
try
|
return null;
|
||||||
{
|
|
||||||
|
try {
|
||||||
PlaylistInfo info = JsonConvert.DeserializeObject<PlaylistInfo>(output);
|
PlaylistInfo info = JsonConvert.DeserializeObject<PlaylistInfo>(output);
|
||||||
if (!string.IsNullOrEmpty(info._type) && info._type.Equals("playlist"))
|
if (!string.IsNullOrEmpty(info._type) && info._type.Equals("playlist")) {
|
||||||
{
|
|
||||||
return new PlaylistDownloadInfo(info);
|
return new PlaylistDownloadInfo(info);
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
VideoInfo info = JsonConvert.DeserializeObject<VideoInfo>(output);
|
VideoInfo info = JsonConvert.DeserializeObject<VideoInfo>(output);
|
||||||
if (!string.IsNullOrEmpty(info.title))
|
if (!string.IsNullOrEmpty(info.title)) {
|
||||||
{
|
|
||||||
return new VideoDownloadInfo(info);
|
return new VideoDownloadInfo(info);
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,57 +169,45 @@ namespace NYoutubeDL.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<string> ErrorEvent;
|
public event EventHandler<string> ErrorEvent;
|
||||||
|
|
||||||
internal virtual void ParseError(object sender, string error)
|
internal virtual void ParseError(object sender, string error) {
|
||||||
{
|
|
||||||
this.ErrorEvent?.Invoke(this, error);
|
this.ErrorEvent?.Invoke(this, error);
|
||||||
if (error.Contains("WARNING"))
|
if (error.Contains("WARNING")) {
|
||||||
{
|
|
||||||
this.Warnings.Add(error);
|
this.Warnings.Add(error);
|
||||||
this.Status = Enums.DownloadStatus.WARNING.ToString();
|
this.Status = Enums.DownloadStatus.WARNING.ToString();
|
||||||
}
|
} else if (error.Contains("ERROR")) {
|
||||||
else if (error.Contains("ERROR"))
|
|
||||||
{
|
|
||||||
this.Errors.Add(error);
|
this.Errors.Add(error);
|
||||||
this.Status = Enums.DownloadStatus.ERROR.ToString();
|
this.Status = Enums.DownloadStatus.ERROR.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ParseOutput(object sender, string output)
|
internal virtual void ParseOutput(object sender, string output) {
|
||||||
{
|
try {
|
||||||
try
|
if (output.Contains("%")) {
|
||||||
{
|
|
||||||
if (output.Contains("%"))
|
|
||||||
{
|
|
||||||
int progressIndex = output.LastIndexOf(' ', output.IndexOf('%')) + 1;
|
int progressIndex = output.LastIndexOf(' ', output.IndexOf('%')) + 1;
|
||||||
string progressString = output.Substring(progressIndex, output.IndexOf('%') - progressIndex);
|
string progressString = output.Substring(progressIndex, output.IndexOf('%') - progressIndex);
|
||||||
this.VideoProgress = (int) Math.Round(double.Parse(progressString));
|
this.VideoProgress = (int)Math.Round(double.Parse(progressString));
|
||||||
|
|
||||||
int sizeIndex = output.LastIndexOf(' ', output.IndexOf(DOWNLOADSIZESTRING)) + 1;
|
int sizeIndex = output.LastIndexOf(' ', output.IndexOf(DOWNLOADSIZESTRING)) + 1;
|
||||||
string sizeString = output.Substring(sizeIndex, output.IndexOf(DOWNLOADSIZESTRING) - sizeIndex + 2);
|
string sizeString = output.Substring(sizeIndex, output.IndexOf(DOWNLOADSIZESTRING) - sizeIndex + 2);
|
||||||
this.VideoSize = sizeString;
|
this.VideoSize = sizeString;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.Contains(DOWNLOADRATESTRING))
|
if (output.Contains(DOWNLOADRATESTRING)) {
|
||||||
{
|
|
||||||
int rateIndex = output.LastIndexOf(' ', output.LastIndexOf(DOWNLOADRATESTRING)) + 1;
|
int rateIndex = output.LastIndexOf(' ', output.LastIndexOf(DOWNLOADRATESTRING)) + 1;
|
||||||
string rateString =
|
string rateString =
|
||||||
output.Substring(rateIndex, output.LastIndexOf(DOWNLOADRATESTRING) - rateIndex + 4);
|
output.Substring(rateIndex, output.LastIndexOf(DOWNLOADRATESTRING) - rateIndex + 4);
|
||||||
this.DownloadRate = rateString;
|
this.DownloadRate = rateString;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.Contains(ETASTRING))
|
if (output.Contains(ETASTRING)) {
|
||||||
{
|
|
||||||
this.Eta = output.Substring(output.LastIndexOf(' ') + 1);
|
this.Eta = output.Substring(output.LastIndexOf(' ') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.Contains(ALREADY))
|
if (output.Contains(ALREADY)) {
|
||||||
{
|
|
||||||
this.Status = Enums.DownloadStatus.DONE.ToString();
|
this.Status = Enums.DownloadStatus.DONE.ToString();
|
||||||
this.VideoProgress = 100;
|
this.VideoProgress = 100;
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception) {
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace NYoutubeDL.Models
|
|||||||
|
|
||||||
public PlaylistDownloadInfo(PlaylistInfo info)
|
public PlaylistDownloadInfo(PlaylistInfo info)
|
||||||
{
|
{
|
||||||
|
this.Id = info.id;
|
||||||
this.Title = info.title;
|
this.Title = info.title;
|
||||||
foreach (VideoInfo videoInfo in info.entries)
|
foreach (VideoInfo videoInfo in info.entries)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -180,11 +180,6 @@ namespace NYoutubeDL.Models
|
|||||||
|
|
||||||
public int? Width { get; }
|
public int? Width { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The ID string of the video
|
|
||||||
/// </summary>
|
|
||||||
public string Id { get; }
|
|
||||||
|
|
||||||
public List<ThumbnailDownloadInfo> Thumbnails { get; } = new List<ThumbnailDownloadInfo>();
|
public List<ThumbnailDownloadInfo> Thumbnails { get; } = new List<ThumbnailDownloadInfo>();
|
||||||
|
|
||||||
public List<string> Tags { get; }
|
public List<string> Tags { get; }
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace PodNoms.Api.Services.Processor {
|
|||||||
public async Task<AudioType> GetInformation(PodcastEntry entry) {
|
public async Task<AudioType> GetInformation(PodcastEntry entry) {
|
||||||
|
|
||||||
var downloader = new AudioDownloader(entry.SourceUrl, _applicationsSettings.Downloader);
|
var downloader = new AudioDownloader(entry.SourceUrl, _applicationsSettings.Downloader);
|
||||||
var ret = await downloader.GetInfo();
|
var ret = downloader.GetInfo();
|
||||||
if (ret == AudioType.Valid) {
|
if (ret == AudioType.Valid) {
|
||||||
entry.Title = downloader.Properties?.Title;
|
entry.Title = downloader.Properties?.Title;
|
||||||
entry.Description = downloader.Properties?.Description;
|
entry.Description = downloader.Properties?.Description;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ using Microsoft.AspNetCore.Identity;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||||
|
using PodNoms.Api.Utils.RemoteParsers;
|
||||||
|
|
||||||
namespace PodNoms.Api {
|
namespace PodNoms.Api {
|
||||||
public class Startup {
|
public class Startup {
|
||||||
@@ -102,7 +103,7 @@ namespace PodNoms.Api {
|
|||||||
services.Configure<ImageFileStorageSettings>(Configuration.GetSection("ImageFileStorageSettings"));
|
services.Configure<ImageFileStorageSettings>(Configuration.GetSection("ImageFileStorageSettings"));
|
||||||
services.Configure<AudioFileStorageSettings>(Configuration.GetSection("AudioFileStorageSettings"));
|
services.Configure<AudioFileStorageSettings>(Configuration.GetSection("AudioFileStorageSettings"));
|
||||||
services.Configure<FormOptions>(options => {
|
services.Configure<FormOptions>(options => {
|
||||||
options.ValueCountLimit = 10;
|
// options.ValueCountLimit = 10;
|
||||||
options.ValueLengthLimit = int.MaxValue;
|
options.ValueLengthLimit = int.MaxValue;
|
||||||
options.MemoryBufferThreshold = Int32.MaxValue;
|
options.MemoryBufferThreshold = Int32.MaxValue;
|
||||||
options.MultipartBodyLengthLimit = long.MaxValue;
|
options.MultipartBodyLengthLimit = long.MaxValue;
|
||||||
@@ -112,6 +113,10 @@ namespace PodNoms.Api {
|
|||||||
e.AddProfile(new MappingProvider(Configuration));
|
e.AddProfile(new MappingProvider(Configuration));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddHttpClient("mixcloud", c => {
|
||||||
|
c.BaseAddress = new Uri("https://api.mixcloud.com/");
|
||||||
|
c.DefaultRequestHeaders.Add("Accept", "application/json");
|
||||||
|
});
|
||||||
services.AddHttpClient();
|
services.AddHttpClient();
|
||||||
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
|
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
|
||||||
|
|
||||||
@@ -220,6 +225,8 @@ namespace PodNoms.Api {
|
|||||||
services.AddScoped<INotifyJobCompleteService, NotifyJobCompleteService>();
|
services.AddScoped<INotifyJobCompleteService, NotifyJobCompleteService>();
|
||||||
services.AddScoped<IAudioUploadProcessService, AudioUploadProcessService>();
|
services.AddScoped<IAudioUploadProcessService, AudioUploadProcessService>();
|
||||||
services.AddScoped<IMailSender, MailgunSender>();
|
services.AddScoped<IMailSender, MailgunSender>();
|
||||||
|
services.AddScoped<YouTubeParser>();
|
||||||
|
services.AddScoped<MixcloudParser>();
|
||||||
services.AddHttpClient<Services.Gravatar.GravatarHttpClient>();
|
services.AddHttpClient<Services.Gravatar.GravatarHttpClient>();
|
||||||
|
|
||||||
//register the codepages (required for slugify)
|
//register the codepages (required for slugify)
|
||||||
|
|||||||
36
server/Utils/RemoteParsers/MixcloudParser.cs
Normal file
36
server/Utils/RemoteParsers/MixcloudParser.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||||
|
public class MixcloudParser {
|
||||||
|
const string URL_REGEX = @"^(http(s)?:\/\/)?((w){3}.)?mixcloud?(\.com)?\/.+";
|
||||||
|
|
||||||
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
|
||||||
|
public MixcloudParser(IHttpClientFactory httpClientFactory) {
|
||||||
|
this._httpClientFactory = httpClientFactory;
|
||||||
|
}
|
||||||
|
public bool ValidateUrl(string url) {
|
||||||
|
var regex = new Regex(URL_REGEX);
|
||||||
|
var result = regex.Match(url);
|
||||||
|
return result.Success;
|
||||||
|
}
|
||||||
|
public async Task<List<ParsedItemResult>> GetEntries(string identifier) {
|
||||||
|
var client = _httpClientFactory.CreateClient("mixcloud");
|
||||||
|
var result = await client.GetAsync(identifier);
|
||||||
|
if (result.IsSuccessStatusCode) {
|
||||||
|
var typed = JsonConvert.DeserializeObject<MixcloudResult>(await result.Content.ReadAsStringAsync());
|
||||||
|
return typed.data[0].cloudcasts.Select(c => new ParsedItemResult {
|
||||||
|
Id = c.key,
|
||||||
|
VideoType = "mixcloud",
|
||||||
|
UploadDate = c.updated_time
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
server/Utils/RemoteParsers/MixcloudViewModels.cs
Normal file
75
server/Utils/RemoteParsers/MixcloudViewModels.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||||
|
|
||||||
|
|
||||||
|
public class Paging {
|
||||||
|
public string previous { get; set; }
|
||||||
|
public string next { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Pictures {
|
||||||
|
public string medium { get; set; }
|
||||||
|
public string extra_large { get; set; }
|
||||||
|
public string large { get; set; }
|
||||||
|
public string medium_mobile { get; set; }
|
||||||
|
public string small { get; set; }
|
||||||
|
public string thumbnail { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class From {
|
||||||
|
public string url { get; set; }
|
||||||
|
public string username { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string key { get; set; }
|
||||||
|
public Pictures pictures { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Tag {
|
||||||
|
public string url { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string key { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
public string url { get; set; }
|
||||||
|
public string username { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string key { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Cloudcast {
|
||||||
|
public IList<Tag> tags { get; set; }
|
||||||
|
public int play_count { get; set; }
|
||||||
|
public User user { get; set; }
|
||||||
|
public string key { get; set; }
|
||||||
|
public DateTime created_time { get; set; }
|
||||||
|
public int audio_length { get; set; }
|
||||||
|
public string slug { get; set; }
|
||||||
|
public int favorite_count { get; set; }
|
||||||
|
public int listener_count { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string url { get; set; }
|
||||||
|
public int repost_count { get; set; }
|
||||||
|
public DateTime updated_time { get; set; }
|
||||||
|
public int comment_count { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Datum {
|
||||||
|
public From from { get; set; }
|
||||||
|
public string title { get; set; }
|
||||||
|
public string url { get; set; }
|
||||||
|
public string key { get; set; }
|
||||||
|
public DateTime created_time { get; set; }
|
||||||
|
public IList<Cloudcast> cloudcasts { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MixcloudResult {
|
||||||
|
public Paging paging { get; set; }
|
||||||
|
public IList<Datum> data { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
server/Utils/RemoteParsers/ParsedItemResult.cs
Normal file
9
server/Utils/RemoteParsers/ParsedItemResult.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||||
|
public class ParsedItemResult {
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string VideoType { get; set; }
|
||||||
|
public DateTime? UploadDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
61
server/Utils/RemoteParsers/YouTubeParser.cs
Normal file
61
server/Utils/RemoteParsers/YouTubeParser.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Google.Apis.Services;
|
||||||
|
using Google.Apis.YouTube.v3;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using PodNoms.Api.Models;
|
||||||
|
|
||||||
|
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||||
|
public partial class YouTubeParser {
|
||||||
|
const string URL_REGEX = @"^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/.+";
|
||||||
|
private readonly AppSettings _settings;
|
||||||
|
private YouTubeService youtube;
|
||||||
|
public YouTubeParser(IOptions<AppSettings> options) {
|
||||||
|
this._settings = options.Value;
|
||||||
|
this.youtube = _getYouTubeService();
|
||||||
|
}
|
||||||
|
private YouTubeService _getYouTubeService() {
|
||||||
|
return new YouTubeService(new BaseClientService.Initializer() {
|
||||||
|
ApiKey = _settings.GoogleApiKey,
|
||||||
|
ApplicationName = this.GetType().ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidateUrl(string url) {
|
||||||
|
var regex = new Regex(URL_REGEX);
|
||||||
|
var result = regex.Match(url);
|
||||||
|
return result.Success;
|
||||||
|
}
|
||||||
|
public async Task<List<ParsedItemResult>> GetPlaylistEntriesForId(string id, int nCount = 10) {
|
||||||
|
var playlistRequest = youtube.PlaylistItems.List("contentDetails");
|
||||||
|
playlistRequest.PlaylistId = id;
|
||||||
|
playlistRequest.MaxResults = nCount;
|
||||||
|
var plists = await playlistRequest.ExecuteAsync();
|
||||||
|
return plists.Items
|
||||||
|
.Select(p => new ParsedItemResult {
|
||||||
|
Id = p.ContentDetails.VideoId,
|
||||||
|
VideoType = "youtube",
|
||||||
|
UploadDate = p.ContentDetails.VideoPublishedAt
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
public async Task<List<ParsedItemResult>> GetPlaylistEntriesForChannelName(string channelName, string searchType, int nCount = 10) {
|
||||||
|
|
||||||
|
var request = youtube.Channels.List("contentDetails");
|
||||||
|
if (searchType.Equals("id"))
|
||||||
|
request.Id = channelName;
|
||||||
|
else
|
||||||
|
request.ForUsername = channelName;
|
||||||
|
request.MaxResults = 1;
|
||||||
|
var resp = await request.ExecuteAsync();
|
||||||
|
if (resp.Items.Count == 1) {
|
||||||
|
var uploadListId = resp.Items[0].ContentDetails.RelatedPlaylists.Uploads;
|
||||||
|
if (!string.IsNullOrEmpty(uploadListId)) {
|
||||||
|
return await GetPlaylistEntriesForId(uploadListId, nCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"App": {
|
"App": {
|
||||||
"Version": "0.23.0",
|
"Version": "0.23.0"
|
||||||
"SiteUrl": "http://localhost:4200",
|
|
||||||
"RssUrl": "http://localhost:5000/rss/"
|
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "server=localhost;database=PodNoms;user id=sa;password=cTXu1nJLCpC/c",
|
"DefaultConnection": "server=localhost;database=PodNoms;user id=sa;password=cTXu1nJLCpC/c",
|
||||||
|
|||||||
Reference in New Issue
Block a user