402 lines
15 KiB
C#
402 lines
15 KiB
C#
using System.Globalization;
|
|
using YamlDotNet.Serialization;
|
|
|
|
namespace Catalog
|
|
{
|
|
public class ModInit
|
|
{
|
|
public static void loaded()
|
|
{
|
|
}
|
|
|
|
#region goInit
|
|
public static CatalogSettings goInit(string site)
|
|
{
|
|
if (string.IsNullOrEmpty(site))
|
|
return null;
|
|
|
|
site = site.ToLowerAndTrim();
|
|
site = Regex.Replace(site, "[^a-z0-9\\-]", "", RegexOptions.IgnoreCase);
|
|
|
|
var hybridCache = IHybridCache.Get(null);
|
|
|
|
string memKey = $"catalog:goInit:{site}";
|
|
if (!hybridCache.TryGetValue(memKey, out CatalogSettings init))
|
|
{
|
|
// Если файл не найден по имени, пробуем найти по displayname в *.yaml
|
|
if (!File.Exists($"catalog/sites/{site}.yaml"))
|
|
{
|
|
string found = FindSiteByDisplayName(site);
|
|
if (string.IsNullOrEmpty(found))
|
|
return null;
|
|
|
|
site = found;
|
|
}
|
|
|
|
var deserializer = new DeserializerBuilder().Build();
|
|
|
|
// Чтение основного YAML-файла
|
|
string yaml = File.ReadAllText($"catalog/sites/{site}.yaml");
|
|
var target = deserializer.Deserialize<Dictionary<object, object>>(yaml);
|
|
|
|
foreach (string y in new string[] { "_", site })
|
|
{
|
|
if (File.Exists($"catalog/override/{y}.yaml"))
|
|
{
|
|
// Чтение пользовательского YAML-файла
|
|
string myYaml = File.ReadAllText($"catalog/override/{y}.yaml");
|
|
var mySource = deserializer.Deserialize<Dictionary<object, object>>(myYaml);
|
|
|
|
// Объединение словарей
|
|
foreach (var property in mySource)
|
|
{
|
|
if (!target.ContainsKey(property.Key))
|
|
{
|
|
target[property.Key] = property.Value;
|
|
continue;
|
|
}
|
|
|
|
if (property.Value is IDictionary<object, object> sourceDict &&
|
|
target[property.Key] is IDictionary<object, object> targetDict)
|
|
{
|
|
// Рекурсивное объединение вложенных словарей
|
|
foreach (var item in sourceDict)
|
|
targetDict[item.Key] = item.Value;
|
|
}
|
|
else
|
|
{
|
|
target[property.Key] = property.Value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Преобразование словаря в объект CatalogSettings
|
|
var serializer = new SerializerBuilder().Build();
|
|
|
|
var yamlResult = serializer.Serialize(target);
|
|
init = deserializer.Deserialize<CatalogSettings>(yamlResult);
|
|
|
|
if (string.IsNullOrEmpty(init.plugin))
|
|
init.plugin = init.displayname;
|
|
|
|
if (!init.debug || !AppInit.conf.multiaccess)
|
|
hybridCache.Set(memKey, init, DateTime.Now.AddMinutes(1), inmemory: true);
|
|
}
|
|
|
|
return init;
|
|
}
|
|
#endregion
|
|
|
|
#region FindSiteByDisplayName
|
|
static string FindSiteByDisplayName(string site)
|
|
{
|
|
var deserializer = new DeserializerBuilder().Build();
|
|
|
|
foreach (var folder in new[] { "catalog/sites", "catalog/override" })
|
|
{
|
|
if (!Directory.Exists(folder))
|
|
continue;
|
|
|
|
foreach (var file in Directory.EnumerateFiles(folder, "*.yaml"))
|
|
{
|
|
try
|
|
{
|
|
var yaml = File.ReadAllText(file);
|
|
var dict = deserializer.Deserialize<Dictionary<object, object>>(yaml);
|
|
if (dict != null && dict.TryGetValue("displayname", out var dnObj) && dnObj != null)
|
|
{
|
|
var dn = dnObj.ToString().ToLowerAndTrim();
|
|
if (dn == site)
|
|
return Path.GetFileNameWithoutExtension(file);
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
#endregion
|
|
|
|
#region IsRhubFallback
|
|
public static bool IsRhubFallback(BaseSettings init)
|
|
{
|
|
if (init.rhub && init.rhub_fallback)
|
|
{
|
|
init.rhub = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region nodeValue - HtmlNode
|
|
public static object nodeValue(HtmlNode node, SingleNodeSettings nd, string host)
|
|
{
|
|
string value = null;
|
|
|
|
if (nd != null)
|
|
{
|
|
if (string.IsNullOrEmpty(nd.node) && (!string.IsNullOrEmpty(nd.attribute) || nd.attributes != null))
|
|
{
|
|
if (nd.attributes != null)
|
|
{
|
|
foreach (var attr in nd.attributes)
|
|
{
|
|
var attrValue = node.GetAttributeValue(attr, null);
|
|
if (!string.IsNullOrEmpty(attrValue))
|
|
{
|
|
value = attrValue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ("innerhtml".Equals(nd.attribute, StringComparison.OrdinalIgnoreCase))
|
|
value = node.InnerHtml;
|
|
else if ("outerhtml".Equals(nd.attribute, StringComparison.OrdinalIgnoreCase))
|
|
value = node.OuterHtml;
|
|
else
|
|
value = node.GetAttributeValue(nd.attribute, null);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var inNode = node.SelectSingleNode(nd.node);
|
|
if (inNode != null)
|
|
{
|
|
if (nd.attributes != null)
|
|
{
|
|
foreach (var attr in nd.attributes)
|
|
{
|
|
var attrValue = inNode.GetAttributeValue(attr, null);
|
|
if (!string.IsNullOrEmpty(attrValue))
|
|
{
|
|
value = attrValue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!string.IsNullOrEmpty(nd.attribute))
|
|
{
|
|
if ("innerhtml".Equals(nd.attribute, StringComparison.OrdinalIgnoreCase))
|
|
value = inNode.InnerHtml;
|
|
else if ("outerhtml".Equals(nd.attribute, StringComparison.OrdinalIgnoreCase))
|
|
value = inNode.OuterHtml;
|
|
else
|
|
value = inNode.GetAttributeValue(nd.attribute, null)?.Trim();
|
|
}
|
|
else
|
|
{
|
|
value = inNode.InnerText?.Trim();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(value))
|
|
return null;
|
|
|
|
if (nd.format != null)
|
|
{
|
|
var options = ScriptOptions.Default
|
|
.AddReferences(CSharpEval.ReferenceFromFile("Shared.dll"))
|
|
.AddImports("Shared")
|
|
.AddImports("Shared.Engine")
|
|
.AddImports("Shared.Models")
|
|
.AddReferences(CSharpEval.ReferenceFromFile("Newtonsoft.Json.dll"))
|
|
.AddImports("Newtonsoft.Json")
|
|
.AddImports("Newtonsoft.Json.Linq");
|
|
|
|
return CSharpEval.Execute<object>(nd.format, new CatalogNodeValue(value, host), options);
|
|
}
|
|
|
|
return value?.Trim();
|
|
}
|
|
#endregion
|
|
|
|
#region nodeValue - JToken
|
|
public static object nodeValue(JToken node, SingleNodeSettings nd, string host)
|
|
{
|
|
if (node == null || nd == null)
|
|
return null;
|
|
|
|
var current = node is JProperty property ? property.Value : node;
|
|
|
|
JToken valueToken = null;
|
|
|
|
if (!string.IsNullOrEmpty(nd.node))
|
|
{
|
|
current = current.SelectToken(nd.node);
|
|
if (current == null)
|
|
return null;
|
|
}
|
|
|
|
if (nd.attributes != null)
|
|
{
|
|
foreach (var attr in nd.attributes)
|
|
{
|
|
valueToken = current[attr];
|
|
if (valueToken != null)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valueToken == null && !string.IsNullOrEmpty(nd.attribute))
|
|
valueToken = current[nd.attribute];
|
|
|
|
if (valueToken == null)
|
|
return null;
|
|
|
|
string value = valueToken switch
|
|
{
|
|
JValue jValue => jValue.Value?.ToString(),
|
|
JProperty jProp => jProp.Value?.ToString(),
|
|
_ => valueToken.ToString(Formatting.None)
|
|
};
|
|
|
|
if (string.IsNullOrEmpty(value))
|
|
return null;
|
|
|
|
if (nd.format != null)
|
|
{
|
|
var options = ScriptOptions.Default
|
|
.AddReferences(CSharpEval.ReferenceFromFile("Shared.dll"))
|
|
.AddImports("Shared")
|
|
.AddImports("Shared.Engine")
|
|
.AddImports("Shared.Models")
|
|
.AddReferences(CSharpEval.ReferenceFromFile("Newtonsoft.Json.dll"))
|
|
.AddImports("Newtonsoft.Json")
|
|
.AddImports("Newtonsoft.Json.Linq");
|
|
|
|
return CSharpEval.Execute<object>(nd.format, new CatalogNodeValue(value, host), options);
|
|
}
|
|
|
|
if (valueToken is JValue)
|
|
return value?.Trim();
|
|
|
|
return valueToken;
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region setArgsValue
|
|
public static void setArgsValue(SingleNodeSettings arg, object val, JObject jo)
|
|
{
|
|
if (val != null)
|
|
{
|
|
if (arg.name_arg is "kp_rating" or "imdb_rating")
|
|
{
|
|
string rating = val?.ToString()?.Trim();
|
|
if (!string.IsNullOrEmpty(rating) && rating != "0" && rating != "0.0" && double.TryParse(rating, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
|
|
{
|
|
rating = rating.Length > 3 ? rating.Substring(0, 3) : rating;
|
|
if (rating.Length == 1)
|
|
rating = $"{rating}.0";
|
|
|
|
jo[arg.name_arg] = JToken.FromObject(rating.Replace(",", "."));
|
|
}
|
|
}
|
|
else if (arg.name_arg is "vote_average")
|
|
{
|
|
string value = val?.ToString()?.Trim();
|
|
if (!string.IsNullOrEmpty(value) && double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out double _v) && _v > 0)
|
|
jo[arg.name_arg] = JToken.FromObject(_v);
|
|
}
|
|
else if (arg.name_arg is "runtime" or "PG")
|
|
{
|
|
string value = val?.ToString()?.Trim();
|
|
if (!string.IsNullOrEmpty(value) && long.TryParse(value, out long _v) && _v > 0)
|
|
jo[arg.name_arg] = JToken.FromObject(_v);
|
|
}
|
|
else if (arg.name_arg is "genres" or "created_by" or "production_countries" or "production_companies" or "networks" or "spoken_languages")
|
|
{
|
|
if (val is string)
|
|
{
|
|
string arrayStr = val?.ToString();
|
|
var array = new JArray();
|
|
|
|
if (!string.IsNullOrEmpty(arrayStr))
|
|
{
|
|
foreach (string str in arrayStr.Split(","))
|
|
{
|
|
if (string.IsNullOrWhiteSpace(str))
|
|
continue;
|
|
|
|
array.Add(new JObject() { ["name"] = clearText(str) });
|
|
}
|
|
|
|
jo[arg.name_arg] = array;
|
|
}
|
|
}
|
|
else if (IsStringList(val as JToken))
|
|
{
|
|
var array = new JArray();
|
|
foreach (var item in (JArray)val)
|
|
array.Add(new JObject() { ["name"] = clearText(item.ToString()) });
|
|
|
|
jo[arg.name_arg] = array;
|
|
}
|
|
else if (val is JToken token && token.Type == JTokenType.Array)
|
|
{
|
|
jo[arg.name_arg] = token;
|
|
}
|
|
}
|
|
else if (val is string && (arg.name_arg is "origin_country" or "languages"))
|
|
{
|
|
string arrayStr = val?.ToString();
|
|
var array = new JArray();
|
|
|
|
if (!string.IsNullOrEmpty(arrayStr))
|
|
{
|
|
foreach (string str in arrayStr.Split(","))
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(str))
|
|
array.Add(str.Trim());
|
|
}
|
|
|
|
if (array.Count > 0)
|
|
jo[arg.name_arg] = array;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
jo[arg.name_arg] = JToken.FromObject(val);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region IsStringList
|
|
static bool IsStringList(JToken token)
|
|
{
|
|
if (token?.Type != JTokenType.Array)
|
|
return false;
|
|
|
|
var array = token as JArray;
|
|
return array?.All(item => item.Type == JTokenType.String) == true;
|
|
}
|
|
#endregion
|
|
|
|
#region clearText
|
|
public static string clearText(string text)
|
|
{
|
|
if (string.IsNullOrEmpty(text))
|
|
return text;
|
|
|
|
text = text.Replace(" ", "");
|
|
text = Regex.Replace(text, "<[^>]+>", "");
|
|
text = HttpUtility.HtmlDecode(text);
|
|
return text.Trim();
|
|
}
|
|
#endregion
|
|
}
|
|
}
|