lampac/Shared/Engine/SISI/SpankbangTo.cs
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

181 lines
6.1 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 Shared.Engine.RxEnumerate;
using Shared.Models.SISI.Base;
using Shared.Models.SISI.OnResult;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
namespace Shared.Engine.SISI
{
public static class SpankbangTo
{
static readonly ThreadLocal<StringBuilder> sbUri = new(() => new StringBuilder(PoolInvk.rentChunk));
#region Uri
public static string Uri(string host, string search, string sort, int pg)
{
var url = sbUri.Value;
url.Clear();
url.Append(host);
url.Append("/");
if (!string.IsNullOrWhiteSpace(search))
{
url.Append($"s/{HttpUtility.UrlEncode(search)}/{pg}/");
}
else
{
url.Append($"{sort ?? "new_videos"}/{pg}/");
if (sort == "most_popular")
url.Append("?p=m");
}
return url.ToString();
}
#endregion
#region Playlist
public static List<PlaylistItem> Playlist(string route, ReadOnlySpan<char> html, Func<PlaylistItem, PlaylistItem> onplaylist = null)
{
if (html.IsEmpty)
return null;
ReadOnlySpan<char> container = html.Contains("class=\"main-container\"", StringComparison.Ordinal)
? Rx.Split("class=\"main-container\"", html)[1].Span
: html;
var playlists = new List<PlaylistItem>(80);
foreach (ReadOnlySpan<char> row in HtmlSpan.Nodes(container, "div", "data-testid", "video-item", HtmlSpanTargetType.Exact))
{
var g = Rx.Groups(row, "<a href=\"/(?<link>[^\"]+)\" title=\"(?<title>[^\"]+)\"");
if (!string.IsNullOrWhiteSpace(g["link"].Value) && !string.IsNullOrWhiteSpace(g["title"].Value))
{
string img = Rx.Match(row, "([\n\r\t ]+)src=\"([^\"]+)\"", 2) ?? string.Empty;
if (!img.Contains("/w:"))
img = Rx.Match(row, "data-src=\"([^\"]+)\"");
if (img == null)
continue;
img = Regex.Replace(img, "/w:[0-9]00/", "/w:300/").Replace("http://", "https://");
string preview = Rx.Match(row, "data-preview=\"([^\"]+)\"");
if (preview == null)
preview = Rx.Match(row, "<source data-src=\"([^\"]+)\"");
var pl = new PlaylistItem()
{
name = g["title"].Value,
video = $"{route}?uri={g["link"].Value}",
quality = Rx.Match(row, "\"video-item-resolution\">([^<]+)</span>"),
picture = img,
preview = preview,
time = Rx.Match(row, "\"video-item-length\">([^<]+)</span>"),
json = true,
related = true,
bookmark = new Bookmark()
{
site = "sbg",
href = g["link"].Value,
image = img
}
};
if (onplaylist != null)
pl = onplaylist.Invoke(pl);
playlists.Add(pl);
}
}
return playlists;
}
#endregion
#region Menu
public static List<MenuItem> Menu(string host, string sort)
{
host = string.IsNullOrWhiteSpace(host) ? string.Empty : $"{host}/";
return new List<MenuItem>()
{
new MenuItem()
{
title = "Поиск",
search_on = "search_on",
playlist_url = host + "sbg",
},
new MenuItem()
{
title = $"Сортировка: {(string.IsNullOrWhiteSpace(sort) ? "новое" : sort)}",
playlist_url = "submenu",
submenu = new List<MenuItem>()
{
new MenuItem()
{
title = "Новое",
playlist_url = host + "sbg"
},
new MenuItem()
{
title = "Трендовое",
playlist_url = host + "sbg?sort=trending_videos"
},
new MenuItem()
{
title = "Популярное",
playlist_url = host + "sbg?sort=most_popular"
}
}
}
};
}
#endregion
#region StreamLinks
public static string StreamLinksUri(string host, string url)
{
if (string.IsNullOrEmpty(url))
return null;
return $"{host}/{url}";
}
public static StreamItem StreamLinks(string route, ReadOnlySpan<char> html)
{
if (html.IsEmpty)
return null;
var rx = Rx.Matches("'([0-9]+)(p|k)': ?\\[\'(https?://[^']+)\'", html);
if (rx.Count == 0)
return null;
var stream_links = new Dictionary<int, string>(rx.Count);
foreach (var row in rx.Rows())
{
var g = row.Groups();
if (string.IsNullOrEmpty(g[1].Value))
continue;
int q = $"{g[1].Value}{g[2].Value}" == "4k" ? 2160 : - 1;
if (q == -1)
int.TryParse(g[1].Value, out q);
stream_links.TryAdd(q, g[3].Value);
}
return new StreamItem()
{
qualitys = stream_links.OrderByDescending(i => i.Key).ToDictionary(k => $"{k.Key}p", v => v.Value),
recomends = Playlist(route, html)
};
}
#endregion
}
}