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; }
}
}