lampac-talks f843f04fd4 chore: initial commit 154.3
Signed-off-by: lampac-talks <lampac-talks@users.noreply.github.com>
2026-01-30 16:23:09 +03:00

619 lines
33 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Playwright;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Shared.Engine.RxEnumerate;
using Shared.Models.Online.Settings;
using Shared.PlaywrightCore;
namespace Online.Controllers
{
public class Mirage : BaseOnlineController<AllohaSettings>
{
public Mirage() : base(AppInit.conf.Mirage)
{
loadKitInitialization = (j, i, c) =>
{
if (j.ContainsKey("m4s"))
i.m4s = c.m4s;
return i;
};
}
[HttpGet]
[Route("lite/mirage")]
async public Task<ActionResult> Index(string orid, string imdb_id, long kinopoisk_id, string title, string original_title, int serial, string original_language, int year, int t = -1, int s = -1, bool origsource = false, bool rjson = false, bool similar = false)
{
if (similar)
return await RouteSpiderSearch(title, origsource, rjson);
if (await IsRequestBlocked(rch: false))
return badInitMsg;
var result = await search(orid, imdb_id, kinopoisk_id, title, serial, original_language, year);
if (result.category_id == 0 || result.data == null)
return OnError();
JToken data = result.data;
string tokenMovie = data["token_movie"] != null ? data.Value<string>("token_movie") : null;
var frame = await iframe(tokenMovie);
if (frame.all == null)
return OnError();
//return ContentTo(JsonConvert.SerializeObject(frame.all));
if (result.category_id is 1 or 3)
{
#region Фильм
var videos = frame.all["theatrical"].ToObject<Dictionary<string, Dictionary<string, JObject>>>();
var mtpl = new MovieTpl(title, original_title, videos.Count);
foreach (var i in videos)
{
var file = i.Value.First().Value;
string translation = file.Value<string>("translation");
string quality = file.Value<string>("quality");
long id = file.Value<long>("id");
bool uhd = init.m4s ? file.Value<bool>("uhd") : false;
string link = $"{host}/lite/mirage/video?id_file={id}&token_movie={data.Value<string>("token_movie")}";
string streamlink = accsArgs($"{link.Replace("/video", "/video.m3u8")}&play=true");
mtpl.Append(translation, link, "call", streamlink, voice_name: uhd ? "2160p" : quality, quality: uhd ? "2160p" : "");
}
return await ContentTpl(mtpl);
#endregion
}
else
{
#region Сериал
string defaultargs = $"&orid={orid}&imdb_id={imdb_id}&kinopoisk_id={kinopoisk_id}&title={HttpUtility.UrlEncode(title)}&original_title={HttpUtility.UrlEncode(original_title)}&year={year}&original_language={original_language}";
if (s == -1)
{
#region Сезоны
string q = null;
try
{
if (init.m4s)
q = frame.active.Value<bool>("uhd") == true ? "2160p" : null;
}
catch { }
Dictionary<string, JToken> seasons;
if (frame.all["seasons"] != null)
seasons = frame.all["seasons"].ToObject<Dictionary<string, JToken>>();
else
seasons = frame.all.ToObject<Dictionary<string, JToken>>();
if (seasons.First().Key.StartsWith("t"))
{
var tpl = new SeasonTpl(q);
var seasonNumbers = new HashSet<int>();
foreach (var translation in seasons)
{
var file = translation.Value["file"];
if (file == null)
continue;
foreach (var season in file.ToObject<Dictionary<string, object>>())
{
if (int.TryParse(season.Key, out int seasonNumber))
seasonNumbers.Add(seasonNumber);
}
}
if (!seasonNumbers.Any())
seasonNumbers.Add(frame.active.Value<int>("seasons"));
foreach (int i in seasonNumbers.OrderBy(i => i))
tpl.Append($"{i} сезон", $"{host}/lite/mirage?rjson={rjson}&s={i}{defaultargs}", i.ToString());
return await ContentTpl(tpl);
}
else
{
var tpl = new SeasonTpl(q, seasons.Count);
foreach (var season in seasons)
tpl.Append($"{season.Key} сезон", $"{host}/lite/mirage?rjson={rjson}&s={season.Key}{defaultargs}", season.Key);
return await ContentTpl(tpl);
}
#endregion
}
else
{
var vtpl = new VoiceTpl();
var etpl = new EpisodeTpl();
var voices = new HashSet<int>();
string sArhc = s.ToString();
if (frame.all[sArhc] is JArray)
{
#region Перевод
foreach (var episode in frame.all[sArhc])
{
foreach (var voice in episode.ToObject<Dictionary<string, JObject>>().Select(i => i.Value))
{
int id_translation = voice.Value<int>("id_translation");
if (voices.Contains(id_translation))
continue;
voices.Add(id_translation);
if (t == -1)
t = id_translation;
string link = $"{host}/lite/mirage?rjson={rjson}&s={s}&t={id_translation}{defaultargs}";
bool active = t == id_translation;
vtpl.Append(voice.Value<string>("translation"), active, link);
}
}
#endregion
foreach (var episode in frame.all[sArhc])
{
foreach (var voice in episode.ToObject<Dictionary<string, JObject>>().Select(i => i.Value))
{
if (voice.Value<int>("id_translation") != t)
continue;
string translation = voice.Value<string>("translation");
int e = voice.Value<int>("episode");
string link = $"{host}/lite/mirage/video?id_file={voice.Value<long>("id")}&token_movie={data.Value<string>("token_movie")}";
string streamlink = accsArgs($"{link.Replace("/video", "/video.m3u8")}&play=true");
if (e > 0)
etpl.Append($"{e} серия", title ?? original_title, sArhc, e.ToString(), link, "call", voice_name: translation, streamlink: streamlink);
}
}
}
else if (frame.all.ToObject<Dictionary<string, object>>().First().Key.StartsWith("t"))
{
#region Перевод
foreach (var node in frame.all)
{
if (!node.First["file"].ToObject<Dictionary<string, object>>().ContainsKey(sArhc))
continue;
var voice = node.First["file"].First.First.First.First;
int id_translation = voice.Value<int>("id_translation");
if (voices.Contains(id_translation))
continue;
voices.Add(id_translation);
if (t == -1)
t = id_translation;
string link = $"{host}/lite/mirage?rjson={rjson}&s={s}&t={id_translation}{defaultargs}";
bool active = t == id_translation;
vtpl.Append(voice.Value<string>("translation"), active, link);
}
#endregion
foreach (var node in frame.all)
{
foreach (var season in node.First["file"].ToObject<Dictionary<string, object>>())
{
if (season.Key != sArhc)
continue;
if (season.Value is JArray sjar)
{
}
else if (season.Value is JObject sjob)
{
foreach (var episode in sjob.ToObject<Dictionary<string, JObject>>())
{
if (episode.Value.Value<int>("id_translation") != t)
continue;
string translation = episode.Value.Value<string>("translation");
int e = episode.Value.Value<int>("episode");
string link = $"{host}/lite/mirage/video?id_file={episode.Value.Value<long>("id")}&token_movie={data.Value<string>("token_movie")}";
string streamlink = accsArgs($"{link.Replace("/video", "/video.m3u8")}&play=true");
if (e > 0)
etpl.Append($"{e} серия", title ?? original_title, sArhc, e.ToString(), link, "call", voice_name: translation, streamlink: streamlink);
}
}
}
}
}
else
{
#region Перевод
foreach (var episode in frame.all[sArhc].ToObject<Dictionary<string, Dictionary<string, JObject>>>())
{
foreach (var voice in episode.Value.Select(i => i.Value))
{
int id_translation = voice.Value<int>("id_translation");
if (voices.Contains(id_translation))
continue;
voices.Add(id_translation);
if (t == -1)
t = id_translation;
string link = $"{host}/lite/mirage?rjson={rjson}&s={s}&t={id_translation}{defaultargs}";
bool active = t == id_translation;
vtpl.Append(voice.Value<string>("translation"), active, link);
}
}
#endregion
foreach (var episode in frame.all[sArhc].ToObject<Dictionary<string, Dictionary<string, JObject>>>())
{
foreach (var voice in episode.Value.Select(i => i.Value))
{
string translation = voice.Value<string>("translation");
if (voice.Value<int>("id_translation") != t)
continue;
string link = $"{host}/lite/mirage/video?id_file={voice.Value<long>("id")}&token_movie={data.Value<string>("token_movie")}";
string streamlink = accsArgs($"{link.Replace("/video", "/video.m3u8")}&play=true");
etpl.Append($"{episode.Key} серия", title ?? original_title, sArhc, episode.Key, link, "call", voice_name: translation, streamlink: streamlink);
}
}
}
etpl.Append(vtpl);
return await ContentTpl(etpl);
}
#endregion
}
}
#region Video
[HttpGet]
[Route("lite/mirage/video")]
[Route("lite/mirage/video.m3u8")]
async public ValueTask<ActionResult> Video(long id_file, string token_movie, bool play)
{
if (await IsRequestBlocked(rch: false, rch_check: !play))
return badInitMsg;
string memKey = $"mirage:video:{id_file}:{init.m4s}";
if (!hybridCache.TryGetValue(memKey, out (string hls, List<HeadersModel> headers) movie))
{
movie = await goMovie($"{init.linkhost}/?token_movie={token_movie}&token={init.token}", id_file);
if (movie.hls == null)
return OnError();
hybridCache.Set(memKey, movie, cacheTime(10));
}
var streamquality = new StreamQualityTpl();
streamquality.Append(HostStreamProxy(movie.hls, headers: movie.headers), "auto");
if (play)
return Redirect(streamquality.Firts().link);
return ContentTo(VideoTpl.ToJson("play", streamquality.Firts().link, "auto",
streamquality: streamquality,
vast: init.vast,
headers: movie.headers,
hls_manifest_timeout: (int)TimeSpan.FromSeconds(20).TotalMilliseconds
));
}
#endregion
#region iframe
async ValueTask<(JToken all, JToken active)> iframe(string token_movie)
{
if (string.IsNullOrEmpty(token_movie))
return default;
string memKey = $"mirage:iframe:{token_movie}";
if (!hybridCache.TryGetValue(memKey, out (JToken all, JToken active) cache))
{
string json = null;
string uri = $"{init.linkhost}/?token_movie={token_movie}&token={init.token}";
string referer = $"https://lgfilm.fun/" + reffers[Random.Shared.Next(0, reffers.Length)];
await httpHydra.GetSpan(uri, safety: true, addheaders: HeadersModel.Init(
("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"),
("referer", referer),
("sec-fetch-dest", "iframe"),
("sec-fetch-mode", "navigate"),
("sec-fetch-site", "cross-site"),
("upgrade-insecure-requests", "1")
),
spanAction: html =>
{
json = Rx.Match(html, "fileList = JSON.parse\\('([^\n\r]+)'\\);");
});
if (string.IsNullOrEmpty(json))
return default;
try
{
var root = JsonConvert.DeserializeObject<JObject>(json);
if (root == null || !root.ContainsKey("all"))
return default;
cache = (root["all"], root["active"]);
hybridCache.Set(memKey, cache, cacheTime(40));
}
catch { return default; }
}
return cache;
}
#endregion
#region goMovie
async Task<(string hls, List<HeadersModel> headers)> goMovie(string uri, long id_file)
{
try
{
using (var browser = new PlaywrightBrowser())
{
var page = await browser.NewPageAsync(init.plugin, proxy: proxy_data).ConfigureAwait(false);
if (page == null)
return default;
await page.RouteAsync("**/*", async route =>
{
try
{
if (route.Request.Url.Contains("lgfilm.fun"))
{
await route.FulfillAsync(new RouteFulfillOptions
{
Body = PlaywrightBase.IframeHtml(uri)
});
}
else if (route.Request.Method == "POST" && route.Request.Url.Contains("/movies/"))
{
string newUrl = Regex.Replace(route.Request.Url, "/[0-9]+$", $"/{id_file}");
var fetchHeaders = route.Request.Headers;
fetchHeaders.TryAdd("accept-encoding", "gzip, deflate, br, zstd");
fetchHeaders.TryAdd("cache-control", "no-cache");
fetchHeaders.TryAdd("dnt", "1");
fetchHeaders.TryAdd("pragma", "no-cache");
fetchHeaders.TryAdd("priority", "u=1, i");
fetchHeaders.TryAdd("sec-fetch-dest", "empty");
fetchHeaders.TryAdd("sec-fetch-mode", "cors");
fetchHeaders.TryAdd("sec-fetch-site", "same-origin");
fetchHeaders.TryAdd("sec-fetch-storage-access", "active");
var fetchResponse = await route.FetchAsync(new RouteFetchOptions
{
Url = newUrl,
Method = "POST",
Headers = fetchHeaders,
PostData = route.Request.PostDataBuffer
}).ConfigureAwait(false);
string json = await fetchResponse.TextAsync().ConfigureAwait(false);
string targetStream = null;
try
{
foreach (var hlsSource in JsonConvert.DeserializeObject<JObject>(json)["hlsSource"])
{
// first or default
if (targetStream == null || hlsSource.Value<bool>("default"))
{
foreach (var q in hlsSource["quality"].ToObject<Dictionary<string, string>>())
{
if ((q.Key is "2160" or "1440") && !init.m4s)
continue;
targetStream = q.Value;
break;
}
}
}
}
catch { }
if (string.IsNullOrWhiteSpace(targetStream))
{
if (init.m4s)
targetStream = Regex.Match(json, "\"(2160|1440)\":\"([^\"]+)\"").Groups[2].Value;
if (string.IsNullOrWhiteSpace(targetStream))
targetStream = Regex.Match(json, "\"(1080|720)\":\"([^\"]+)\"").Groups[2].Value;
}
if (!string.IsNullOrWhiteSpace(targetStream))
json = Regex.Replace(json, "\"(2160|1440|1080|720|480|360)\":\"[^\"]+\"", $"\"$1\":\"{targetStream}\"");
await route.FulfillAsync(new RouteFulfillOptions
{
Status = fetchResponse.Status,
Body = json,
Headers = fetchResponse.Headers
}).ConfigureAwait(false);
}
else
{
if (await PlaywrightBase.AbortOrCache(page, route, abortMedia: true, fullCacheJS: true))
return;
await route.ContinueAsync();
}
}
catch { }
});
page.Response += Page_Response;
PlaywrightBase.GotoAsync(page, $"https://lgfilm.fun/" + reffers[Random.Shared.Next(0, reffers.Length)]);
try
{
return await tcsPageResponse.Task.WaitAsync(TimeSpan.FromSeconds(15));
}
catch { }
finally
{
page.Response -= Page_Response;
}
}
}
catch { }
return default;
}
TaskCompletionSource<(string hls, List<HeadersModel> headers)> tcsPageResponse = new TaskCompletionSource<(string hls, List<HeadersModel> headers)>();
private void Page_Response(object sender, IResponse e)
{
if (e.Request.Method == "GET" && e.Url.Contains("/master.m3u8"))
{
var headers = HeadersModel.Init(Http.defaultFullHeaders,
("sec-fetch-dest", "empty"),
("sec-fetch-mode", "cors"),
("sec-fetch-site", "cross-site")
);
foreach (var item in e.Request.Headers)
{
if (item.Key.ToLower() is "host" or "accept-encoding" or "connection" or "range")
continue;
if (!Http.defaultFullHeaders.ContainsKey(item.Key.ToLower()))
headers.Add(new HeadersModel(item.Key, item.Value.ToString()));
}
tcsPageResponse.SetResult((e.Url, headers));
}
}
#endregion
#region SpiderSearch
[HttpGet]
[Route("lite/mirage-search")]
async public Task<ActionResult> RouteSpiderSearch(string title, bool origsource = false, bool rjson = false)
{
if (string.IsNullOrWhiteSpace(title))
return OnError();
if (await IsRequestBlocked(rch: false))
return badInitMsg;
var cache = await InvokeCacheResult<JArray>($"mirage:search:{title}", 40, async e =>
{
var root = await httpHydra.Get<JObject>($"{init.apihost}/?token={init.token}&name={HttpUtility.UrlEncode(title)}&list", safety: true);
if (root == null || !root.ContainsKey("data"))
return e.Fail("data");
return e.Success(root["data"].ToObject<JArray>());
});
return await ContentTpl(cache, () =>
{
var stpl = new SimilarTpl(cache.Value.Count);
foreach (var j in cache.Value)
{
string uri = $"{host}/lite/mirage?orid={j.Value<string>("token_movie")}";
stpl.Append(j.Value<string>("name") ?? j.Value<string>("original_name"), j.Value<int>("year").ToString(), string.Empty, uri, PosterApi.Size(j.Value<string>("poster")));
}
return stpl;
});
}
#endregion
#region search
async ValueTask<(bool refresh_proxy, int category_id, JToken data)> search(string token_movie, string imdb_id, long kinopoisk_id, string title, int serial, string original_language, int year)
{
string memKey = $"mirage:view:{kinopoisk_id}:{imdb_id}";
if (0 >= kinopoisk_id && string.IsNullOrEmpty(imdb_id))
memKey = $"mirage:viewsearch:{title}:{serial}:{original_language}:{year}";
if (!string.IsNullOrEmpty(token_movie))
memKey = $"mirage:view:{token_movie}";
JObject root;
if (!hybridCache.TryGetValue(memKey, out (int category_id, JToken data) res))
{
string stitle = title.ToLowerAndTrim();
if (memKey.Contains(":viewsearch:"))
{
if (string.IsNullOrWhiteSpace(title) || year == 0)
return default;
root = await httpHydra.Get<JObject>($"{init.apihost}/?token={init.token}&name={HttpUtility.UrlEncode(title)}&list={(serial == 1 ? "serial" : "movie")}", safety: true);
if (root == null)
return (true, 0, null);
if (root.ContainsKey("data"))
{
foreach (var item in root["data"])
{
if (item.Value<string>("name")?.ToLowerAndTrim() == stitle)
{
int y = item.Value<int>("year");
if (y > 0 && (y == year || y == (year - 1) || y == (year + 1)))
{
if (original_language == "ru" && item.Value<string>("country")?.ToLowerAndTrim() != "россия")
continue;
res.data = item;
res.category_id = item.Value<int>("category_id");
break;
}
}
}
}
}
else
{
root = await httpHydra.Get<JObject>($"{init.apihost}/?token={init.token}&kp={kinopoisk_id}&imdb={imdb_id}&token_movie={token_movie}", safety: true);
if (root == null)
return (true, 0, null);
if (root.ContainsKey("data"))
{
res.data = root.GetValue("data");
res.category_id = res.data.Value<int>("category");
}
}
if (res.data != null || (root.ContainsKey("error_info") && root.Value<string>("error_info") == "not movie"))
hybridCache.Set(memKey, res, cacheTime(res.category_id is 1 or 3 ? 120 : 40));
else
hybridCache.Set(memKey, res, cacheTime(2));
}
return (false, res.category_id, res.data);
}
#endregion
static string[] reffers = new string[] { "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "1400-princessa-i-tajna-goblinov-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "408-legenda-o-chernom-dereve-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1221-magazin-svetilnikov-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1112-vspylchivyj-svjaschennik-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1239-forsazh-polnyj-vpered-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1230-chelovek-vnutri-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1214-moj-marchello-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1200-reinkarnacija-vozvraschenie-vedmy-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1185-ne-hochu-nichego-terjat-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1168-astral-koshmar-v-spring-garden-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1179-komandante-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1157-bolshoe-prikljuchenie-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "1143-kak-stat-korolem-2024.html", "944-pingvin-2024.html", "944-pingвин-2024.html" };
}
}