mirror of
https://github.com/lampame/lampac-ukraine.git
synced 2026-04-16 17:32:20 +00:00
Adds a comprehensive host blocking system that prevents requests to specific disallowed hosts across all online streaming services. The implementation includes: - New `NotAllowedHosts` HashSet containing base64-encoded blocked hostnames - `IsNotAllowedHost()` method to validate URLs before making HTTP requests - Integration in all service classes (Anihub, AnimeON, Bamboo, CikavaIdeya, StarLight, UAKino, UaTUT, Uaflix, Unimay) - Checks applied to search, content fetching, and streaming URL resolution - Consistent implementation pattern across both Invoke and Controller classes This security enhancement prevents connections to potentially malicious or unauthorized streaming hosts while maintaining existing functionality for allowed sources.
288 lines
12 KiB
C#
288 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using System.Web;
|
|
using Shared;
|
|
using Shared.Engine;
|
|
using Shared.Models;
|
|
using Shared.Models.Online.Settings;
|
|
using StarLight.Models;
|
|
|
|
namespace StarLight
|
|
{
|
|
public class StarLightInvoke
|
|
{
|
|
private const string PlayerApi = "https://vcms-api2.starlight.digital/player-api";
|
|
private const string PlayerReferer = "https://teleportal.ua/";
|
|
private const string Language = "ua";
|
|
private static readonly HashSet<string> NotAllowedHosts =
|
|
new HashSet<string>(
|
|
new[]
|
|
{
|
|
"c3ZpdGFubW92aWU=",
|
|
"cG9ydGFsLXR2"
|
|
"bGFtcGEuc3RyZWFt"
|
|
}
|
|
.Select(base64 => Encoding.UTF8.GetString(Convert.FromBase64String(base64))),
|
|
StringComparer.OrdinalIgnoreCase
|
|
);
|
|
private readonly OnlinesSettings _init;
|
|
private readonly HybridCache _hybridCache;
|
|
private readonly Action<string> _onLog;
|
|
private readonly ProxyManager _proxyManager;
|
|
|
|
public StarLightInvoke(OnlinesSettings init, HybridCache hybridCache, Action<string> onLog, ProxyManager proxyManager)
|
|
{
|
|
_init = init;
|
|
_hybridCache = hybridCache;
|
|
_onLog = onLog;
|
|
_proxyManager = proxyManager;
|
|
}
|
|
|
|
public async Task<List<SearchResult>> Search(string title, string original_title)
|
|
{
|
|
string query = !string.IsNullOrEmpty(title) ? title : original_title;
|
|
if (string.IsNullOrEmpty(query))
|
|
return null;
|
|
|
|
string memKey = $"StarLight:search:{query}";
|
|
if (_hybridCache.TryGetValue(memKey, out List<SearchResult> cached))
|
|
return cached;
|
|
|
|
string url = $"{_init.host}/{Language}/live-search?q={HttpUtility.UrlEncode(query)}";
|
|
if (IsNotAllowedHost(url))
|
|
return null;
|
|
|
|
var headers = new List<HeadersModel>()
|
|
{
|
|
new HeadersModel("User-Agent", "Mozilla/5.0"),
|
|
new HeadersModel("Referer", _init.host)
|
|
};
|
|
|
|
try
|
|
{
|
|
_onLog?.Invoke($"StarLight search: {url}");
|
|
string payload = await Http.Get(url, headers: headers, proxy: _proxyManager.Get());
|
|
if (string.IsNullOrEmpty(payload))
|
|
return null;
|
|
|
|
var results = new List<SearchResult>();
|
|
using var document = JsonDocument.Parse(payload);
|
|
if (document.RootElement.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var item in document.RootElement.EnumerateArray())
|
|
{
|
|
string typeSlug = item.TryGetProperty("typeSlug", out var typeProp) ? typeProp.GetString() : null;
|
|
string channelSlug = item.TryGetProperty("channelSlug", out var channelProp) ? channelProp.GetString() : null;
|
|
string projectSlug = item.TryGetProperty("projectSlug", out var projectProp) ? projectProp.GetString() : null;
|
|
if (string.IsNullOrEmpty(typeSlug) || string.IsNullOrEmpty(channelSlug) || string.IsNullOrEmpty(projectSlug))
|
|
continue;
|
|
|
|
string href = $"{_init.host}/{Language}/{typeSlug}/{channelSlug}/{projectSlug}";
|
|
results.Add(new SearchResult
|
|
{
|
|
Title = item.TryGetProperty("title", out var titleProp) ? titleProp.GetString() : null,
|
|
Type = typeSlug,
|
|
Href = href,
|
|
Channel = channelSlug,
|
|
Project = projectSlug
|
|
});
|
|
}
|
|
}
|
|
|
|
if (results.Count > 0)
|
|
_hybridCache.Set(memKey, results, cacheTime(15, init: _init));
|
|
|
|
return results;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_onLog?.Invoke($"StarLight search error: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public async Task<ProjectInfo> GetProject(string href)
|
|
{
|
|
if (string.IsNullOrEmpty(href))
|
|
return null;
|
|
|
|
string memKey = $"StarLight:project:{href}";
|
|
if (_hybridCache.TryGetValue(memKey, out ProjectInfo cached))
|
|
return cached;
|
|
|
|
var headers = new List<HeadersModel>()
|
|
{
|
|
new HeadersModel("User-Agent", "Mozilla/5.0"),
|
|
new HeadersModel("Referer", _init.host)
|
|
};
|
|
|
|
try
|
|
{
|
|
if (IsNotAllowedHost(href))
|
|
return null;
|
|
|
|
_onLog?.Invoke($"StarLight project: {href}");
|
|
string payload = await Http.Get(href, headers: headers, proxy: _proxyManager.Get());
|
|
if (string.IsNullOrEmpty(payload))
|
|
return null;
|
|
|
|
using var document = JsonDocument.Parse(payload);
|
|
var root = document.RootElement;
|
|
|
|
var project = new ProjectInfo
|
|
{
|
|
Title = root.TryGetProperty("title", out var titleProp) ? titleProp.GetString() : null,
|
|
Description = root.TryGetProperty("description", out var descProp) ? descProp.GetString() : null,
|
|
Poster = NormalizeImage(root.TryGetProperty("image", out var imageProp) ? imageProp.GetString() : null),
|
|
Hash = root.TryGetProperty("hash", out var hashProp) ? hashProp.GetString() : null,
|
|
Type = root.TryGetProperty("typeSlug", out var typeProp) ? typeProp.GetString() : null,
|
|
Channel = root.TryGetProperty("channelTitle", out var channelProp) ? channelProp.GetString() : null
|
|
};
|
|
|
|
if (root.TryGetProperty("seasonsGallery", out var seasonsProp) && seasonsProp.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var season in seasonsProp.EnumerateArray())
|
|
{
|
|
string seasonTitle = season.TryGetProperty("title", out var sTitle) ? sTitle.GetString() : null;
|
|
string seasonSlug = season.TryGetProperty("seasonSlug", out var sSlug) ? sSlug.GetString() : null;
|
|
project.Seasons.Add(new SeasonInfo { Title = seasonTitle, Slug = seasonSlug });
|
|
|
|
if (season.TryGetProperty("items", out var itemsProp) && itemsProp.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var item in itemsProp.EnumerateArray())
|
|
{
|
|
project.Episodes.Add(new EpisodeInfo
|
|
{
|
|
Title = item.TryGetProperty("title", out var eTitle) ? eTitle.GetString() : null,
|
|
Hash = item.TryGetProperty("hash", out var eHash) ? eHash.GetString() : null,
|
|
VideoSlug = item.TryGetProperty("videoSlug", out var eSlug) ? eSlug.GetString() : null,
|
|
Date = item.TryGetProperty("dateOfBroadcast", out var eDate) ? eDate.GetString() : (item.TryGetProperty("timeUploadVideo", out var eDate2) ? eDate2.GetString() : null),
|
|
SeasonSlug = seasonSlug
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_hybridCache.Set(memKey, project, cacheTime(10, init: _init));
|
|
return project;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_onLog?.Invoke($"StarLight project error: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public List<EpisodeInfo> GetEpisodes(ProjectInfo project, string seasonSlug)
|
|
{
|
|
if (project == null || project.Seasons.Count == 0)
|
|
return new List<EpisodeInfo>();
|
|
|
|
if (string.IsNullOrEmpty(seasonSlug))
|
|
return project.Episodes;
|
|
|
|
return project.Episodes.Where(e => e.SeasonSlug == seasonSlug).ToList();
|
|
}
|
|
|
|
public async Task<StreamResult> ResolveStream(string hash)
|
|
{
|
|
if (string.IsNullOrEmpty(hash))
|
|
return null;
|
|
|
|
string url = $"{PlayerApi}/{hash}?referer={HttpUtility.UrlEncode(PlayerReferer)}&lang={Language}";
|
|
if (IsNotAllowedHost(url))
|
|
return null;
|
|
|
|
var headers = new List<HeadersModel>()
|
|
{
|
|
new HeadersModel("User-Agent", "Mozilla/5.0"),
|
|
new HeadersModel("Referer", PlayerReferer)
|
|
};
|
|
|
|
try
|
|
{
|
|
_onLog?.Invoke($"StarLight stream: {url}");
|
|
string payload = await Http.Get(url, headers: headers, proxy: _proxyManager.Get());
|
|
if (string.IsNullOrEmpty(payload))
|
|
return null;
|
|
|
|
using var document = JsonDocument.Parse(payload);
|
|
var root = document.RootElement;
|
|
|
|
string stream = null;
|
|
if (root.TryGetProperty("video", out var videoProp) && videoProp.ValueKind == JsonValueKind.Array)
|
|
{
|
|
var video = videoProp.EnumerateArray().FirstOrDefault();
|
|
if (video.ValueKind != JsonValueKind.Undefined)
|
|
{
|
|
if (video.TryGetProperty("mediaHlsNoAdv", out var hlsNoAdv))
|
|
stream = hlsNoAdv.GetString();
|
|
if (string.IsNullOrEmpty(stream) && video.TryGetProperty("mediaHls", out var hls))
|
|
stream = hls.GetString();
|
|
if (string.IsNullOrEmpty(stream) && video.TryGetProperty("media", out var mediaProp) && mediaProp.ValueKind == JsonValueKind.Array)
|
|
{
|
|
var media = mediaProp.EnumerateArray().FirstOrDefault();
|
|
if (media.TryGetProperty("url", out var mediaUrl))
|
|
stream = mediaUrl.GetString();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(stream))
|
|
return null;
|
|
|
|
return new StreamResult
|
|
{
|
|
Stream = stream,
|
|
Poster = root.TryGetProperty("poster", out var posterProp) ? posterProp.GetString() : null,
|
|
Name = root.TryGetProperty("name", out var nameProp) ? nameProp.GetString() : null
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_onLog?.Invoke($"StarLight stream error: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private string NormalizeImage(string path)
|
|
{
|
|
if (string.IsNullOrEmpty(path))
|
|
return string.Empty;
|
|
|
|
if (path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
|
return IsNotAllowedHost(path) ? string.Empty : path;
|
|
|
|
return IsNotAllowedHost(_init.host) ? string.Empty : $"{_init.host}{path}";
|
|
}
|
|
|
|
private static bool IsNotAllowedHost(string url)
|
|
{
|
|
if (string.IsNullOrEmpty(url))
|
|
return false;
|
|
|
|
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
|
|
return false;
|
|
|
|
return NotAllowedHosts.Contains(uri.Host);
|
|
}
|
|
|
|
public static TimeSpan cacheTime(int multiaccess, int home = 5, int mikrotik = 2, OnlinesSettings init = null, int rhub = -1)
|
|
{
|
|
if (init != null && init.rhub && rhub != -1)
|
|
return TimeSpan.FromMinutes(rhub);
|
|
|
|
int ctime = AppInit.conf.mikrotik ? mikrotik : AppInit.conf.multiaccess ? init != null && init.cache_time > 0 ? init.cache_time : multiaccess : home;
|
|
if (ctime > multiaccess)
|
|
ctime = multiaccess;
|
|
|
|
return TimeSpan.FromMinutes(ctime);
|
|
}
|
|
}
|
|
}
|