mirror of
https://github.com/lampame/lampac-ukraine.git
synced 2026-04-16 09:22:21 +00:00
feat(mikai,uaflix): implement voice-specific season filtering and redirect handling
Add support for restricting season lists by specific voice selection, implement proper redirect handling when selected season is unavailable for chosen voice, and add season set validation to ensure consistent navigation between voices with different season availability
This commit is contained in:
parent
6ebd793e90
commit
f2b70fa95e
@ -57,11 +57,14 @@ namespace Mikai.Controllers
|
||||
|
||||
if (isSerial)
|
||||
{
|
||||
var seasonNumbers = voices.Values
|
||||
.SelectMany(v => v.Seasons.Keys)
|
||||
.Distinct()
|
||||
.OrderBy(n => n)
|
||||
.ToList();
|
||||
bool restrictByVoice = !string.IsNullOrEmpty(t) && voices.TryGetValue(t, out var voiceForSeasons);
|
||||
var seasonNumbers = restrictByVoice
|
||||
? GetSeasonSet(voiceForSeasons).OrderBy(n => n).ToList()
|
||||
: voices.Values
|
||||
.SelectMany(v => GetSeasonSet(v))
|
||||
.Distinct()
|
||||
.OrderBy(n => n)
|
||||
.ToList();
|
||||
|
||||
if (seasonNumbers.Count == 0)
|
||||
return OnError("mikai", _proxyManager);
|
||||
@ -72,6 +75,8 @@ namespace Mikai.Controllers
|
||||
foreach (var seasonNumber in seasonNumbers)
|
||||
{
|
||||
string link = $"{host}/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={seasonNumber}";
|
||||
if (restrictByVoice)
|
||||
link += $"&t={HttpUtility.UrlEncode(t)}";
|
||||
seasonTpl.Append($"{seasonNumber}", link, seasonNumber.ToString());
|
||||
}
|
||||
|
||||
@ -89,16 +94,29 @@ namespace Mikai.Controllers
|
||||
|
||||
if (string.IsNullOrEmpty(t))
|
||||
t = voicesForSeason[0].Key;
|
||||
else if (!voices.ContainsKey(t))
|
||||
t = voicesForSeason[0].Key;
|
||||
|
||||
var voiceTpl = new VoiceTpl();
|
||||
var selectedVoiceInfo = voices[t];
|
||||
var selectedSeasonSet = GetSeasonSet(selectedVoiceInfo);
|
||||
foreach (var voice in voicesForSeason)
|
||||
{
|
||||
string voiceLink = $"{host}/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={s}&t={HttpUtility.UrlEncode(voice.Key)}";
|
||||
var targetSeasonSet = GetSeasonSet(voice.Value);
|
||||
bool sameSeasonSet = targetSeasonSet.SetEquals(selectedSeasonSet);
|
||||
string voiceLink = $"{host}/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1";
|
||||
if (sameSeasonSet)
|
||||
voiceLink += $"&s={s}&t={HttpUtility.UrlEncode(voice.Key)}";
|
||||
else
|
||||
voiceLink += $"&s=-1&t={HttpUtility.UrlEncode(voice.Key)}";
|
||||
voiceTpl.Append(voice.Key, voice.Key == t, voiceLink);
|
||||
}
|
||||
|
||||
if (!voices.ContainsKey(t) || !voices[t].Seasons.ContainsKey(s))
|
||||
return OnError("mikai", _proxyManager);
|
||||
{
|
||||
string redirectUrl = $"{host}/mikai?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s=-1&t={HttpUtility.UrlEncode(t)}";
|
||||
return Redirect(redirectUrl);
|
||||
}
|
||||
|
||||
var episodeTpl = new EpisodeTpl();
|
||||
foreach (var ep in voices[t].Seasons[s].OrderBy(e => e.Number))
|
||||
@ -367,6 +385,17 @@ namespace Mikai.Controllers
|
||||
streamLink.Contains("moonanime.art", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static HashSet<int> GetSeasonSet(MikaiVoiceInfo voice)
|
||||
{
|
||||
if (voice?.Seasons == null || voice.Seasons.Count == 0)
|
||||
return new HashSet<int>();
|
||||
|
||||
return voice.Seasons
|
||||
.Where(kv => kv.Value != null && kv.Value.Any(ep => !string.IsNullOrEmpty(ep.Url)))
|
||||
.Select(kv => kv.Key)
|
||||
.ToHashSet();
|
||||
}
|
||||
|
||||
private static string StripLampacArgs(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Mikai
|
||||
{
|
||||
public class ModInit
|
||||
{
|
||||
public static double Version => 3.3;
|
||||
public static double Version => 3.4;
|
||||
|
||||
public static OnlinesSettings Mikai;
|
||||
public static bool ApnHostProvided;
|
||||
|
||||
@ -167,11 +167,21 @@ namespace Uaflix.Controllers
|
||||
// s == -1: Вибір сезону
|
||||
if (s == -1)
|
||||
{
|
||||
var allSeasons = structure.Voices
|
||||
.SelectMany(v => v.Value.Seasons.Keys)
|
||||
.Distinct()
|
||||
.OrderBy(sn => sn)
|
||||
.ToList();
|
||||
List<int> allSeasons;
|
||||
bool restrictByVoice = !string.IsNullOrEmpty(t) && structure.Voices.TryGetValue(t, out var tVoice) && IsAshdiVoice(tVoice);
|
||||
if (restrictByVoice)
|
||||
{
|
||||
allSeasons = GetSeasonSet(tVoice).OrderBy(sn => sn).ToList();
|
||||
OnLog($"Ashdi voice selected (t='{t}'), seasons count={allSeasons.Count}");
|
||||
}
|
||||
else
|
||||
{
|
||||
allSeasons = structure.Voices
|
||||
.SelectMany(v => GetSeasonSet(v.Value))
|
||||
.Distinct()
|
||||
.OrderBy(sn => sn)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
OnLog($"Found {allSeasons.Count} seasons in structure: {string.Join(", ", allSeasons)}");
|
||||
|
||||
@ -205,6 +215,8 @@ namespace Uaflix.Controllers
|
||||
foreach (var season in seasonsWithValidEpisodes)
|
||||
{
|
||||
string link = $"{host}/uaflix?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={season}&href={HttpUtility.UrlEncode(filmUrl)}";
|
||||
if (restrictByVoice)
|
||||
link += $"&t={HttpUtility.UrlEncode(t)}";
|
||||
season_tpl.Append($"{season}", link, season.ToString());
|
||||
OnLog($"Added season {season} to template");
|
||||
}
|
||||
@ -239,12 +251,31 @@ namespace Uaflix.Controllers
|
||||
t = voicesForSeason[0].DisplayName;
|
||||
OnLog($"Auto-selected first voice: {t}");
|
||||
}
|
||||
|
||||
else if (!structure.Voices.ContainsKey(t))
|
||||
{
|
||||
t = voicesForSeason[0].DisplayName;
|
||||
OnLog($"Voice '{t}' not found, fallback to first voice: {t}");
|
||||
}
|
||||
|
||||
// Створюємо VoiceTpl з усіма озвучками
|
||||
var voice_tpl = new VoiceTpl();
|
||||
var selectedVoiceInfo = structure.Voices[t];
|
||||
var selectedSeasonSet = GetSeasonSet(selectedVoiceInfo);
|
||||
bool selectedIsAshdi = IsAshdiVoice(selectedVoiceInfo);
|
||||
|
||||
foreach (var voice in voicesForSeason)
|
||||
{
|
||||
string voiceLink = $"{host}/uaflix?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s={s}&t={HttpUtility.UrlEncode(voice.DisplayName)}&href={HttpUtility.UrlEncode(filmUrl)}";
|
||||
bool targetIsAshdi = IsAshdiVoice(voice.Info);
|
||||
var targetSeasonSet = GetSeasonSet(voice.Info);
|
||||
bool sameSeasonSet = targetSeasonSet.SetEquals(selectedSeasonSet);
|
||||
bool needSeasonReset = (selectedIsAshdi || targetIsAshdi) && !sameSeasonSet;
|
||||
|
||||
string voiceLink = $"{host}/uaflix?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&href={HttpUtility.UrlEncode(filmUrl)}";
|
||||
if (needSeasonReset)
|
||||
voiceLink += $"&s=-1&t={HttpUtility.UrlEncode(voice.DisplayName)}";
|
||||
else
|
||||
voiceLink += $"&s={s}&t={HttpUtility.UrlEncode(voice.DisplayName)}";
|
||||
|
||||
bool isActive = voice.DisplayName == t;
|
||||
voice_tpl.Append(voice.DisplayName, isActive, voiceLink);
|
||||
}
|
||||
@ -261,6 +292,13 @@ namespace Uaflix.Controllers
|
||||
if (!structure.Voices[t].Seasons.ContainsKey(s))
|
||||
{
|
||||
OnLog($"Season {s} not found for voice '{t}'");
|
||||
if (IsAshdiVoice(structure.Voices[t]))
|
||||
{
|
||||
string redirectUrl = $"{host}/uaflix?imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&serial=1&s=-1&t={HttpUtility.UrlEncode(t)}&href={HttpUtility.UrlEncode(filmUrl)}";
|
||||
OnLog($"Ashdi voice missing season, redirect to season selector: {redirectUrl}");
|
||||
return Redirect(redirectUrl);
|
||||
}
|
||||
|
||||
OnLog("=== RETURN: season not found for voice OnError ===");
|
||||
return OnError("uaflix", proxyManager);
|
||||
}
|
||||
@ -369,5 +407,24 @@ namespace Uaflix.Controllers
|
||||
cleaned = cleaned.Replace("?&", "?").Replace("&&", "&").TrimEnd('?', '&');
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
private static bool IsAshdiVoice(VoiceInfo voice)
|
||||
{
|
||||
if (voice == null || string.IsNullOrEmpty(voice.PlayerType))
|
||||
return false;
|
||||
|
||||
return voice.PlayerType == "ashdi-serial" || voice.PlayerType == "ashdi-vod";
|
||||
}
|
||||
|
||||
private static HashSet<int> GetSeasonSet(VoiceInfo voice)
|
||||
{
|
||||
if (voice?.Seasons == null || voice.Seasons.Count == 0)
|
||||
return new HashSet<int>();
|
||||
|
||||
return voice.Seasons
|
||||
.Where(kv => kv.Value != null && kv.Value.Any(ep => !string.IsNullOrEmpty(ep.File)))
|
||||
.Select(kv => kv.Key)
|
||||
.ToHashSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ namespace Uaflix
|
||||
{
|
||||
public class ModInit
|
||||
{
|
||||
public static double Version => 3.3;
|
||||
public static double Version => 3.4;
|
||||
|
||||
public static OnlinesSettings UaFlix;
|
||||
public static bool ApnHostProvided;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user