Compare commits
8 Commits
6a518b0c9b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 8dcc153806 | |||
| 41c75ee3f2 | |||
| 5cfcecc5c3 | |||
| 6a50c94cf2 | |||
| acac2a25e8 | |||
| 47b44fb59a | |||
| 965bd58799 | |||
| 039e3189eb |
@@ -6,5 +6,6 @@ namespace AnimeAnnouncer.Cache
|
||||
public required String Title { get; set; }
|
||||
public int ShowID { get; set; }
|
||||
public DateTime? LastAirDate { get; set; }
|
||||
public int LatestEpisodeNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public class TMDBCache
|
||||
public async Task SetCacheItem(String key, TMDBCacheItem item)
|
||||
{
|
||||
var db = redis.GetDatabase();
|
||||
|
||||
String jsonItem = JsonSerializer.Serialize(item);
|
||||
await db.StringSetAsync(key, jsonItem, CacheExpiration);
|
||||
}
|
||||
@@ -28,26 +29,33 @@ public class TMDBCache
|
||||
var db = redis.GetDatabase();
|
||||
String jsonItem = await db.StringGetAsync(key);
|
||||
|
||||
if(!String.IsNullOrEmpty(jsonItem))
|
||||
if (!String.IsNullOrEmpty(jsonItem))
|
||||
return JsonSerializer.Deserialize<TMDBCacheItem>(jsonItem);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task RemoveCacheItem(String key)
|
||||
{
|
||||
var db = redis.GetDatabase();
|
||||
_ = await db.KeyDeleteAsync(key);
|
||||
}
|
||||
|
||||
public async Task SetAiringSoon(List<AiringSoonItem> list)
|
||||
{
|
||||
var db = redis.GetDatabase();
|
||||
String jsonItem = JsonSerializer.Serialize(list);
|
||||
await db.StringSetAsync("AiringSoon", jsonItem, CacheExpiration);
|
||||
await db.StringSetAsync("AiringSoon", jsonItem, TimeSpan.FromDays(60));
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<AiringSoonItem>> GetAiringList()
|
||||
{
|
||||
var db = redis.GetDatabase();
|
||||
|
||||
String jsonItem = await db.StringGetAsync("AiringSoon");
|
||||
|
||||
if(!String.IsNullOrEmpty(jsonItem))
|
||||
if (!String.IsNullOrEmpty(jsonItem))
|
||||
return JsonSerializer.Deserialize<List<AiringSoonItem>>(jsonItem);
|
||||
else
|
||||
return null;
|
||||
@@ -62,4 +70,9 @@ public class TMDBCache
|
||||
var db = redis.GetDatabase();
|
||||
await db.StringSetAsync(key, value);
|
||||
}
|
||||
public async Task<String?> GetStringValue(String key)
|
||||
{
|
||||
var db = redis.GetDatabase();
|
||||
return await db.StringGetAsync(key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using AnimeAnnouncer.Cache;
|
||||
using AnimeAnnouncer.RSS;
|
||||
using Mastonet;
|
||||
using Mastonet.Entities;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TMDbLib.Client;
|
||||
@@ -59,14 +61,32 @@ namespace AnimeAnnouncer
|
||||
if(airingSoonList == null)
|
||||
airingSoonList = new List<AiringSoonItem>();
|
||||
|
||||
if (args.Any(p => p == "--show-airing-list"))
|
||||
{
|
||||
PrintAiringList();
|
||||
return;
|
||||
}
|
||||
|
||||
nyaaIndexer.NewPost += OnNewPost;
|
||||
nyaaIndexer.RssReadFinished += OnRssReadFinished;
|
||||
nyaaIndexer.Start(true);
|
||||
nyaaIndexer.IterationSleepTime = 60;
|
||||
nyaaIndexer.Start(false);
|
||||
|
||||
Console.WriteLine("Press enter to quit...");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
private static void PrintAiringList()
|
||||
{
|
||||
var airingThisHalf = airingSoonList.Where(a => a.LastAirDate > DateTime.Now && a.LastAirDate.Value.Subtract(DateTime.Now) < TimeSpan.FromDays(180)).ToList();
|
||||
int cnt = 1;
|
||||
for(int i = 0;i < airingThisHalf.Count;i++)
|
||||
{
|
||||
var airing = airingThisHalf[i];
|
||||
Console.WriteLine($"{cnt++}. {airing.Title} on {airing.LastAirDate:MM/dd/yyyy}{Environment.NewLine}");
|
||||
}
|
||||
}
|
||||
|
||||
static async void OnNewPost(RSS.NyaaItem item)
|
||||
{
|
||||
try
|
||||
@@ -81,6 +101,14 @@ namespace AnimeAnnouncer
|
||||
|
||||
static void OnRssReadFinished()
|
||||
{
|
||||
if(DateTime.Today.Day == 1)
|
||||
{
|
||||
if(!tmdbCache.KeyExists($"UpcomingAnnounced-{DateTime.Today.Year}-{DateTime.Today.Month}").Result)
|
||||
{
|
||||
CreateAiringMonthPost().Wait();
|
||||
tmdbCache.SetPair($"UpcomingAnnounced-{DateTime.Today.Year}-{DateTime.Today.Month}", "1").Wait();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -212,6 +240,8 @@ namespace AnimeAnnouncer
|
||||
};
|
||||
_ = tmdbCache.SetCacheItem($"ShowCache-{title}", cachedShow);
|
||||
Console.WriteLine($"{title} Added to cache");
|
||||
if(latestSeason.AirDate < DateTime.Now && (latestSeason.AirDate + TimeSpan.FromDays(180)) > DateTime.Now &&
|
||||
((showResult.Status == "Ended" || showResult.NextEpisodeToAir == null ? showResult.LastAirDate : showResult.NextEpisodeToAir.AirDate) + TimeSpan.FromDays(30)) > DateTime.Now)
|
||||
UpdateAiringShowList(cachedShow);
|
||||
}
|
||||
catch(Exception ex)
|
||||
@@ -241,7 +271,7 @@ namespace AnimeAnnouncer
|
||||
{ //Episode_Type isn't making it with the current client, guess based on ordering
|
||||
var targetFinale = targetSeason.Episodes.OrderByDescending(g => g.Order).FirstOrDefault(e => e.EpisodeType.Equals("finale", StringComparison.InvariantCultureIgnoreCase));
|
||||
//Confirm it's aired within the last week
|
||||
if(targetFinale != null && targetEpisodeGroup.Groups.OrderByDescending(g => g.Order).FirstOrDefault() == targetSeason)
|
||||
if(targetFinale != null && targetEpisodeGroup.Groups.Where(g => g.Episodes.Count != 0).OrderByDescending(g => g.Order).FirstOrDefault() == targetSeason)
|
||||
{ //confirm the episode is marked as finale and that this season is the latest one in the episode group
|
||||
Console.WriteLine($"!!Choosing S{titleSeason}E{targetFinale.Order + 1} airing on {targetFinale.AirDate} for finale using episode groups");
|
||||
cachedShow.LatestSeasonNumber = latestSeasonNumber = titleSeason;
|
||||
@@ -257,6 +287,9 @@ namespace AnimeAnnouncer
|
||||
|
||||
seasonOverride = finaleConfirmed = true;
|
||||
_ = tmdbCache.SetCacheItem($"ShowCache-{title}", cachedShow);
|
||||
|
||||
if(targetSeason != null && (targetSeason.Episodes.OrderBy(e => e.Order).First().AirDate + TimeSpan.FromDays(180)) > DateTime.Now &&
|
||||
((showResult.NextEpisodeToAir ?? showResult.LastEpisodeToAir).AirDate + TimeSpan.FromDays(30)) > DateTime.Now)
|
||||
UpdateAiringShowList(cachedShow);
|
||||
}
|
||||
else
|
||||
@@ -289,7 +322,10 @@ namespace AnimeAnnouncer
|
||||
}
|
||||
|
||||
// Announce if unique
|
||||
if(await tmdbCache.KeyExists($"ShowAnnounced-{supposedShowId}"))
|
||||
var lastAnnouncedSeason = await tmdbCache.GetStringValue($"ShowAnnounced-{supposedShowId}");
|
||||
Int32 lastSeason = 0;
|
||||
if (lastAnnouncedSeason != null && Int32.TryParse(lastAnnouncedSeason, out lastSeason) &&
|
||||
latestSeasonNumber <= lastSeason)
|
||||
{
|
||||
Console.WriteLine($"{title} has been previously announced, so avoiding announcing it again.");
|
||||
return;
|
||||
@@ -297,17 +333,16 @@ namespace AnimeAnnouncer
|
||||
else if (!finaleConfirmed)
|
||||
{
|
||||
Console.WriteLine($"Would have announced finale for {title}, on S{cachedShow.LatestSeasonNumber}E{cachedShow.LastEpisodeNumber} but the finale episode type was not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = tmdbCache.SetPair($"ShowAnnounced-{supposedShowId}", "1");
|
||||
//Remove from cache so subsequent releases cause a fresh lookup
|
||||
await tmdbCache.RemoveCacheItem($"ShowCache-{title}");
|
||||
return;
|
||||
}
|
||||
if(mastodonClient != null && cachedShow != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = tmdbCache.SetPair($"ShowAnnounced-{supposedShowId}", latestSeasonNumber.ToString());
|
||||
PostStatus(cachedShow);
|
||||
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
@@ -318,6 +353,55 @@ namespace AnimeAnnouncer
|
||||
Console.WriteLine($"Choosing {title} as a finished season!");
|
||||
}
|
||||
|
||||
|
||||
private static async Task CreateAiringMonthPost()
|
||||
{
|
||||
var airingSoon = await tmdbCache.GetAiringList();
|
||||
DateTime beginningOfMonth = DateTime.Today;
|
||||
DateTime endOfMonth = DateTime.Today.AddMonths(1);
|
||||
var airingThisMonth = airingSoon.Where(p => p.LastAirDate >= beginningOfMonth && p.LastAirDate <= endOfMonth).ToList();
|
||||
String statusText = $"DUBBED airing anime ending this month (probably){Environment.NewLine + Environment.NewLine}";
|
||||
int cnt = 1;
|
||||
for(int i = 0;i < airingThisMonth.Count;i++)
|
||||
{
|
||||
var airing = airingThisMonth[i];
|
||||
if(!await tmdbCache.KeyExists($"ShowAnnounced-{airing.ShowID}"))
|
||||
{ //TODO: fix for seasons
|
||||
statusText += $"{cnt++}. {airing.Title} on {airing.LastAirDate:MM/dd/yyyy}{Environment.NewLine}";
|
||||
}
|
||||
}
|
||||
int neededPostCount = (int)Math.Ceiling((decimal)statusText.Length / 500);
|
||||
if(neededPostCount >= 2)
|
||||
{
|
||||
//statusText = statusText[..497] + "...";
|
||||
int lineBreakIdx = 500 - new string(statusText.Take(500).Reverse().ToArray()).IndexOf(Environment.NewLine);
|
||||
String postOne = statusText.Substring(0, lineBreakIdx);
|
||||
String postTwo = statusText.Substring(lineBreakIdx);
|
||||
|
||||
var statusOne = await mastodonClient.PublishStatus(postOne,
|
||||
Visibility.Public, null);
|
||||
var statusTwo = await mastodonClient.PublishStatus(postTwo, Visibility.Public, statusOne.Id);
|
||||
}else
|
||||
{
|
||||
_ = mastodonClient.PublishStatus(statusText,
|
||||
Visibility.Public, null);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
for(cnt = 1; cnt < neededPostCount; cnt++)
|
||||
{
|
||||
//go back and find a line break
|
||||
String postPart = "";
|
||||
//_ = mastodonClient.PublishStatus(${statusText},
|
||||
// Visibility.Public, null);
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private static async void PostStatus(TMDBCacheItem cachedShow)
|
||||
{
|
||||
//get poster
|
||||
@@ -346,8 +430,12 @@ namespace AnimeAnnouncer
|
||||
}
|
||||
statusText += $"..{anidbLink}";
|
||||
|
||||
_ = mastodonClient.PublishStatus(statusText,
|
||||
var status = await mastodonClient.PublishStatus(statusText,
|
||||
Visibility.Public, mediaIds: attachment != null ? new String[] { attachment.Id } : null);
|
||||
if(String.IsNullOrEmpty(status.Id))
|
||||
{
|
||||
Console.WriteLine("An error has occurred posting the status update");
|
||||
}
|
||||
|
||||
}
|
||||
private static async void UpdateAiringShowList(TMDBCacheItem cachedShow)
|
||||
@@ -356,20 +444,27 @@ namespace AnimeAnnouncer
|
||||
{
|
||||
Title = cachedShow.Title,
|
||||
ShowID = cachedShow.ShowID,
|
||||
LastAirDate = cachedShow.LastAirDate ?? DateTime.MaxValue
|
||||
LastAirDate = cachedShow.LastAirDate ?? DateTime.MaxValue,
|
||||
LatestEpisodeNumber = cachedShow.LatestEpisodeNumber ?? 0
|
||||
};
|
||||
if(!airingSoonList.Any(s => s.ShowID == cachedShow.ShowID))
|
||||
var existingAiringItem = airingSoonList.FirstOrDefault(s => s.ShowID == cachedShow.ShowID);
|
||||
if(existingAiringItem == null)
|
||||
{
|
||||
airingSoonList.Add(airingSoonItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(existingAiringItem.LatestEpisodeNumber >= cachedShow.LatestEpisodeNumber)
|
||||
{
|
||||
Console.WriteLine($"Not updating {cachedShow.Title} airdate due to episode number not incrementing");
|
||||
return;
|
||||
}
|
||||
airingSoonList.RemoveAll(s => s.ShowID == cachedShow.ShowID);
|
||||
airingSoonList.Add(airingSoonItem);
|
||||
}
|
||||
airingSoonList.Sort((showOne, showTwo) => showOne.LastAirDate.Value.CompareTo(showTwo.LastAirDate.Value));
|
||||
_ = tmdbCache.SetAiringSoon(airingSoonList);
|
||||
Console.WriteLine("Updated airing soon list");
|
||||
Console.WriteLine($"Updated airing soon list, setting {cachedShow.Title} Season {cachedShow.LatestSeasonNumber} to end on {cachedShow.LastAirDate ?? DateTime.MaxValue}");
|
||||
}
|
||||
private static bool HasAiringEndDate(int showID)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace MassTorrentAdd
|
||||
transmissionDirectoryName = System.Text.RegularExpressions.Regex.Replace(transmissionDirectoryName, @"E\d{2,3}.*?(\d{3,4}p)", " $1");
|
||||
transmissionDirectoryName = System.Text.RegularExpressions.Regex.Replace(transmissionDirectoryName, @"\s\(.*?\)$", "");
|
||||
transmissionDirectoryName = destinationFolder + (destinationFolder.EndsWith("/") ? String.Empty : "/") + transmissionDirectoryName.Replace(" ", ".");
|
||||
Console.WriteLine("to " + transmissionDirectoryName);
|
||||
Console.WriteLine($"{items.Count()} item(s) to {transmissionDirectoryName}");
|
||||
|
||||
Console.WriteLine("Continue?");
|
||||
if(Console.ReadKey().KeyChar != 'y')
|
||||
|
||||
Reference in New Issue
Block a user