mirror of
https://github.com/fergalmoran/podnoms.git
synced 2025-12-22 09:18:08 +00:00
Mixcloud playlists working
This commit is contained in:
@@ -118,7 +118,8 @@ namespace PodNoms.Api.Controllers {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (status == AudioType.Playlist && YouTubeParser.ValidateUrl(item.SourceUrl)) {
|
||||
} else if ((status == AudioType.Playlist && YouTubeParser.ValidateUrl(item.SourceUrl))
|
||||
|| MixcloudParser.ValidateUrl(item.SourceUrl)) {
|
||||
entry.ProcessingStatus = ProcessingStatus.Deferred;
|
||||
var result = _mapper.Map<PodcastEntry, PodcastEntryViewModel>(entry);
|
||||
return Accepted(result);
|
||||
|
||||
512
server/Migrations/20180512180833_Initial.Designer.cs
generated
Normal file
512
server/Migrations/20180512180833_Initial.Designer.cs
generated
Normal file
@@ -0,0 +1,512 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PodNoms.Api.Persistence;
|
||||
|
||||
namespace PodNoms.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(PodNomsDbContext))]
|
||||
[Migration("20180512180833_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.0-rc1-32029")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||
.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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
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.ChatMessage", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("FromUserId");
|
||||
|
||||
b.Property<string>("Message");
|
||||
|
||||
b.Property<DateTime?>("MessageSeen");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("ToUserId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FromUserId");
|
||||
|
||||
b.HasIndex("ToUserId");
|
||||
|
||||
b.ToTable("ChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<bool>("IsProcessed");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<int>("PlaylistId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
|
||||
b.Property<string>("SourceUrl");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("Playlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AppUserId");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("Slug");
|
||||
|
||||
b.Property<string>("TemporaryImageUrl");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("Podcasts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("AudioFileSize");
|
||||
|
||||
b.Property<float>("AudioLength");
|
||||
|
||||
b.Property<string>("AudioUrl");
|
||||
|
||||
b.Property<string>("Author");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<string>("ImageUrl");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
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")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("PodcastEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ServerConfig", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Key");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Value");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ServerConfig","admin");
|
||||
});
|
||||
|
||||
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.ChatMessage", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "FromUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("FromUserId");
|
||||
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "ToUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("ToUserId");
|
||||
});
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
451
server/Migrations/20180512180833_Initial.cs
Normal file
451
server/Migrations/20180512180833_Initial.cs
Normal file
@@ -0,0 +1,451 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace PodNoms.Api.Migrations
|
||||
{
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "admin");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
Name = table.Column<string>(maxLength: 256, nullable: true),
|
||||
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
|
||||
ConcurrencyStamp = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
UserName = table.Column<string>(maxLength: 256, nullable: true),
|
||||
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
|
||||
Email = table.Column<string>(maxLength: 256, nullable: true),
|
||||
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
|
||||
EmailConfirmed = table.Column<bool>(nullable: false),
|
||||
PasswordHash = table.Column<string>(nullable: true),
|
||||
SecurityStamp = table.Column<string>(nullable: true),
|
||||
ConcurrencyStamp = table.Column<string>(nullable: true),
|
||||
PhoneNumber = table.Column<string>(nullable: true),
|
||||
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
|
||||
TwoFactorEnabled = table.Column<bool>(nullable: false),
|
||||
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
|
||||
LockoutEnabled = table.Column<bool>(nullable: false),
|
||||
AccessFailedCount = table.Column<int>(nullable: false),
|
||||
FirstName = table.Column<string>(nullable: true),
|
||||
LastName = table.Column<string>(nullable: true),
|
||||
FacebookId = table.Column<long>(nullable: true),
|
||||
PictureUrl = table.Column<string>(nullable: true),
|
||||
Slug = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ServerConfig",
|
||||
schema: "admin",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
Uid = table.Column<string>(nullable: true),
|
||||
NewId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
|
||||
CreateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
UpdateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
Key = table.Column<string>(nullable: true),
|
||||
Value = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ServerConfig", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoleClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
RoleId = table.Column<string>(nullable: false),
|
||||
ClaimType = table.Column<string>(nullable: true),
|
||||
ClaimValue = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<string>(nullable: false),
|
||||
ClaimType = table.Column<string>(nullable: true),
|
||||
ClaimValue = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserLogins",
|
||||
columns: table => new
|
||||
{
|
||||
LoginProvider = table.Column<string>(nullable: false),
|
||||
ProviderKey = table.Column<string>(nullable: false),
|
||||
ProviderDisplayName = table.Column<string>(nullable: true),
|
||||
UserId = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserRoles",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(nullable: false),
|
||||
RoleId = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserTokens",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(nullable: false),
|
||||
LoginProvider = table.Column<string>(nullable: false),
|
||||
Name = table.Column<string>(nullable: false),
|
||||
Value = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ChatMessages",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
Uid = table.Column<string>(nullable: true),
|
||||
NewId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
|
||||
CreateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
UpdateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
FromUserId = table.Column<string>(nullable: true),
|
||||
ToUserId = table.Column<string>(nullable: true),
|
||||
Message = table.Column<string>(nullable: true),
|
||||
MessageSeen = table.Column<DateTime>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ChatMessages", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ChatMessages_AspNetUsers_FromUserId",
|
||||
column: x => x.FromUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_ChatMessages_AspNetUsers_ToUserId",
|
||||
column: x => x.ToUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Podcasts",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
Uid = table.Column<string>(nullable: true),
|
||||
NewId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
|
||||
CreateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
UpdateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
AppUserId = table.Column<string>(nullable: true),
|
||||
Title = table.Column<string>(nullable: true),
|
||||
Description = table.Column<string>(nullable: true),
|
||||
Slug = table.Column<string>(nullable: true),
|
||||
TemporaryImageUrl = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Podcasts", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Podcasts_AspNetUsers_AppUserId",
|
||||
column: x => x.AppUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Playlists",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
Uid = table.Column<string>(nullable: true),
|
||||
NewId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
|
||||
CreateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
UpdateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
SourceUrl = table.Column<string>(nullable: true),
|
||||
PodcastId = table.Column<int>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Playlists", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Playlists_Podcasts_PodcastId",
|
||||
column: x => x.PodcastId,
|
||||
principalTable: "Podcasts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ParsedPlaylistItems",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
Uid = table.Column<string>(nullable: true),
|
||||
NewId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
|
||||
CreateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
UpdateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
VideoId = table.Column<string>(nullable: true),
|
||||
VideoType = 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.CreateTable(
|
||||
name: "PodcastEntries",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
|
||||
Uid = table.Column<string>(nullable: true),
|
||||
NewId = table.Column<Guid>(nullable: false, defaultValueSql: "newsequentialid()"),
|
||||
CreateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
UpdateDate = table.Column<DateTime>(nullable: false, defaultValueSql: "getdate()"),
|
||||
Author = table.Column<string>(nullable: true),
|
||||
Title = table.Column<string>(nullable: true),
|
||||
Description = table.Column<string>(nullable: true),
|
||||
SourceUrl = table.Column<string>(nullable: true),
|
||||
AudioUrl = table.Column<string>(nullable: true),
|
||||
AudioLength = table.Column<float>(nullable: false),
|
||||
AudioFileSize = table.Column<long>(nullable: false),
|
||||
ImageUrl = table.Column<string>(nullable: true),
|
||||
ProcessingPayload = table.Column<string>(nullable: true),
|
||||
ProcessingStatus = table.Column<int>(nullable: false),
|
||||
Processed = table.Column<bool>(nullable: false),
|
||||
PodcastId = table.Column<int>(nullable: false),
|
||||
PlaylistId = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PodcastEntries", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_PodcastEntries_Playlists_PlaylistId",
|
||||
column: x => x.PlaylistId,
|
||||
principalTable: "Playlists",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_PodcastEntries_Podcasts_PodcastId",
|
||||
column: x => x.PodcastId,
|
||||
principalTable: "Podcasts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetRoleClaims_RoleId",
|
||||
table: "AspNetRoleClaims",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "RoleNameIndex",
|
||||
table: "AspNetRoles",
|
||||
column: "NormalizedName",
|
||||
unique: true,
|
||||
filter: "[NormalizedName] IS NOT NULL");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserClaims_UserId",
|
||||
table: "AspNetUserClaims",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserLogins_UserId",
|
||||
table: "AspNetUserLogins",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserRoles_RoleId",
|
||||
table: "AspNetUserRoles",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "EmailIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedEmail");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UserNameIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedUserName",
|
||||
unique: true,
|
||||
filter: "[NormalizedUserName] IS NOT NULL");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ChatMessages_FromUserId",
|
||||
table: "ChatMessages",
|
||||
column: "FromUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ChatMessages_ToUserId",
|
||||
table: "ChatMessages",
|
||||
column: "ToUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ParsedPlaylistItems_PlaylistId",
|
||||
table: "ParsedPlaylistItems",
|
||||
column: "PlaylistId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Playlists_PodcastId",
|
||||
table: "Playlists",
|
||||
column: "PodcastId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PodcastEntries_PlaylistId",
|
||||
table: "PodcastEntries",
|
||||
column: "PlaylistId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PodcastEntries_PodcastId",
|
||||
table: "PodcastEntries",
|
||||
column: "PodcastId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Podcasts_AppUserId",
|
||||
table: "Podcasts",
|
||||
column: "AppUserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoleClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserLogins");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ChatMessages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ParsedPlaylistItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PodcastEntries");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ServerConfig",
|
||||
schema: "admin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Playlists");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Podcasts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUsers");
|
||||
}
|
||||
}
|
||||
}
|
||||
516
server/Migrations/20180512181432_PK_OnParsedPlaylistItem.Designer.cs
generated
Normal file
516
server/Migrations/20180512181432_PK_OnParsedPlaylistItem.Designer.cs
generated
Normal file
@@ -0,0 +1,516 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PodNoms.Api.Persistence;
|
||||
|
||||
namespace PodNoms.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(PodNomsDbContext))]
|
||||
[Migration("20180512181432_PK_OnParsedPlaylistItem")]
|
||||
partial class PK_OnParsedPlaylistItem
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.0-rc1-32029")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||
.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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
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.ChatMessage", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("FromUserId");
|
||||
|
||||
b.Property<string>("Message");
|
||||
|
||||
b.Property<DateTime?>("MessageSeen");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("ToUserId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FromUserId");
|
||||
|
||||
b.HasIndex("ToUserId");
|
||||
|
||||
b.ToTable("ChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<bool>("IsProcessed");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<int>("PlaylistId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("VideoId");
|
||||
|
||||
b.Property<string>("VideoType");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.HasIndex("VideoId", "PlaylistId")
|
||||
.IsUnique()
|
||||
.HasFilter("[VideoId] IS NOT NULL");
|
||||
|
||||
b.ToTable("ParsedPlaylistItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
|
||||
b.Property<string>("SourceUrl");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("Playlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AppUserId");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("Slug");
|
||||
|
||||
b.Property<string>("TemporaryImageUrl");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("Podcasts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("AudioFileSize");
|
||||
|
||||
b.Property<float>("AudioLength");
|
||||
|
||||
b.Property<string>("AudioUrl");
|
||||
|
||||
b.Property<string>("Author");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<string>("ImageUrl");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
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")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("PodcastEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ServerConfig", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Key");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Value");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ServerConfig","admin");
|
||||
});
|
||||
|
||||
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.ChatMessage", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "FromUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("FromUserId");
|
||||
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "ToUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("ToUserId");
|
||||
});
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
38
server/Migrations/20180512181432_PK_OnParsedPlaylistItem.cs
Normal file
38
server/Migrations/20180512181432_PK_OnParsedPlaylistItem.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace PodNoms.Api.Migrations
|
||||
{
|
||||
public partial class PK_OnParsedPlaylistItem : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "VideoId",
|
||||
table: "ParsedPlaylistItems",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ParsedPlaylistItems_VideoId_PlaylistId",
|
||||
table: "ParsedPlaylistItems",
|
||||
columns: new[] { "VideoId", "PlaylistId" },
|
||||
unique: true,
|
||||
filter: "[VideoId] IS NOT NULL");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_ParsedPlaylistItems_VideoId_PlaylistId",
|
||||
table: "ParsedPlaylistItems");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "VideoId",
|
||||
table: "ParsedPlaylistItems",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldNullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
514
server/Migrations/PodNomsDbContextModelSnapshot.cs
Normal file
514
server/Migrations/PodNomsDbContextModelSnapshot.cs
Normal file
@@ -0,0 +1,514 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PodNoms.Api.Persistence;
|
||||
|
||||
namespace PodNoms.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(PodNomsDbContext))]
|
||||
partial class PodNomsDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.0-rc1-32029")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||
.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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
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()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
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.ChatMessage", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("FromUserId");
|
||||
|
||||
b.Property<string>("Message");
|
||||
|
||||
b.Property<DateTime?>("MessageSeen");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("ToUserId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FromUserId");
|
||||
|
||||
b.HasIndex("ToUserId");
|
||||
|
||||
b.ToTable("ChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ParsedPlaylistItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<bool>("IsProcessed");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<int>("PlaylistId");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("VideoId");
|
||||
|
||||
b.Property<string>("VideoType");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.HasIndex("VideoId", "PlaylistId")
|
||||
.IsUnique()
|
||||
.HasFilter("[VideoId] IS NOT NULL");
|
||||
|
||||
b.ToTable("ParsedPlaylistItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<int>("PodcastId");
|
||||
|
||||
b.Property<string>("SourceUrl");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("Playlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<string>("AppUserId");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("Slug");
|
||||
|
||||
b.Property<string>("TemporaryImageUrl");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("Podcasts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<long>("AudioFileSize");
|
||||
|
||||
b.Property<float>("AudioLength");
|
||||
|
||||
b.Property<string>("AudioUrl");
|
||||
|
||||
b.Property<string>("Author");
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Description");
|
||||
|
||||
b.Property<string>("ImageUrl");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
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")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PlaylistId");
|
||||
|
||||
b.HasIndex("PodcastId");
|
||||
|
||||
b.ToTable("PodcastEntries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PodNoms.Api.Models.ServerConfig", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime>("CreateDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Key");
|
||||
|
||||
b.Property<Guid>("NewId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValueSql("newsequentialid()");
|
||||
|
||||
b.Property<string>("Uid");
|
||||
|
||||
b.Property<DateTime>("UpdateDate")
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasDefaultValueSql("getdate()");
|
||||
|
||||
b.Property<string>("Value");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ServerConfig","admin");
|
||||
});
|
||||
|
||||
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.ChatMessage", b =>
|
||||
{
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "FromUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("FromUserId");
|
||||
|
||||
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "ToUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("ToUserId");
|
||||
});
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,9 @@ namespace PodNoms.Api.Persistence {
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
||||
base.OnModelCreating(modelBuilder);
|
||||
modelBuilder.Entity<ParsedPlaylistItem>()
|
||||
.HasIndex(p => new { p.VideoId, p.PlaylistId })
|
||||
.IsUnique(true);
|
||||
|
||||
foreach (var pb in __getColumn(modelBuilder, "CreateDate")) {
|
||||
pb.ValueGeneratedOnAdd()
|
||||
|
||||
@@ -13,7 +13,11 @@ namespace PodNoms.Api.Persistence {
|
||||
public class PlaylistRepository : GenericRepository<Playlist>, IPlaylistRepository {
|
||||
public PlaylistRepository(PodNomsDbContext context, ILogger<PlaylistRepository> logger) : base(context, logger) {
|
||||
}
|
||||
|
||||
public new async Task<Playlist> GetAsync(int id) {
|
||||
return await GetContext().Playlists
|
||||
.Include(i => i.ParsedPlaylistItems)
|
||||
.SingleOrDefaultAsync(i => i.Id == id);
|
||||
}
|
||||
public async Task<ParsedPlaylistItem> GetParsedItem(string itemId, int playlistId) {
|
||||
return await GetContext().ParsedPlaylistItems
|
||||
.Include(i => i.Playlist)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace PodNoms.Api.Services.Jobs {
|
||||
public static void BootstrapJobs() {
|
||||
RecurringJob.AddOrUpdate<ClearOrphanAudioJob>(x => x.Execute(), Cron.Daily(1));
|
||||
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(3), TimeSpan.FromSeconds(1));
|
||||
RecurringJob.AddOrUpdate<ProcessPlaylistsJob>(x => x.Execute(), Cron.Daily(2));
|
||||
}
|
||||
}
|
||||
|
||||
150
server/Services/Jobs/MutexAttribute.cs
Normal file
150
server/Services/Jobs/MutexAttribute.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Hangfire.Common;
|
||||
using Hangfire.States;
|
||||
using Hangfire.Storage;
|
||||
|
||||
namespace PodNoms.Api.Services.Jobs {
|
||||
public class MutexAttribute : JobFilterAttribute, IElectStateFilter, IApplyStateFilter {
|
||||
private static readonly TimeSpan DistributedLockTimeout = TimeSpan.FromMinutes(1);
|
||||
|
||||
private readonly string _resource;
|
||||
|
||||
public MutexAttribute(string resource) {
|
||||
_resource = resource;
|
||||
RetryInSeconds = 15;
|
||||
}
|
||||
|
||||
public int RetryInSeconds { get; set; }
|
||||
public int MaxAttempts { get; set; }
|
||||
|
||||
public void OnStateElection(ElectStateContext context) {
|
||||
// We are intercepting transitions to the Processed state, that is performed by
|
||||
// a worker just before processing a job. During the state election phase we can
|
||||
// change the target state to another one, causing a worker not to process the
|
||||
// backgorund job.
|
||||
if (context.CandidateState.Name != ProcessingState.StateName ||
|
||||
context.BackgroundJob.Job == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This filter requires an extended set of storage operations. It's supported
|
||||
// by all the official storages, and many of the community-based ones.
|
||||
var storageConnection = context.Connection as JobStorageConnection;
|
||||
if (storageConnection == null) {
|
||||
throw new NotSupportedException("This version of storage doesn't support extended methods. Please try to update to the latest version.");
|
||||
}
|
||||
|
||||
string blockedBy;
|
||||
|
||||
try {
|
||||
// Distributed lock is needed here only to prevent a race condition, when another
|
||||
// worker picks up a background job with the same resource between GET and SET
|
||||
// operations.
|
||||
// There will be no race condition, when two or more workers pick up background job
|
||||
// with the same id, because state transitions are protected with distributed lock
|
||||
// themselves.
|
||||
using (AcquireDistributedSetLock(context.Connection, context.BackgroundJob.Job.Args)) {
|
||||
// Resource set contains a background job id that acquired a mutex for the resource.
|
||||
// We are getting only one element to see what background job blocked the invocation.
|
||||
var range = storageConnection.GetRangeFromSet(
|
||||
GetResourceKey(context.BackgroundJob.Job.Args),
|
||||
0,
|
||||
0);
|
||||
|
||||
blockedBy = range.Count > 0 ? range[0] : null;
|
||||
|
||||
// We should permit an invocation only when the set is empty, or if current background
|
||||
// job is already owns a resource. This may happen, when the localTransaction succeeded,
|
||||
// but outer transaction was failed.
|
||||
if (blockedBy == null || blockedBy == context.BackgroundJob.Id) {
|
||||
// We need to commit the changes inside a distributed lock, otherwise it's
|
||||
// useless. So we create a local transaction instead of using the
|
||||
// context.Transaction property.
|
||||
var localTransaction = context.Connection.CreateWriteTransaction();
|
||||
|
||||
// Add the current background job identifier to a resource set. This means
|
||||
// that resource is owned by the current background job. Identifier will be
|
||||
// removed only on failed state, or in one of final states (succeeded or
|
||||
// deleted).
|
||||
localTransaction.AddToSet(GetResourceKey(context.BackgroundJob.Job.Args), context.BackgroundJob.Id);
|
||||
localTransaction.Commit();
|
||||
|
||||
// Invocation is permitted, and we did all the required things.
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (DistributedLockTimeoutException) {
|
||||
// We weren't able to acquire a distributed lock within a specified window. This may
|
||||
// be caused by network delays, storage outages or abandoned locks in some storages.
|
||||
// Since it is required to expire abandoned locks after some time, we can simply
|
||||
// postpone the invocation.
|
||||
context.CandidateState = new ScheduledState(TimeSpan.FromSeconds(RetryInSeconds)) {
|
||||
Reason = "Couldn't acquire a distributed lock for mutex: timeout exceeded"
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Background job execution is blocked. We should change the target state either to
|
||||
// the Scheduled or to the Deleted one, depending on current retry attempt number.
|
||||
var currentAttempt = context.GetJobParameter<int>("MutexAttempt") + 1;
|
||||
context.SetJobParameter("MutexAttempt", currentAttempt);
|
||||
|
||||
context.CandidateState = MaxAttempts == 0 || currentAttempt <= MaxAttempts
|
||||
? CreateScheduledState(blockedBy, currentAttempt)
|
||||
: CreateDeletedState(blockedBy);
|
||||
}
|
||||
|
||||
public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction) {
|
||||
if (context.BackgroundJob.Job == null) return;
|
||||
|
||||
if (context.OldStateName == ProcessingState.StateName) {
|
||||
using (AcquireDistributedSetLock(context.Connection, context.BackgroundJob.Job.Args)) {
|
||||
var localTransaction = context.Connection.CreateWriteTransaction();
|
||||
localTransaction.RemoveFromSet(GetResourceKey(context.BackgroundJob.Job.Args), context.BackgroundJob.Id);
|
||||
|
||||
localTransaction.Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction) {
|
||||
}
|
||||
|
||||
private static DeletedState CreateDeletedState(string blockedBy) {
|
||||
return new DeletedState {
|
||||
Reason = $"Execution was blocked by background job {blockedBy}, all attempts exhausted"
|
||||
};
|
||||
}
|
||||
|
||||
private IState CreateScheduledState(string blockedBy, int currentAttempt) {
|
||||
var reason = $"Execution is blocked by background job {blockedBy}, retry attempt: {currentAttempt}";
|
||||
|
||||
if (MaxAttempts > 0) {
|
||||
reason += $"/{MaxAttempts}";
|
||||
}
|
||||
|
||||
return new ScheduledState(TimeSpan.FromSeconds(RetryInSeconds)) {
|
||||
Reason = reason
|
||||
};
|
||||
}
|
||||
|
||||
private IDisposable AcquireDistributedSetLock(IStorageConnection connection, IEnumerable<object> args) {
|
||||
return connection.AcquireDistributedLock(GetDistributedLockKey(args), DistributedLockTimeout);
|
||||
}
|
||||
|
||||
private string GetDistributedLockKey(IEnumerable<object> args) {
|
||||
return $"extension:job-mutex:lock:{GetKeyFormat(args, _resource)}";
|
||||
}
|
||||
|
||||
private string GetResourceKey(IEnumerable<object> args) {
|
||||
return $"extension:job-mutex:set:{GetKeyFormat(args, _resource)}";
|
||||
}
|
||||
|
||||
private static string GetKeyFormat(IEnumerable<object> args, string keyFormat) {
|
||||
return String.Format(keyFormat, args.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,16 +33,23 @@ namespace PodNoms.Api.Services.Jobs {
|
||||
this._helpersSettings = _helpersSettings.Value;
|
||||
this._logger = logger;
|
||||
}
|
||||
[Mutex("ProcessPlaylistItemJob")]
|
||||
public async Task Execute() {
|
||||
var items = await _playlistRepository.GetUnprocessedItems();
|
||||
foreach (var item in items) {
|
||||
await ExecuteForItem(item.VideoId, item.Playlist.Id);
|
||||
}
|
||||
}
|
||||
[Mutex("ProcessPlaylistItemJob")]
|
||||
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}";
|
||||
if (item != null && !string.IsNullOrEmpty(item.VideoType) &&
|
||||
(item.VideoType.Equals("youtube") || item.VideoType.Equals("mixcloud"))) {
|
||||
var url = item.VideoType.Equals("youtube") ? $"https://www.youtube.com/watch?v={item.VideoId}"
|
||||
: item.VideoType.Equals("mixcloud") ? $"https://mixcloud.com/{item.VideoId}" : string.Empty;
|
||||
if (string.IsNullOrEmpty(url)) {
|
||||
_logger.LogError($"Unknown video type for ParsedItem: {itemId} - {playlistId}");
|
||||
} else {
|
||||
var downloader = new AudioDownloader(url, _helpersSettings.Downloader);
|
||||
var info = downloader.GetInfo();
|
||||
if (info == AudioType.Valid) {
|
||||
@@ -78,3 +85,4 @@ namespace PodNoms.Api.Services.Jobs {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -45,23 +46,24 @@ namespace PodNoms.Api.Services.Jobs {
|
||||
}
|
||||
}
|
||||
public async Task Execute(int playlistId) {
|
||||
|
||||
try {
|
||||
var playlist = await _playlistRepository.GetAsync(playlistId);
|
||||
var resultList = new List<ParsedItemResult>();
|
||||
|
||||
var downloader = new AudioDownloader(playlist.SourceUrl, _helpersSettings.Downloader);
|
||||
var info = downloader.GetInfo();
|
||||
var id = ((PlaylistDownloadInfo)downloader.RawProperties).Id;
|
||||
if (info == AudioType.Playlist && downloader.RawProperties is PlaylistDownloadInfo) {
|
||||
var id = ((PlaylistDownloadInfo)downloader.RawProperties)?.Id;
|
||||
if (!string.IsNullOrEmpty(id)) {
|
||||
if (YouTubeParser.ValidateUrl(playlist.SourceUrl)) {
|
||||
var searchTerm = (playlist.SourceUrl.Contains("/user/")) ? "forUsername" : "id";
|
||||
resultList = await _youTubeParser.GetPlaylistEntriesForId(id);
|
||||
//make sure the items are sorted in ascending date order
|
||||
//so they will be processed in the order they were created
|
||||
} else if (MixcloudParser.ValidateUrl(playlist.SourceUrl)) {
|
||||
resultList = await _mixcloudParser.GetEntries(id);
|
||||
}
|
||||
resultList = await _mixcloudParser.GetEntries(playlist.SourceUrl);
|
||||
}
|
||||
if (resultList != null) {
|
||||
//order in reverse so the newest item is added first
|
||||
foreach (var item in resultList?.OrderBy(r => r.UploadDate)) {
|
||||
if (!playlist.ParsedPlaylistItems.Any(p => p.VideoId == item.Id)) {
|
||||
playlist.ParsedPlaylistItems.Add(new ParsedPlaylistItem {
|
||||
@@ -69,10 +71,14 @@ namespace PodNoms.Api.Services.Jobs {
|
||||
VideoType = item.VideoType
|
||||
});
|
||||
await _unitOfWork.CompleteAsync();
|
||||
|
||||
BackgroundJob.Enqueue<ProcessPlaylistItemJob>(service => service.ExecuteForItem(item.Id, playlist.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,5 +17,19 @@ namespace PodNoms.Api.Utils {
|
||||
}
|
||||
return file;
|
||||
}
|
||||
public static string UrlCombine(string url1, string url2) {
|
||||
if (url1.Length == 0) {
|
||||
return url2;
|
||||
}
|
||||
|
||||
if (url2.Length == 0) {
|
||||
return url1;
|
||||
}
|
||||
|
||||
url1 = url1.TrimEnd('/', '\\');
|
||||
url2 = url2.TrimStart('/', '\\');
|
||||
|
||||
return string.Format("{0}/{1}", url1, url2);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
server/Utils/RemoteParsers/MixcloudJsonConverter.cs
Normal file
15
server/Utils/RemoteParsers/MixcloudJsonConverter.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||
internal static class MixcloudJsonConverter {
|
||||
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings {
|
||||
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||
DateParseHandling = DateParseHandling.None,
|
||||
Converters = {
|
||||
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,31 +4,58 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Security.Policy;
|
||||
|
||||
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||
public class MixcloudParser {
|
||||
const string URL_REGEX = @"^(http(s)?:\/\/)?((w){3}.)?mixcloud?(\.com)?\/.+";
|
||||
static string[] VALID_PATHS = new string[] {
|
||||
"stream", "uploads", "favorites", "listens", "playlists"
|
||||
};
|
||||
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<MixcloudParser> _logger;
|
||||
|
||||
public MixcloudParser(IHttpClientFactory httpClientFactory) {
|
||||
public MixcloudParser(IHttpClientFactory httpClientFactory, ILogger<MixcloudParser> logger) {
|
||||
this._logger = logger;
|
||||
this._httpClientFactory = httpClientFactory;
|
||||
}
|
||||
public static bool ValidateUrl(string url) {
|
||||
var regex = new Regex(URL_REGEX);
|
||||
var result = regex.Match(url);
|
||||
return result.Success;
|
||||
try {
|
||||
var uri = new Uri(url);
|
||||
if (uri.Host.EndsWith("mixcloud.com")) {
|
||||
var path = uri.Segments[uri.Segments.Length - 1].ToString().TrimEnd(new[] { '/' });
|
||||
return (VALID_PATHS.Any(path.Equals)) || uri.Segments.Length == 1;
|
||||
}
|
||||
public async Task<List<ParsedItemResult>> GetEntries(string identifier) {
|
||||
} catch (Exception) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public async Task<List<ParsedItemResult>> GetEntries(string url) {
|
||||
try {
|
||||
var path = new Uri(url).Segments.First(s => s != "/");
|
||||
var newUrl = HttpUtils.UrlCombine(path, "cloudcasts");
|
||||
var client = _httpClientFactory.CreateClient("mixcloud");
|
||||
var result = await client.GetAsync(identifier);
|
||||
var result = await client.GetAsync(newUrl);
|
||||
|
||||
if (result.IsSuccessStatusCode) {
|
||||
var typed = JsonConvert.DeserializeObject<MixcloudResult>(await result.Content.ReadAsStringAsync());
|
||||
return typed.data[0].cloudcasts.Select(c => new ParsedItemResult {
|
||||
Id = c.key,
|
||||
var body = await result.Content.ReadAsStringAsync();
|
||||
Console.WriteLine(body);
|
||||
System.IO.File.WriteAllText("/tmp/dump.json", body);
|
||||
var typed = JsonConvert.DeserializeObject<Welcome>(body, MixcloudJsonConverter.Settings);
|
||||
// var typed = JsonConvert.DeserializeObject<MixcloudResult>(body);
|
||||
var data = typed.Data.OrderByDescending(p => p.UpdatedTime)
|
||||
.Select(c => new ParsedItemResult {
|
||||
Id = c.Key,
|
||||
VideoType = "mixcloud",
|
||||
UploadDate = c.updated_time
|
||||
}).ToList();
|
||||
UploadDate = c.UpdatedTime.DateTime
|
||||
}).Take(10).ToList();
|
||||
return data;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_logger.LogError($"Error parsing url: {url}");
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,75 +1,131 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PodNoms.Api.Utils.RemoteParsers {
|
||||
public partial class Welcome {
|
||||
[JsonProperty("paging")]
|
||||
public Paging Paging { get; set; }
|
||||
|
||||
[JsonProperty("data")]
|
||||
public Datum[] Data { get; set; }
|
||||
|
||||
public class Paging {
|
||||
public string previous { get; set; }
|
||||
public string next { get; set; }
|
||||
[JsonProperty("name")]
|
||||
public string Name { 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 partial class Datum {
|
||||
[JsonProperty("tags")]
|
||||
public Tag[] Tags { get; set; }
|
||||
|
||||
[JsonProperty("play_count")]
|
||||
public long PlayCount { get; set; }
|
||||
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
|
||||
[JsonProperty("key")]
|
||||
public string Key { get; set; }
|
||||
|
||||
[JsonProperty("created_time")]
|
||||
public DateTimeOffset CreatedTime { get; set; }
|
||||
|
||||
[JsonProperty("audio_length")]
|
||||
public long AudioLength { get; set; }
|
||||
|
||||
[JsonProperty("slug")]
|
||||
public string Slug { get; set; }
|
||||
|
||||
[JsonProperty("favorite_count")]
|
||||
public long FavoriteCount { get; set; }
|
||||
|
||||
[JsonProperty("listener_count")]
|
||||
public long ListenerCount { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("pictures")]
|
||||
public Pictures Pictures { get; set; }
|
||||
|
||||
[JsonProperty("repost_count")]
|
||||
public long RepostCount { get; set; }
|
||||
|
||||
[JsonProperty("updated_time")]
|
||||
public DateTimeOffset UpdatedTime { get; set; }
|
||||
|
||||
[JsonProperty("comment_count")]
|
||||
public long CommentCount { 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 partial class Pictures {
|
||||
[JsonProperty("medium")]
|
||||
public string Medium { get; set; }
|
||||
|
||||
[JsonProperty("768wx768h", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string The768Wx768H { get; set; }
|
||||
|
||||
[JsonProperty("320wx320h")]
|
||||
public string The320Wx320H { get; set; }
|
||||
|
||||
[JsonProperty("extra_large")]
|
||||
public string ExtraLarge { get; set; }
|
||||
|
||||
[JsonProperty("large")]
|
||||
public string Large { get; set; }
|
||||
|
||||
[JsonProperty("640wx640h")]
|
||||
public string The640Wx640H { get; set; }
|
||||
|
||||
[JsonProperty("medium_mobile")]
|
||||
public string MediumMobile { get; set; }
|
||||
|
||||
[JsonProperty("small")]
|
||||
public string Small { get; set; }
|
||||
|
||||
[JsonProperty("1024wx1024h", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string The1024Wx1024H { get; set; }
|
||||
|
||||
[JsonProperty("thumbnail")]
|
||||
public string Thumbnail { get; set; }
|
||||
}
|
||||
|
||||
public class Tag {
|
||||
public string url { get; set; }
|
||||
public string name { get; set; }
|
||||
public string key { get; set; }
|
||||
public partial class Tag {
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("key")]
|
||||
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 partial class User {
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("key")]
|
||||
public string Key { get; set; }
|
||||
|
||||
[JsonProperty("pictures")]
|
||||
public Pictures Pictures { 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 partial class Paging {
|
||||
[JsonProperty("previous")]
|
||||
public string Previous { 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; }
|
||||
[JsonProperty("next")]
|
||||
public string Next { get; set; }
|
||||
}
|
||||
|
||||
public class MixcloudResult {
|
||||
public Paging paging { get; set; }
|
||||
public IList<Datum> data { get; set; }
|
||||
public string name { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user