Decompiled source of TikTokTTS v1.1.1

TikTokTTS.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;

[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: AssemblyCompany("MyFirstPlugin")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("My first plugin")]
[assembly: AssemblyTitle("MyFirstPlugin")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TikTokTTS
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "MyFirstPlugin";

		public const string PLUGIN_NAME = "My first plugin";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace TTSVoiceOverride
{
	[BepInPlugin("com.Porkey27.TikTokTTS", "TikTokTTS", "1.0.0")]
	public class TTSVoicePlugin : BaseUnityPlugin
	{
		public static ConfigEntry<string> SpeakerNormal;

		public static ConfigEntry<string> SpeakerCrouching;

		public static ConfigEntry<string> SessionID;

		private void Awake()
		{
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Expected O, but got Unknown
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Expected O, but got Unknown
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Expected O, but got Unknown
			string[] array = new string[98]
			{
				"en_male_jomboy", "en_us_002", "es_mx_002", "en_male_funny", "en_us_ghostface", "en_female_samc", "en_male_cody", "en_female_makeup", "en_female_richgirl", "en_male_grinch",
				"en_us_006", "en_male_narration", "en_male_deadpool", "en_uk_001", "en_uk_003", "en_au_001", "en_male_jarvis", "en_male_ashmagic", "en_male_olantekkers", "en_male_ukneighbor",
				"en_male_ukbutler", "en_female_shenna", "en_female_pansino", "en_male_trevor", "en_female_f08_twinkle", "en_male_m03_classical", "en_female_betty", "en_male_cupid", "en_female_grandma", "en_male_m2_xhxs_m03_christmas",
				"en_male_santa_narration", "en_male_sing_deep_jingle", "en_male_santa_effect", "en_female_ht_f08_newyear", "en_male_wizard", "en_female_ht_f08_halloween", "en_female_ht_f08_glorious", "en_male_sing_funny_it_goes_up", "en_female_ht_f08_wonderful_world", "en_male_m2_xhxs_m03_silly",
				"en_female_emotional", "en_male_m03_sunshine_soon", "en_female_f08_warmy_breeze", "en_male_m03_lobby", "en_male_sing_funny_thanksgiving", "en_female_f08_salut_damour", "en_us_007", "en_us_009", "en_us_010", "en_au_002",
				"en_us_chewbacca", "en_us_c3po", "en_us_stitch", "en_us_stormtrooper", "en_us_rocket", "en_female_madam_leota", "en_male_ghosthost", "en_male_pirate", "fr_001", "fr_002",
				"es_002", "br_001", "br_003", "br_004", "br_005", "bp_female_ivete", "bp_female_ludmilla", "pt_female_lhays", "pt_female_laizza", "pt_male_bueno",
				"de_001", "de_002", "id_001", "jp_001", "jp_003", "jp_005", "jp_006", "jp_female_fujicochan", "jp_female_hasegawariona", "jp_male_keiichinakano",
				"jp_female_oomaeaika", "jp_male_yujinchigusa", "jp_female_shirou", "jp_male_tamawakazuki", "jp_female_kaorishoji", "jp_female_yagishaki", "jp_male_hikakin", "jp_female_rei", "jp_male_shuichiro", "jp_male_matsudake",
				"jp_female_machikoriiita", "jp_male_matsuo", "jp_male_osada", "kr_002", "kr_003", "kr_004", "BV074_streaming", "BV075_streaming"
			};
			SpeakerNormal = ((BaseUnityPlugin)this).Config.Bind<string>("TTS", "SpeakerNormal", "en_us_002", new ConfigDescription("Voice when not crouching", (AcceptableValueBase)(object)new AcceptableValueList<string>(array), Array.Empty<object>()));
			SpeakerCrouching = ((BaseUnityPlugin)this).Config.Bind<string>("TTS", "SpeakerCrouching", "en_us_ghostface", new ConfigDescription("Voice when crouching", (AcceptableValueBase)(object)new AcceptableValueList<string>(array), Array.Empty<object>()));
			SessionID = ((BaseUnityPlugin)this).Config.Bind<string>("TTS", "SessionID", "", new ConfigDescription("TikTok session ID for TTS requests", (AcceptableValueBase)null, Array.Empty<object>()));
			Harmony val = new Harmony("com.Porkey27.TikTokTTS");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("TTS Voice Override loaded. Normal: " + SpeakerNormal.Value + ", Crouching: " + SpeakerCrouching.Value));
		}
	}
	[HarmonyPatch(typeof(TTSVoice), "Start")]
	internal class PatchTTSVoiceStart
	{
		private static void Postfix(TTSVoice __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<TTSVoice2>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<TTSVoice2>();
				Debug.Log((object)"[TikTokTTS] TTSVoice2 attached to GameObject.");
			}
		}
	}
	[HarmonyPatch(typeof(TTSVoice), "TTSSpeakNow")]
	internal class PatchTTSSpeakNow
	{
		private static bool Prefix(TTSVoice __instance, string text, bool crouch)
		{
			Debug.Log((object)"[TikTokTTS] Prefix: Intercepted TTSSpeakNow");
			TTSVoice2 component = ((Component)__instance).GetComponent<TTSVoice2>();
			if ((Object)(object)component != (Object)null)
			{
				component.TTSSpeakNow(text, crouch);
				return false;
			}
			Debug.LogError((object)"[TikTokTTS] TTSVoice2 not found, falling back to original.");
			return true;
		}
	}
	public class TTSVoice2 : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <GetAudio>d__11 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string url;

			public TTSVoice2 <>4__this;

			private UnityWebRequest <www>5__1;

			private Root <root>5__2;

			private byte[] <bytes>5__3;

			private string <path>5__4;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetAudio>d__11(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<www>5__1 = null;
				<root>5__2 = null;
				<bytes>5__3 = null;
				<path>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Invalid comparison between Unknown and I4
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<www>5__1 = UnityWebRequest.PostWwwForm(url, "");
						<>1__state = -3;
						<www>5__1.SetRequestHeader("User-Agent", "com.zhiliaoapp.musically/2022600030 (Linux; U; Android 7.1.2; es_ES; SM-G988N; Build/NRD90M;tt-ok/3.12.13.1)");
						<www>5__1.SetRequestHeader("Cookie", "sessionid=" + TTSVoicePlugin.SessionID.Value);
						<www>5__1.SetRequestHeader("Accept-Encoding", "gzip,deflate,compress");
						<>2__current = <www>5__1.SendWebRequest();
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -3;
						if ((int)<www>5__1.result == 1)
						{
							Debug.Log((object)("\nReceived: " + <www>5__1.downloadHandler.text));
							<root>5__2 = JsonConvert.DeserializeObject<Root>(<www>5__1.downloadHandler.text);
							if (<root>5__2.message != "success")
							{
								Debug.LogError((object)("TTS Error: " + <root>5__2.message));
							}
							else
							{
								<bytes>5__3 = Convert.FromBase64String(<root>5__2.data.v_str);
								<path>5__4 = Path.Combine(Application.persistentDataPath, "TTS.mp3");
								File.WriteAllBytes(<path>5__4, <bytes>5__3);
								<>4__this.Play(<path>5__4);
								<bytes>5__3 = null;
								<path>5__4 = null;
							}
							<root>5__2 = null;
						}
						else
						{
							Debug.LogError((object)("TTS error: " + <www>5__1.error));
						}
						<>m__Finally1();
						<www>5__1 = null;
						return false;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<www>5__1 != null)
				{
					((IDisposable)<www>5__1).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SetAudio>d__13 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string path;

			public TTSVoice2 <>4__this;

			private UnityWebRequest <www>5__1;

			private AudioClip <clip>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetAudio>d__13(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<www>5__1 = null;
				<clip>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Invalid comparison between Unknown and I4
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						path = "file://" + path;
						<www>5__1 = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)13);
						<>1__state = -3;
						<>2__current = <www>5__1.SendWebRequest();
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -3;
						if ((int)<www>5__1.result == 1)
						{
							<clip>5__2 = DownloadHandlerAudioClip.GetContent(<www>5__1);
							<>4__this.audioSource.clip = <clip>5__2;
							<>4__this.audioSource.Play();
							<>4__this.isSpeaking = true;
							<clip>5__2 = null;
						}
						else
						{
							Debug.LogError((object)("Audio Load Error: " + <www>5__1.error));
						}
						<>m__Finally1();
						<www>5__1 = null;
						return false;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<www>5__1 != null)
				{
					((IDisposable)<www>5__1).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal PlayerAvatar playerAvatar;

		internal bool isSpeaking;

		internal float currentWordTime;

		internal string voiceText;

		private AudioSource audioSource;

		private readonly string BASE_URL = "api22-normal-c-useast2a.tiktokv.com";

		private readonly string API_PATH = "/media/api/text/speech/invoke/";

		private void Awake()
		{
			if (string.IsNullOrEmpty(TTSVoicePlugin.SessionID.Value))
			{
				Debug.LogError((object)"Please set the SessionID config value in BepInEx/config/com.yourname.TikTokTTS.cfg");
			}
			audioSource = ((Component)this).gameObject.GetComponent<AudioSource>();
			if (!Object.op_Implicit((Object)(object)audioSource))
			{
				audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			}
		}

		public void TTSSpeakNow(string text, bool crouching)
		{
			((MonoBehaviour)this).StopAllCoroutines();
			StopAudio();
			voiceText = TranslateSpecialLetters(text);
			CreateAudioFromText(voiceText, crouching);
		}

		private string TranslateSpecialLetters(string _text)
		{
			_text = _text.Replace("ö", "oe").Replace("Ö", "OE").Replace("ä", "ae")
				.Replace("Ä", "AE")
				.Replace("å", "oa")
				.Replace("Å", "OA")
				.Replace("ü", "ue")
				.Replace("Ü", "UE")
				.Replace("ß", "ss")
				.Replace("æ", "ae")
				.Replace("Æ", "AE")
				.Replace("ø", "oe")
				.Replace("Ø", "OE");
			return _text;
		}

		public void CreateAudioFromText(string msg, bool crouching)
		{
			Debug.Log((object)("get text: " + msg));
			msg = msg.Replace("+", "plus");
			msg = msg.Replace("&", "and");
			msg = Regex.Replace(msg, "\\s+", "+");
			string text = (crouching ? TTSVoicePlugin.SpeakerCrouching.Value : TTSVoicePlugin.SpeakerNormal.Value);
			Debug.Log((object)("speaker: " + text));
			string text2 = "https://" + BASE_URL + API_PATH + "?text_speaker=" + text + "&req_text=" + msg + "&speaker_map_type=0&aid=1233";
			Debug.Log((object)("url: " + text2));
			((MonoBehaviour)this).StartCoroutine(GetAudio(text2));
		}

		[IteratorStateMachine(typeof(<GetAudio>d__11))]
		private IEnumerator GetAudio(string url)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetAudio>d__11(0)
			{
				<>4__this = this,
				url = url
			};
		}

		public void Play(string path)
		{
			Debug.Log((object)("PlayAudio: " + path));
			((MonoBehaviour)this).StartCoroutine(SetAudio(path));
		}

		[IteratorStateMachine(typeof(<SetAudio>d__13))]
		private IEnumerator SetAudio(string path)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetAudio>d__13(0)
			{
				<>4__this = this,
				path = path
			};
		}

		private void StopAudio()
		{
			if ((Object)(object)audioSource != (Object)null)
			{
				audioSource.Stop();
			}
			isSpeaking = false;
		}
	}
	public class Data
	{
		public string s_key { get; set; }

		public string v_str { get; set; }

		public string duration { get; set; }

		public string speaker { get; set; }
	}
	public class Extra
	{
		public string log_id { get; set; }
	}
	public class Root
	{
		public Data data { get; set; }

		public Extra extra { get; set; }

		public string message { get; set; }

		public int status_code { get; set; }

		public string status_msg { get; set; }
	}
}