using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using XiaohaiTV_Extended.Patches;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("sasnews")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4e4aedba538d8595258df797e1bf2ad0fabb56da")]
[assembly: AssemblyProduct("XiaohaiTV_Extended")]
[assembly: AssemblyTitle("XiaohaiTV_Extended")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace XiaohaiTV_Extended
{
[HarmonyPatch(typeof(PlayerController))]
internal static class ExamplePlayerControllerPatch
{
[HarmonyPrefix]
[HarmonyPatch("Start")]
private static void Start_Prefix(PlayerController __instance)
{
XiaohaiTV_Extended.Logger.LogDebug((object)$"{__instance} Start Prefix");
}
[HarmonyPostfix]
[HarmonyPatch("Start")]
private static void Start_Postfix(PlayerController __instance)
{
XiaohaiTV_Extended.Logger.LogDebug((object)$"{__instance} Start Postfix");
}
}
[BepInPlugin("sasnews.XiaohaiTV_Extended", "XiaohaiTV_Extended", "1.0")]
public class XiaohaiTV_Extended : BaseUnityPlugin
{
[CompilerGenerated]
private sealed class <WaitAndApplyPatch>d__16 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public XiaohaiTV_Extended <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WaitAndApplyPatch>d__16(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSeconds(2f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
Logger.LogInfo((object)"Attempting to apply patch to REPO_TV...");
if (<>4__this.Harmony != null)
{
TVScriptBilibiliPatch.ApplyPatch(<>4__this.Harmony);
}
else
{
Logger.LogError((object)"Harmony instance is null!");
}
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
internal static XiaohaiTV_Extended Instance { get; private set; }
internal static ManualLogSource Logger => Instance._logger;
private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;
internal Harmony? Harmony { get; set; }
private void Awake()
{
Instance = this;
((Component)this).gameObject.transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Patch();
Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
CheckYtDlpInstallation();
((MonoBehaviour)this).StartCoroutine(WaitAndApplyPatch());
}
internal void Patch()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_0026: Expected O, but got Unknown
if (Harmony == null)
{
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
Harmony val2 = val;
Harmony = val;
}
Logger.LogInfo((object)"Harmony instance created, waiting for REPO_TV to load...");
}
private void CheckYtDlpInstallation()
{
try
{
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "yt-dlp",
Arguments = "--version",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
process.Start();
process.WaitForExit(3000);
if (process.ExitCode == 0)
{
string text = process.StandardOutput.ReadToEnd().Trim();
Logger.LogInfo((object)("yt-dlp detected: v" + text));
}
else
{
LogYtDlpWarning();
}
}
catch
{
LogYtDlpWarning();
}
}
private void LogYtDlpWarning()
{
Logger.LogWarning((object)"================================================================================");
Logger.LogWarning((object)"███████████████████████████████ WARNING ███████████████████████████████");
Logger.LogWarning((object)"================================================================================");
Logger.LogWarning((object)"");
Logger.LogWarning((object)" yt-dlp is NOT installed or not found in PATH!");
Logger.LogWarning((object)"");
Logger.LogWarning((object)" This MOD requires yt-dlp to be installed.");
Logger.LogWarning((object)"");
Logger.LogWarning((object)" Installation:");
Logger.LogWarning((object)" pip install yt-dlp");
Logger.LogWarning((object)"");
Logger.LogWarning((object)" Or visit:");
Logger.LogWarning((object)" https://github.com/yt-dlp/yt-dlp#installation");
Logger.LogWarning((object)"");
Logger.LogWarning((object)"================================================================================");
}
[IteratorStateMachine(typeof(<WaitAndApplyPatch>d__16))]
private IEnumerator WaitAndApplyPatch()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WaitAndApplyPatch>d__16(0)
{
<>4__this = this
};
}
internal void Unpatch()
{
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
public static class YouTubeHelper
{
private static ManualLogSource Logger => XiaohaiTV_Extended.Logger;
public static string? ExtractVideoId(string input)
{
if (string.IsNullOrEmpty(input))
{
Logger.LogInfo((object)"[YouTubeHelper] Input is null or empty");
return null;
}
Logger.LogInfo((object)("[YouTubeHelper] Checking input: " + input));
if (IsYouTubeUrl(input))
{
string[] array = new string[2] { "(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([a-zA-Z0-9_-]{11})", "^([a-zA-Z0-9_-]{11})$" };
string[] array2 = array;
foreach (string pattern in array2)
{
Match match = Regex.Match(input, pattern);
if (match.Success)
{
string value = match.Groups[1].Value;
Logger.LogInfo((object)("[YouTubeHelper] YouTube video ID detected: " + value));
return value;
}
}
}
if (IsTwitterUrl(input))
{
Logger.LogInfo((object)("[YouTubeHelper] Twitter/X URL detected: " + input));
return input;
}
Logger.LogInfo((object)("[YouTubeHelper] Not a supported video URL: " + input));
return null;
}
private static bool IsYouTubeUrl(string input)
{
return Regex.IsMatch(input, "(youtube\\.com|youtu\\.be)") || Regex.IsMatch(input, "^[a-zA-Z0-9_-]{11}$");
}
private static bool IsTwitterUrl(string input)
{
return Regex.IsMatch(input, "(twitter\\.com|x\\.com)/.+/status/\\d+", RegexOptions.IgnoreCase);
}
public static async Task<string> GetYouTubeUrlAsync(string videoIdOrUrl, string quality = "best")
{
try
{
string videoId = ExtractVideoId(videoIdOrUrl);
if (string.IsNullOrEmpty(videoId))
{
Logger.LogWarning((object)("[YouTubeHelper] Invalid video URL: " + videoIdOrUrl));
return string.Empty;
}
string targetUrl = (videoId.StartsWith("http") ? videoId : ("https://www.youtube.com/watch?v=" + videoId));
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "yt-dlp",
Arguments = "--get-url -f \"18/22/(mp4)[height<=720]/best[ext=mp4]/best\" \"" + targetUrl + "\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8
}
};
process.StartInfo.EnvironmentVariables["PYTHONIOENCODING"] = "utf-8";
Logger.LogInfo((object)("[YouTubeHelper] Executing yt-dlp: " + videoId));
process.Start();
Task<string> outputTask = process.StandardOutput.ReadToEndAsync();
Task<string> errorTask = process.StandardError.ReadToEndAsync();
await Task.WhenAll<string>(outputTask, errorTask);
await Task.Run(delegate
{
process.WaitForExit();
});
string output = outputTask.Result.Trim();
string error = errorTask.Result;
if (process.ExitCode != 0)
{
Logger.LogError((object)("[YouTubeHelper] yt-dlp error: " + error));
return string.Empty;
}
if (string.IsNullOrEmpty(output))
{
Logger.LogWarning((object)("[YouTubeHelper] 動画URLが取得できませんでした: " + videoId));
return string.Empty;
}
string[] lines = output.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
string videoUrl = lines[0];
Logger.LogInfo((object)("[YouTubeHelper] Video URL retrieved successfully: " + videoId));
return videoUrl;
}
catch (Exception ex2)
{
Exception ex = ex2;
Logger.LogError((object)("[YouTubeHelper] Exception occurred: " + ex.Message));
return string.Empty;
}
}
public static string GetYouTubeUrl(string videoIdOrUrl, string quality = "best")
{
return GetYouTubeUrlAsync(videoIdOrUrl, quality).GetAwaiter().GetResult();
}
public static async Task<string> GetVideoTitleAsync(string videoIdOrUrl)
{
try
{
string videoId = ExtractVideoId(videoIdOrUrl);
if (string.IsNullOrEmpty(videoId))
{
return string.Empty;
}
string targetUrl = (videoId.StartsWith("http") ? videoId : ("https://www.youtube.com/watch?v=" + videoId));
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "yt-dlp",
Arguments = "--get-title --encoding utf-8 \"" + targetUrl + "\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8,
StandardErrorEncoding = Encoding.UTF8
}
};
process.StartInfo.EnvironmentVariables["PYTHONIOENCODING"] = "utf-8";
process.Start();
Task<string> outputTask = process.StandardOutput.ReadToEndAsync();
await Task.Run(delegate
{
process.WaitForExit();
});
string title = outputTask.Result.Trim();
if (process.ExitCode != 0 || string.IsNullOrEmpty(title))
{
return videoId;
}
return title;
}
catch (Exception ex2)
{
Exception ex = ex2;
Logger.LogError((object)("[YouTubeHelper] タイトル取得例外: " + ex.Message));
return string.Empty;
}
}
public static string GetVideoTitle(string videoIdOrUrl)
{
return GetVideoTitleAsync(videoIdOrUrl).GetAwaiter().GetResult();
}
public static bool IsYtDlpAvailable()
{
try
{
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "yt-dlp",
Arguments = "--version",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
process.Start();
process.WaitForExit(5000);
return process.ExitCode == 0;
}
catch
{
return false;
}
}
}
}
namespace XiaohaiTV_Extended.Patches
{
public static class TVScriptBilibiliPatch
{
[CompilerGenerated]
private sealed class <PlayYoutubeCoroutine>d__6 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public object tvScriptInstance;
public string videoId;
private Task<string> <urlTask>5__1;
private Task<string> <titleTask>5__2;
private string <videoUrl>5__3;
private string <videoTitle>5__4;
private Type <photonNetworkType>5__5;
private bool <isMultiplayer>5__6;
private PropertyInfo <offlineModeProperty>5__7;
private bool <offlineMode>5__8;
private PropertyInfo <photonViewProp>5__9;
private object <photonView>5__10;
private Type <rpcTargetType>5__11;
private object <rpcTargetAll>5__12;
private Type <photonViewType>5__13;
private MethodInfo <rpcMethod>5__14;
private MethodInfo <rpcMethod>5__15;
private Exception <ex>5__16;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <PlayYoutubeCoroutine>d__6(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<urlTask>5__1 = null;
<titleTask>5__2 = null;
<videoUrl>5__3 = null;
<videoTitle>5__4 = null;
<photonNetworkType>5__5 = null;
<offlineModeProperty>5__7 = null;
<photonViewProp>5__9 = null;
<photonView>5__10 = null;
<rpcTargetType>5__11 = null;
<rpcTargetAll>5__12 = null;
<photonViewType>5__13 = null;
<rpcMethod>5__14 = null;
<rpcMethod>5__15 = null;
<ex>5__16 = null;
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Starting Youtube playback: " + videoId));
SetBilibiliReturnInfo(tvScriptInstance, "");
<urlTask>5__1 = YouTubeHelper.GetYouTubeUrlAsync(videoId);
<titleTask>5__2 = YouTubeHelper.GetVideoTitleAsync(videoId);
break;
case 1:
<>1__state = -1;
break;
}
if (!<urlTask>5__1.IsCompleted || !<titleTask>5__2.IsCompleted)
{
<>2__current = null;
<>1__state = 1;
return true;
}
<videoUrl>5__3 = <urlTask>5__1.Result;
<videoTitle>5__4 = <titleTask>5__2.Result;
if (string.IsNullOrEmpty(<videoUrl>5__3))
{
SetBilibiliReturnInfo(tvScriptInstance, "動画URLの取得に失敗しました");
Logger.LogWarning((object)("[TVScriptBilibiliPatch] Failed to get video URL: " + videoId));
return false;
}
if (<videoUrl>5__3.Contains(".m3u8") || <videoUrl>5__3.Contains("manifest/hls"))
{
SetBilibiliReturnInfo(tvScriptInstance, "Video format not supported (HLS)");
Logger.LogWarning((object)("[TVScriptBilibiliPatch] HLS format not supported: " + <videoUrl>5__3));
return false;
}
if (string.IsNullOrEmpty(<videoTitle>5__4))
{
<videoTitle>5__4 = videoId;
}
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Video retrieved: " + <videoTitle>5__4));
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Video URL: " + <videoUrl>5__3));
try
{
if (tvScriptType == null)
{
SetBilibiliReturnInfo(tvScriptInstance, "TVScript not found");
Logger.LogError((object)"[TVScriptBilibiliPatch] tvScriptType is null");
return false;
}
<photonNetworkType>5__5 = Type.GetType("Photon.Pun.PhotonNetwork, PhotonUnityNetworking");
<isMultiplayer>5__6 = false;
if (<photonNetworkType>5__5 != null)
{
<offlineModeProperty>5__7 = <photonNetworkType>5__5.GetProperty("OfflineMode", BindingFlags.Static | BindingFlags.Public);
if (<offlineModeProperty>5__7 != null)
{
<offlineMode>5__8 = (bool)<offlineModeProperty>5__7.GetValue(null);
<isMultiplayer>5__6 = !<offlineMode>5__8;
Logger.LogInfo((object)$"[TVScriptBilibiliPatch] OfflineMode: {<offlineMode>5__8}, IsMultiplayer: {<isMultiplayer>5__6}");
}
else
{
Logger.LogError((object)"[TVScriptBilibiliPatch] OfflineMode property not found");
}
<offlineModeProperty>5__7 = null;
}
else
{
Logger.LogError((object)"[TVScriptBilibiliPatch] PhotonNetwork type not found");
}
if (<isMultiplayer>5__6)
{
Logger.LogInfo((object)"[TVScriptBilibiliPatch] Multiplayer mode - sending RPC");
<photonViewProp>5__9 = tvScriptType.BaseType?.GetProperty("photonView", BindingFlags.Instance | BindingFlags.Public);
if (<photonViewProp>5__9 == null)
{
Logger.LogError((object)"[TVScriptBilibiliPatch] photonView property not found in base type");
return false;
}
<photonView>5__10 = <photonViewProp>5__9.GetValue(tvScriptInstance);
if (<photonView>5__10 == null)
{
Logger.LogError((object)"[TVScriptBilibiliPatch] photonView is null");
return false;
}
Logger.LogInfo((object)$"[TVScriptBilibiliPatch] PhotonView obtained: {<photonView>5__10}");
<rpcTargetType>5__11 = Type.GetType("Photon.Pun.RpcTarget, PhotonUnityNetworking");
if (<rpcTargetType>5__11 == null)
{
Logger.LogError((object)"[TVScriptBilibiliPatch] RpcTarget type not found");
return false;
}
<rpcTargetAll>5__12 = Enum.ToObject(<rpcTargetType>5__11, 3);
<photonViewType>5__13 = <photonView>5__10.GetType();
<rpcMethod>5__14 = <photonViewType>5__13.GetMethod("RPC", new Type[3]
{
typeof(string),
<rpcTargetType>5__11,
typeof(object[])
});
if (<rpcMethod>5__14 == null)
{
Logger.LogError((object)"[TVScriptBilibiliPatch] RPC method not found");
return false;
}
Logger.LogInfo((object)"[TVScriptBilibiliPatch] Invoking RPC...");
<rpcMethod>5__14.Invoke(<photonView>5__10, new object[3]
{
"RPC_AddPlaylistItem",
<rpcTargetAll>5__12,
new object[3] { <videoUrl>5__3, <videoTitle>5__4, true }
});
Logger.LogInfo((object)"[TVScriptBilibiliPatch] RPC invoked successfully");
<photonViewProp>5__9 = null;
<photonView>5__10 = null;
<rpcTargetType>5__11 = null;
<rpcTargetAll>5__12 = null;
<photonViewType>5__13 = null;
<rpcMethod>5__14 = null;
}
else
{
Logger.LogInfo((object)"[TVScriptBilibiliPatch] Singleplayer mode - calling directly");
<rpcMethod>5__15 = tvScriptType.GetMethod("RPC_AddPlaylistItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (<rpcMethod>5__15 == null)
{
Logger.LogError((object)"[TVScriptBilibiliPatch] RPC_AddPlaylistItem method not found");
return false;
}
<rpcMethod>5__15.Invoke(tvScriptInstance, new object[3] { <videoUrl>5__3, <videoTitle>5__4, true });
Logger.LogInfo((object)"[TVScriptBilibaliPatch] RPC_AddPlaylistItem called successfully");
<rpcMethod>5__15 = null;
}
SetBilibiliReturnInfo(tvScriptInstance, "Youtube動画再生成功!");
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Youtube video added to playlist: " + <videoTitle>5__4));
<photonNetworkType>5__5 = null;
}
catch (Exception ex)
{
<ex>5__16 = ex;
SetBilibiliReturnInfo(tvScriptInstance, "再生エラー: " + <ex>5__16.Message);
Logger.LogError((object)$"[TVScriptBilibiliPatch] Playback error: {<ex>5__16}");
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static Type? tvScriptType;
private static ManualLogSource Logger => XiaohaiTV_Extended.Logger;
public static void ApplyPatch(Harmony harmony)
{
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Expected O, but got Unknown
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Expected O, but got Unknown
Logger.LogInfo((object)"[TVScriptBilibiliPatch] Searching for TVScript...");
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Assembly[] array = assemblies;
foreach (Assembly assembly in array)
{
try
{
Type[] types = assembly.GetTypes();
Type[] array2 = types;
foreach (Type type in array2)
{
if (!(type.FullName == "REPO_TV.TVScript"))
{
continue;
}
tvScriptType = type;
Logger.LogInfo((object)("[TVScriptBilibiliPatch] TVScript found in " + assembly.GetName().Name));
MethodInfo method = type.GetMethod("ExtractBVFromInput", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
Logger.LogInfo((object)"[TVScriptBilibiliPatch] ExtractBVFromInput method found");
MethodInfo method2 = typeof(TVScriptBilibiliPatch).GetMethod("ExtractBVFromInput_Postfix", BindingFlags.Static | BindingFlags.Public);
if (method2 != null)
{
harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Logger.LogInfo((object)"[TVScriptBilibiliPatch] ExtractBVFromInput patch applied!");
}
}
MethodInfo method3 = type.GetMethod("PlayBilibiliCoroutine", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method3 != null)
{
Logger.LogInfo((object)$"[TVScriptBilibiliPatch] PlayBilibiliCoroutine method found: {method3}");
MethodInfo method4 = typeof(TVScriptBilibiliPatch).GetMethod("PlayBilibiliCoroutine_Prefix", BindingFlags.Static | BindingFlags.Public);
if (method4 != null)
{
harmony.Patch((MethodBase)method3, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Logger.LogInfo((object)"[TVScriptBilibiliPatch] PlayBilibiliCoroutine patch applied!");
}
else
{
Logger.LogError((object)"[TVScriptBilibiliPatch] Prefix method not found!");
}
}
else
{
Logger.LogWarning((object)"[TVScriptBilibiliPatch] PlayBilibiliCoroutine method not found");
}
return;
}
}
catch
{
}
}
Logger.LogWarning((object)"[TVScriptBilibiliPatch] TVScript type not found. Patch will be applied when REPO_TV loads.");
}
public static void ExtractBVFromInput_Postfix(string input, ref string __result)
{
try
{
if (!string.IsNullOrEmpty(__result))
{
Logger.LogInfo((object)("[TVScriptBilibiliPatch] ExtractBVFromInput returned BV: " + __result));
return;
}
string value = YouTubeHelper.ExtractVideoId(input);
if (!string.IsNullOrEmpty(value))
{
Logger.LogInfo((object)("[TVScriptBilibiliPatch] ExtractBVFromInput detected Youtube URL, passing through: " + input));
__result = input;
}
}
catch (Exception arg)
{
Logger.LogError((object)$"[TVScriptBilibiliPatch] ExtractBVFromInput_Postfix exception: {arg}");
}
}
public static bool PlayBilibiliCoroutine_Prefix(object __instance, string bv, ref IEnumerator __result)
{
try
{
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Prefix called with input: " + bv));
string text = YouTubeHelper.ExtractVideoId(bv);
if (!string.IsNullOrEmpty(text))
{
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Youtube URL detected: " + text + ", skipping original method"));
__result = PlayYoutubeCoroutine(__instance, text);
return false;
}
Logger.LogInfo((object)("[TVScriptBilibiliPatch] Bilibili BV号 detected: " + bv + ", running original method"));
return true;
}
catch (Exception arg)
{
Logger.LogError((object)$"[TVScriptBilibiliPatch] Prefix exception: {arg}");
return true;
}
}
[IteratorStateMachine(typeof(<PlayYoutubeCoroutine>d__6))]
private static IEnumerator PlayYoutubeCoroutine(object tvScriptInstance, string videoId)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <PlayYoutubeCoroutine>d__6(0)
{
tvScriptInstance = tvScriptInstance,
videoId = videoId
};
}
private static void SetBilibiliReturnInfo(object tvScriptInstance, string message)
{
try
{
if (!(tvScriptType == null))
{
FieldInfo field = tvScriptType.GetField("bilibiliReturnInfo", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(tvScriptInstance, message);
}
}
}
catch (Exception arg)
{
Logger.LogError((object)$"[TVScriptBilibiliPatch] Failed to set bilibiliReturnInfo: {arg}");
}
}
}
}