mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
parent
70e621a528
commit
209bd9a0b8
13 changed files with 842 additions and 18 deletions
|
|
@ -16,4 +16,6 @@
|
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=appsettings/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wayback/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Waybacks/@EntryIndexedValue">True</s:Boolean>
|
||||
</wpf:ResourceDictionary>
|
||||
645
src/FilterLists.Api/Migrations/20180824155224_AddWaybackTimestamp.Designer.cs
generated
Normal file
645
src/FilterLists.Api/Migrations/20180824155224_AddWaybackTimestamp.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
// <auto-generated />
|
||||
|
||||
using System;
|
||||
using FilterLists.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace FilterLists.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(FilterListsDbContext))]
|
||||
[Migration("20180824155224_AddWaybackTimestamp")]
|
||||
partial class AddWaybackTimestamp
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.FilterList", b =>
|
||||
{
|
||||
b.Property<ushort>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("SMALLINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<bool>("CantSnapshot");
|
||||
|
||||
b.Property<string>("ChatUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DescriptionSourceUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("DiscontinuedDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("DATE")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("DonateUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("EmailAddress")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(126)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("ForumUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("HomeUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("IssuesUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte>("LicenseId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasDefaultValue((byte)5);
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("VARCHAR(126)");
|
||||
|
||||
b.Property<string>("PolicyUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("PublishedDate")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("DATE")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("SubmissionUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte?>("SyntaxId");
|
||||
|
||||
b.Property<string>("ViewUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LicenseId");
|
||||
|
||||
b.HasIndex("SyntaxId");
|
||||
|
||||
b.ToTable("filterlists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
|
||||
{
|
||||
b.Property<ushort>("FilterListId");
|
||||
|
||||
b.Property<ushort>("LanguageId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("FilterListId", "LanguageId");
|
||||
|
||||
b.HasIndex("LanguageId");
|
||||
|
||||
b.ToTable("filterlists_languages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListMaintainer", b =>
|
||||
{
|
||||
b.Property<ushort>("FilterListId");
|
||||
|
||||
b.Property<ushort>("MaintainerId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("FilterListId", "MaintainerId");
|
||||
|
||||
b.HasIndex("MaintainerId");
|
||||
|
||||
b.ToTable("filterlists_maintainers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListTag", b =>
|
||||
{
|
||||
b.Property<ushort>("FilterListId");
|
||||
|
||||
b.Property<byte>("TagId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("FilterListId", "TagId");
|
||||
|
||||
b.HasIndex("TagId");
|
||||
|
||||
b.ToTable("filterlists_tags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Fork", b =>
|
||||
{
|
||||
b.Property<ushort>("ForkFilterListId");
|
||||
|
||||
b.Property<ushort>("UpstreamFilterListId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("ForkFilterListId", "UpstreamFilterListId");
|
||||
|
||||
b.HasIndex("UpstreamFilterListId");
|
||||
|
||||
b.ToTable("forks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Merge", b =>
|
||||
{
|
||||
b.Property<ushort>("MergeFilterListId");
|
||||
|
||||
b.Property<ushort>("UpstreamFilterListId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("MergeFilterListId", "UpstreamFilterListId");
|
||||
|
||||
b.HasIndex("UpstreamFilterListId");
|
||||
|
||||
b.ToTable("merges");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SnapshotRule", b =>
|
||||
{
|
||||
b.Property<uint>("SnapshotId");
|
||||
|
||||
b.Property<uint>("RuleId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("SnapshotId", "RuleId");
|
||||
|
||||
b.HasIndex("RuleId");
|
||||
|
||||
b.ToTable("snapshots_rules");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SoftwareSyntax", b =>
|
||||
{
|
||||
b.Property<byte>("SyntaxId");
|
||||
|
||||
b.Property<byte>("SoftwareId");
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.HasKey("SyntaxId", "SoftwareId");
|
||||
|
||||
b.HasIndex("SoftwareId");
|
||||
|
||||
b.ToTable("software_syntaxes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Language", b =>
|
||||
{
|
||||
b.Property<ushort>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("SMALLINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("Iso6391")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(2)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("Iso6392")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(3)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("Iso6392B")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(3)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("Iso6392T")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(3)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("Iso6393")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(3)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("LocalName")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(126)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(126)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("languages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.License", b =>
|
||||
{
|
||||
b.Property<byte>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TINYINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("DescriptionUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("VARCHAR(126)");
|
||||
|
||||
b.Property<bool>("PermissiveAdaptation");
|
||||
|
||||
b.Property<bool>("PermissiveCommercial");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("licenses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Maintainer", b =>
|
||||
{
|
||||
b.Property<ushort>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("SMALLINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("EmailAddress")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(126)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<string>("HomeUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("VARCHAR(126)");
|
||||
|
||||
b.Property<string>("TwitterHandle")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("VARCHAR(126)")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("maintainers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Rule", b =>
|
||||
{
|
||||
b.Property<uint>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("Raw")
|
||||
.IsRequired()
|
||||
.HasColumnType("LONGTEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("rules");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Snapshot", b =>
|
||||
{
|
||||
b.Property<uint>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("MEDIUMINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<ushort>("FilterListId");
|
||||
|
||||
b.Property<ushort?>("HttpStatusCode")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("SMALLINT UNSIGNED")
|
||||
.HasDefaultValueSql("NULL");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<bool>("WasSuccessful");
|
||||
|
||||
b.Property<DateTime?>("WaybackTimestamp")
|
||||
.HasColumnType("TIMESTAMP");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FilterListId");
|
||||
|
||||
b.ToTable("snapshots");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Software", b =>
|
||||
{
|
||||
b.Property<byte>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TINYINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("DownloadUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("HomeUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("VARCHAR(126)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("software");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Syntax", b =>
|
||||
{
|
||||
b.Property<byte>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TINYINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("DefinitionUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("VARCHAR(126)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("syntaxes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Tag", b =>
|
||||
{
|
||||
b.Property<byte>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TINYINT UNSIGNED")
|
||||
.HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
|
||||
|
||||
b.Property<DateTime?>("CreatedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp()");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ModifiedDateUtc")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("TIMESTAMP")
|
||||
.HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("VARCHAR(126)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("tags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.FilterList", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.License", "License")
|
||||
.WithMany("FilterLists")
|
||||
.HasForeignKey("LicenseId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.Syntax", "Syntax")
|
||||
.WithMany("FilterLists")
|
||||
.HasForeignKey("SyntaxId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
|
||||
.WithMany("FilterListLanguages")
|
||||
.HasForeignKey("FilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.Language", "Language")
|
||||
.WithMany("FilterListLanguages")
|
||||
.HasForeignKey("LanguageId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListMaintainer", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
|
||||
.WithMany("FilterListMaintainers")
|
||||
.HasForeignKey("FilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.Maintainer", "Maintainer")
|
||||
.WithMany("FilterListMaintainers")
|
||||
.HasForeignKey("MaintainerId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListTag", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
|
||||
.WithMany("FilterListTags")
|
||||
.HasForeignKey("FilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.Tag", "Tag")
|
||||
.WithMany("FilterListTags")
|
||||
.HasForeignKey("TagId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Fork", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "ForkFilterList")
|
||||
.WithMany("ForkFilterLists")
|
||||
.HasForeignKey("ForkFilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "UpstreamFilterList")
|
||||
.WithMany("UpstreamForkFilterLists")
|
||||
.HasForeignKey("UpstreamFilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Merge", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "MergeFilterList")
|
||||
.WithMany("MergeFilterLists")
|
||||
.HasForeignKey("MergeFilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "UpstreamFilterList")
|
||||
.WithMany("UpstreamMergeFilterLists")
|
||||
.HasForeignKey("UpstreamFilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SnapshotRule", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.Rule", "Rule")
|
||||
.WithMany("SnapshotRules")
|
||||
.HasForeignKey("RuleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.Snapshot", "Snapshot")
|
||||
.WithMany("SnapshotRules")
|
||||
.HasForeignKey("SnapshotId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SoftwareSyntax", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.Software", "Software")
|
||||
.WithMany("SoftwareSyntaxes")
|
||||
.HasForeignKey("SoftwareId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("FilterLists.Data.Entities.Syntax", "Syntax")
|
||||
.WithMany("SoftwareSyntaxes")
|
||||
.HasForeignKey("SyntaxId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("FilterLists.Data.Entities.Snapshot", b =>
|
||||
{
|
||||
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
|
||||
.WithMany("Snapshots")
|
||||
.HasForeignKey("FilterListId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace FilterLists.Api.Migrations
|
||||
{
|
||||
public partial class AddWaybackTimestamp : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
"WaybackTimestamp",
|
||||
"snapshots",
|
||||
"TIMESTAMP",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
"WaybackTimestamp",
|
||||
"snapshots");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -421,6 +421,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
|
|||
|
||||
b.Property<bool>("WasSuccessful");
|
||||
|
||||
b.Property<DateTime?>("WaybackTimestamp")
|
||||
.HasColumnType("TIMESTAMP");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FilterListId");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FilterLists.Data.Entities.Junctions;
|
||||
|
||||
namespace FilterLists.Data.Entities
|
||||
|
|
@ -10,5 +11,6 @@ public class Snapshot : BaseEntity
|
|||
public uint? HttpStatusCode { get; set; }
|
||||
public bool WasSuccessful { get; set; }
|
||||
public ICollection<SnapshotRule> SnapshotRules { get; set; }
|
||||
public DateTime? WaybackTimestamp { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,8 @@ public override void Configure(EntityTypeBuilder<Snapshot> entityTypeBuilder)
|
|||
entityTypeBuilder.Property(x => x.HttpStatusCode)
|
||||
.HasColumnType("SMALLINT UNSIGNED")
|
||||
.HasDefaultValueSql("NULL");
|
||||
entityTypeBuilder.Property(x => x.WaybackTimestamp)
|
||||
.HasColumnType("TIMESTAMP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,5 +8,8 @@ public static class StringExtensions
|
|||
public static bool IsValidHttpOrHttpsUrl(this string source) =>
|
||||
Uri.TryCreate(source, UriKind.Absolute, out var uriResult) &&
|
||||
new[] {Uri.UriSchemeHttps, Uri.UriSchemeHttp}.Contains(uriResult.Scheme);
|
||||
|
||||
public static int GetNthIndexOfChar(this string s, int n, char t) =>
|
||||
s.TakeWhile(c => (n -= c == t ? 1 : 0) > 0).Count();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FilterLists.Services.Snapshot.Models.Wayback
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class ArchivedSnapshots
|
||||
{
|
||||
[JsonProperty("closest")]
|
||||
public Closest Closest { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FilterLists.Services.Snapshot.Models.Wayback
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class Availability
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("archived_snapshots")]
|
||||
public ArchivedSnapshots ArchivedSnapshots { get; set; }
|
||||
}
|
||||
}
|
||||
21
src/FilterLists.Services/Snapshot/Models/Wayback/Closest.cs
Normal file
21
src/FilterLists.Services/Snapshot/Models/Wayback/Closest.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FilterLists.Services.Snapshot.Models.Wayback
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class Closest
|
||||
{
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[JsonProperty("available")]
|
||||
public bool Available { get; set; }
|
||||
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("timestamp")]
|
||||
public string Timestamp { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
using FilterLists.Data;
|
||||
using FilterLists.Services.Extensions;
|
||||
using FilterLists.Services.Snapshot.Models;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.ApplicationInsights;
|
||||
using MoreLinq;
|
||||
|
||||
|
|
@ -18,25 +19,36 @@ public class Snapshot
|
|||
{
|
||||
private const int BatchSize = 500;
|
||||
private readonly FilterListsDbContext dbContext;
|
||||
private readonly string listViewUrl;
|
||||
private readonly Data.Entities.Snapshot snapEntity;
|
||||
public readonly FilterListViewUrlDto List;
|
||||
protected readonly Data.Entities.Snapshot SnapEntity;
|
||||
private readonly TelemetryClient telemetryClient;
|
||||
private readonly string uaString;
|
||||
private HashSet<string> lines;
|
||||
protected string ListUrl;
|
||||
|
||||
public Snapshot()
|
||||
{
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public Snapshot(FilterListsDbContext dbContext, FilterListViewUrlDto list, string uaString)
|
||||
{
|
||||
this.dbContext = dbContext;
|
||||
listViewUrl = list.ViewUrl;
|
||||
snapEntity = new Data.Entities.Snapshot {FilterListId = list.Id};
|
||||
List = list;
|
||||
ListUrl = list.ViewUrl;
|
||||
SnapEntity = new Data.Entities.Snapshot {FilterListId = list.Id};
|
||||
this.uaString = uaString;
|
||||
telemetryClient = new TelemetryClient();
|
||||
}
|
||||
|
||||
public async Task TrySaveAsync()
|
||||
public bool WasSuccessful => SnapEntity.WasSuccessful;
|
||||
|
||||
public virtual async Task TrySaveAsync() => await TrySaveAsyncBase();
|
||||
|
||||
protected async Task TrySaveAsyncBase()
|
||||
{
|
||||
await AddSnapEntity();
|
||||
if (!listViewUrl.IsValidHttpOrHttpsUrl())
|
||||
if (!ListUrl.IsValidHttpOrHttpsUrl())
|
||||
return;
|
||||
try
|
||||
{
|
||||
|
|
@ -50,7 +62,7 @@ public async Task TrySaveAsync()
|
|||
|
||||
private async Task AddSnapEntity()
|
||||
{
|
||||
dbContext.Snapshots.Add(snapEntity);
|
||||
dbContext.Snapshots.Add(SnapEntity);
|
||||
await dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +89,7 @@ private async Task TryGetLines()
|
|||
}
|
||||
catch (WebException we)
|
||||
{
|
||||
snapEntity.HttpStatusCode = (uint)((HttpWebResponse)we.Response).StatusCode;
|
||||
SnapEntity.HttpStatusCode = (uint)((HttpWebResponse)we.Response).StatusCode;
|
||||
await dbContext.SaveChangesAsync();
|
||||
TrackException(we);
|
||||
}
|
||||
|
|
@ -88,8 +100,8 @@ private async Task GetLines()
|
|||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(uaString);
|
||||
var response = await httpClient.GetAsync(listViewUrl, HttpCompletionOption.ResponseHeadersRead);
|
||||
snapEntity.HttpStatusCode = (uint)response.StatusCode;
|
||||
var response = await httpClient.GetAsync(ListUrl, HttpCompletionOption.ResponseHeadersRead);
|
||||
SnapEntity.HttpStatusCode = (uint)response.StatusCode;
|
||||
response.EnsureSuccessStatusCode();
|
||||
lines = new HashSet<string>();
|
||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||
|
|
@ -109,7 +121,7 @@ private async Task SaveInBatches()
|
|||
}
|
||||
|
||||
private IEnumerable<SnapshotBatch> CreateBatches() =>
|
||||
lines.Batch(BatchSize).Select(b => new SnapshotBatch(dbContext, b, snapEntity));
|
||||
lines.Batch(BatchSize).Select(b => new SnapshotBatch(dbContext, b, SnapEntity));
|
||||
|
||||
private static async Task SaveBatches(IEnumerable<SnapshotBatch> batches)
|
||||
{
|
||||
|
|
@ -119,7 +131,7 @@ private static async Task SaveBatches(IEnumerable<SnapshotBatch> batches)
|
|||
|
||||
private async Task SetSuccessful()
|
||||
{
|
||||
snapEntity.WasSuccessful = true;
|
||||
SnapEntity.WasSuccessful = true;
|
||||
await dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace FilterLists.Services.Snapshot
|
|||
public class SnapshotService : Service
|
||||
{
|
||||
private readonly DateTime yesterday = DateTime.UtcNow.AddDays(-1);
|
||||
private string uaString;
|
||||
|
||||
public SnapshotService(FilterListsDbContext dbContext, IConfigurationProvider mapConfig)
|
||||
: base(dbContext, mapConfig)
|
||||
|
|
@ -21,10 +22,11 @@ public SnapshotService(FilterListsDbContext dbContext, IConfigurationProvider ma
|
|||
|
||||
public async Task CaptureAsync(int batchSize)
|
||||
{
|
||||
uaString = await UserAgentService.GetMostPopularString();
|
||||
var lists = await GetListsToCapture(batchSize);
|
||||
var uaString = await UserAgentService.GetMostPopularString();
|
||||
var snaps = CreateSnaps(lists, uaString);
|
||||
await SaveSnaps(snaps);
|
||||
var snaps = await CreateAndSaveSnaps<Snapshot>(lists);
|
||||
var listsToRetry = snaps.Where(s => !s.WasSuccessful).Select(s => s.List);
|
||||
await CreateAndSaveSnaps<SnapshotWayback>(listsToRetry);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<FilterListViewUrlDto>> GetListsToCapture(int batchSize) =>
|
||||
|
|
@ -49,8 +51,17 @@ await DbContext
|
|||
.ProjectTo<FilterListViewUrlDto>(MapConfig)
|
||||
.ToListAsync();
|
||||
|
||||
private IEnumerable<Snapshot> CreateSnaps(IEnumerable<FilterListViewUrlDto> lists, string uaString) =>
|
||||
lists.Select(l => new Snapshot(DbContext, l, uaString));
|
||||
private async Task<List<TSnap>> CreateAndSaveSnaps<TSnap>(IEnumerable<FilterListViewUrlDto> lists)
|
||||
where TSnap : Snapshot, new()
|
||||
{
|
||||
var snaps = CreateSnaps<TSnap>(lists).ToList();
|
||||
await SaveSnaps(snaps);
|
||||
return snaps;
|
||||
}
|
||||
|
||||
private IEnumerable<TSnap> CreateSnaps<TSnap>(IEnumerable<FilterListViewUrlDto> lists)
|
||||
where TSnap : Snapshot, new() =>
|
||||
lists.Select(l => Activator.CreateInstance(typeof(TSnap), DbContext, l, uaString) as TSnap);
|
||||
|
||||
private static async Task SaveSnaps(IEnumerable<Snapshot> snaps)
|
||||
{
|
||||
|
|
|
|||
72
src/FilterLists.Services/Snapshot/SnapshotWayback.cs
Normal file
72
src/FilterLists.Services/Snapshot/SnapshotWayback.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FilterLists.Data;
|
||||
using FilterLists.Services.Extensions;
|
||||
using FilterLists.Services.Snapshot.Models;
|
||||
using FilterLists.Services.Snapshot.Models.Wayback;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace FilterLists.Services.Snapshot
|
||||
{
|
||||
public class SnapshotWayback : Snapshot
|
||||
{
|
||||
private const string WaybackAvailabilityApiUrlPrefix = "https://archive.org/wayback/available?url=";
|
||||
|
||||
public SnapshotWayback()
|
||||
{
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public SnapshotWayback(FilterListsDbContext dbContext, FilterListViewUrlDto list, string uaString)
|
||||
: base(dbContext, list, uaString)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task TrySaveAsync()
|
||||
{
|
||||
await UpdateWaybackData();
|
||||
await TrySaveAsyncBase();
|
||||
}
|
||||
|
||||
private async Task UpdateWaybackData()
|
||||
{
|
||||
var availability = await GetWaybackAvailability();
|
||||
var closest = availability.ArchivedSnapshots?.Closest;
|
||||
if (closest != null)
|
||||
{
|
||||
UpdateViewUrl(closest);
|
||||
UpdateTimestamp(closest);
|
||||
}
|
||||
else
|
||||
{
|
||||
ListUrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Availability> GetWaybackAvailability()
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
var url = WaybackAvailabilityApiUrlPrefix + ListUrl;
|
||||
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
var jsonString = await response.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<Availability>(jsonString);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateViewUrl(Closest closest)
|
||||
{
|
||||
var waybackUrl = closest.Url;
|
||||
var indexOfUrlModification = waybackUrl.GetNthIndexOfChar(5, '/');
|
||||
const string urlModification = "if_";
|
||||
ListUrl = waybackUrl.Substring(0, indexOfUrlModification) + urlModification +
|
||||
waybackUrl.Substring(indexOfUrlModification);
|
||||
}
|
||||
|
||||
private void UpdateTimestamp(Closest closest) =>
|
||||
SnapEntity.WaybackTimestamp =
|
||||
DateTimeOffset.ParseExact(closest.Timestamp, "yyyyMMddHHmmss", null).UtcDateTime;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue