Decompiled source of TootTallyTwitchIntegration v1.0.2

plugins/TootTallyTwitchIntegration.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BaboonAPI.Hooks.Initializer;
using BaboonAPI.Hooks.Tracks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Logging;
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;
using Newtonsoft.Json;
using TMPro;
using TootTallyAccounts;
using TootTallyCore;
using TootTallyCore.APIServices;
using TootTallyCore.Graphics;
using TootTallyCore.Graphics.Animations;
using TootTallyCore.Utils.Assets;
using TootTallyCore.Utils.Helpers;
using TootTallyCore.Utils.TootTallyModules;
using TootTallyCore.Utils.TootTallyNotifs;
using TootTallySettings;
using TrombLoader.CustomTracks;
using TwitchLib.Client;
using TwitchLib.Client.Enums;
using TwitchLib.Client.Events;
using TwitchLib.Client.Models;
using TwitchLib.Communication.Clients;
using TwitchLib.Communication.Events;
using TwitchLib.Communication.Interfaces;
using TwitchLib.Communication.Models;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("TootTallyTwitchIntegration")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Twitch integration with song requests and more")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("TootTallyTwitchIntegration")]
[assembly: AssemblyTitle("TootTallyTwitchIntegration")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.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 TootTallyTwitchIntegration
{
	public static class FileManager
	{
		public const string requestFileName = "TwitchRequests.json";

		public const string blockFileName = "BlockedRequests.json";

		public static void SaveRequestsQueueToFile(List<Plugin.Request> requests)
		{
			string path = Path.Combine(Paths.ConfigPath, "TwitchRequests.json");
			if (File.Exists(path))
			{
				File.Delete(path);
			}
			File.WriteAllText(path, JsonConvert.SerializeObject((object)requests));
		}

		public static List<Plugin.Request> GetRequestsFromFile()
		{
			string path = Path.Combine(Paths.ConfigPath, "TwitchRequests.json");
			if (File.Exists(path))
			{
				try
				{
					return JsonConvert.DeserializeObject<List<Plugin.Request>>(File.ReadAllText(path));
				}
				catch (Exception ex)
				{
					Plugin.LogError("Couldn't parse request queue file.");
					Plugin.LogError(ex.Message);
					Plugin.LogError(ex.StackTrace);
				}
			}
			return new List<Plugin.Request>();
		}

		public static void SaveBlockedRequestsToFile(List<Plugin.BlockedRequests> requests)
		{
			string path = Path.Combine(Paths.ConfigPath, "BlockedRequests.json");
			if (File.Exists(path))
			{
				File.Delete(path);
			}
			File.WriteAllText(path, JsonConvert.SerializeObject((object)requests));
		}

		public static List<Plugin.BlockedRequests> GetBlockedRequestsFromFile()
		{
			string path = Path.Combine(Paths.ConfigPath, "BlockedRequests.json");
			if (File.Exists(path))
			{
				try
				{
					return JsonConvert.DeserializeObject<List<Plugin.BlockedRequests>>(File.ReadAllText(path));
				}
				catch (Exception ex)
				{
					Plugin.LogError("Couldn't parse block list file.");
					Plugin.LogError(ex.Message);
					Plugin.LogError(ex.StackTrace);
				}
			}
			return new List<Plugin.BlockedRequests>();
		}
	}
	[BepInPlugin("TootTallyTwitchIntegration", "TootTallyTwitchIntegration", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin, ITootTallyModule
	{
		public static class TwitchPatches
		{
			private static string _selectedSongTrackRef;

			[HarmonyPatch(typeof(GameObjectFactory), "OnHomeControllerInitialize")]
			[HarmonyPostfix]
			public static void InitializeRequestPanel()
			{
				RequestPanelManager.Initialize();
			}

			[HarmonyPatch(typeof(HomeController), "Start")]
			[HarmonyPostfix]
			public static void DeInitialize()
			{
				RequestPanelManager.songSelectInstance = null;
			}

			[HarmonyPatch(typeof(TootTallyUser), "OnUserLogin")]
			[HarmonyPostfix]
			public static void OnUserLoginInitializeBot()
			{
				Instance.StartBotCoroutine();
			}

			[HarmonyPatch(typeof(HomeController), "tryToSaveSettings")]
			[HarmonyPostfix]
			public static void InitializeRequestPanelOnSaveConfig()
			{
				Instance.StartBotCoroutine();
			}

			[HarmonyPatch(typeof(GameController), "Start")]
			[HarmonyPostfix]
			public static void SetCurrentSong()
			{
				RequestPanelManager.songSelectInstance = null;
				RequestPanelManager.isPlaying = true;
				TromboneTrack val = TrackLookup.lookup(GlobalVariables.chosen_track_data.trackref);
				string songHash = SongDataHelper.GetSongHash(val);
				((MonoBehaviour)Instance).StartCoroutine((IEnumerator)TootTallyAPIService.GetHashInDB(songHash, val is CustomTrack, (Action<int>)delegate(int id)
				{
					RequestPanelManager.currentSongID = id;
				}));
			}

			[HarmonyPatch(typeof(PointSceneController), "Start")]
			[HarmonyPostfix]
			public static void ResetCurrentSong()
			{
				RequestPanelManager.isPlaying = false;
				RequestPanelManager.Remove(GlobalVariables.chosen_track_data.trackref);
			}

			[HarmonyPatch(typeof(LevelSelectController), "Start")]
			[HarmonyPostfix]
			public static void StartBot(LevelSelectController __instance, int ___songindex)
			{
				RequestPanelManager.songSelectInstance = __instance;
				RequestPanelManager.songIndex = ___songindex;
				RequestPanelManager.isPlaying = false;
			}

			[HarmonyPatch(typeof(LevelSelectController), "advanceSongs")]
			[HarmonyPostfix]
			public static void UpdateInstance(LevelSelectController __instance, int ___songindex)
			{
				RequestPanelManager.songSelectInstance = __instance;
				RequestPanelManager.songIndex = ___songindex;
			}

			[HarmonyPatch(typeof(LevelSelectController), "clickBack")]
			[HarmonyPrefix]
			private static bool OnClickBackSkipIfPanelActive()
			{
				return ShouldScrollSongs();
			}

			[HarmonyPatch(typeof(LevelSelectController), "clickNext")]
			[HarmonyPrefix]
			private static bool OnClickNextSkipIfScrollWheelUsed()
			{
				return ShouldScrollSongs();
			}

			[HarmonyPatch(typeof(LevelSelectController), "clickPrev")]
			[HarmonyPrefix]
			private static bool OnClickBackSkipIfScrollWheelUsed()
			{
				return ShouldScrollSongs();
			}

			private static bool ShouldScrollSongs()
			{
				return RequestPanelManager.ShouldScrollSongs();
			}
		}

		[Serializable]
		public class Request
		{
			public string requester;

			public SongDataFromDB songData;

			public int song_id;

			public string date;
		}

		[Serializable]
		public class BlockedRequests
		{
			public int song_id;
		}

		public class UnprocessedRequest
		{
			public string requester;

			public int song_id;
		}

		public class Notif
		{
			public string message;
		}

		public static Plugin Instance;

		private const string CONFIG_NAME = "TwitchIntegration.cfg";

		private const string CONFIG_FIELD = "Twitch";

		private Harmony _harmony;

		public static TootTallySettingPage settingPage;

		public TwitchBot Bot = null;

		public RequestController requestController;

		public ConfigEntry<bool> ModuleConfigEnabled { get; set; }

		public bool IsConfigInitialized { get; set; }

		public string Name
		{
			get
			{
				return "Twitch Integration";
			}
			set
			{
				Name = value;
			}
		}

		public ConfigEntry<bool> EnableRequestsCommand { get; set; }

		public ConfigEntry<bool> EnableProfileCommand { get; set; }

		public ConfigEntry<bool> EnableCurrentSongCommand { get; set; }

		public ConfigEntry<bool> SubOnlyMode { get; set; }

		public ConfigEntry<string> TwitchUsername { get; set; }

		public ConfigEntry<string> TwitchAccessToken { get; set; }

		public ConfigEntry<float> MaxRequestCount { get; set; }

		public static void LogInfo(string msg)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg);
		}

		public static void LogError(string msg)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)msg);
		}

		public static void LogDebug(string msg)
		{
			((BaseUnityPlugin)Instance).Logger.LogDebug((object)msg);
		}

		private void Awake()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				Instance = this;
				_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				GameInitializationEvent.Register(((BaseUnityPlugin)this).Info, (Action)TryInitialize);
			}
		}

		private void Update()
		{
			RequestPanelManager.Update();
		}

		private void TryInitialize()
		{
			ModuleConfigEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Modules", "Twitch", true, "Twitch integration with song requests and more.");
			TootTallyModuleManager.AddModule((ITootTallyModule)(object)this);
			Plugin.Instance.AddModuleToSettingPage((ITootTallyModule)(object)this);
		}

		public void LoadModule()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			AssetManager.LoadAssets(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "Assets"));
			string text = Path.Combine(Paths.BepInExRootPath, "config/");
			string toottallyTwitchLink = "https://toottally.com/twitch/";
			ConfigFile val = new ConfigFile(text + "TwitchIntegration.cfg", true)
			{
				SaveOnConfigSet = true
			};
			EnableRequestsCommand = val.Bind<bool>("Twitch", "Enable requests command", true, "Allow people to requests songs using !ttr [songID]");
			EnableCurrentSongCommand = val.Bind<bool>("Twitch", "Enable current song command", true, "!song command that sends a link to the current song into the chat");
			EnableProfileCommand = val.Bind<bool>("Twitch", "Enable profile command", true, "!profile command that links your toottally profile into the chat");
			SubOnlyMode = val.Bind<bool>("Twitch", "Sub-only requests", false, "Only allow subscribers to send requests");
			TwitchUsername = val.Bind<string>("Twitch", "Twitch channel to attach to", "", "Paste your twitch username here");
			TwitchAccessToken = val.Bind<string>("Twitch", "Twitch Access Token", "", "Paste the access token from the website here");
			MaxRequestCount = val.Bind<float>("Twitch", "Max Request Count", 50f, "Maximum request count allowed in queue");
			settingPage = TootTallySettingsManager.AddNewPage("Twitch", "Twitch Integration Settings", 40f, new Color(0.1f, 0.1f, 0.1f, 0.1f));
			if (settingPage != null)
			{
				settingPage.AddToggle("Enable Requests Command", EnableRequestsCommand, (UnityAction<bool>)null);
				settingPage.AddToggle("Enable Current Songs Command", EnableCurrentSongCommand, (UnityAction<bool>)null);
				settingPage.AddToggle("Enable Profile Command", EnableProfileCommand, (UnityAction<bool>)null);
				settingPage.AddSlider("Max Request Count", 0f, 200f, MaxRequestCount, true);
				settingPage.AddLabel("TwitchSpecificSettingsLabel", "Twitch Integration", 24f, (FontStyles)0, (TextAlignmentOptions)4097);
				settingPage.AddLabel("TwitchSpecificUsernameLabel", "Username", 16f, (FontStyles)0, (TextAlignmentOptions)1025);
				settingPage.AddTextField("Twitch Username", new Vector2(350f, 50f), 20f, TwitchUsername.Value, ((ConfigEntryBase)TwitchUsername).Description.Description, false, (Action<string>)SetTwitchUsername);
				settingPage.AddLabel("TwitchSpecificAccessTokenLabel", "AccessToken", 16f, (FontStyles)0, (TextAlignmentOptions)1025);
				settingPage.AddTextField("Twitch Access Token", new Vector2(350f, 50f), 20f, TwitchAccessToken.Value, ((ConfigEntryBase)TwitchAccessToken).Description.Description, true, (Action<string>)SetTwitchAccessToken);
				settingPage.AddButton("AuthorizeTwitchButton", new Vector2(450f, 50f), "Authorize TootTally on Twitch", "Opens a page to get your auth token", (Action)delegate
				{
					Application.OpenURL(toottallyTwitchLink);
				});
				settingPage.AddLabel("TwitchBotButtons", "Twitch Bot Settings", 24f, (FontStyles)0, (TextAlignmentOptions)4097);
				settingPage.AddButton("ConnectDisconnectBot", new Vector2(350f, 50f), "Connect/Disconnect Bot", "Rarely useful if the bot fails to connect after setting the auth token", (Action)delegate
				{
					if (Bot == null)
					{
						StartBotCoroutine();
					}
					else
					{
						Bot.Disconnect();
						Bot = null;
					}
				});
				settingPage.AddLabel("TwitchBotInstruction", "Twitch bot will also automatically start when you enter the song select menu.", 16f, (FontStyles)0, (TextAlignmentOptions)4097);
			}
			requestController = ((Component)this).gameObject.AddComponent<RequestController>();
			Plugin.TryAddThunderstoreIconToPageButton(((BaseUnityPlugin)Instance).Info.Location, Name, settingPage);
			ThemeManager.OnThemeRefreshEvents = (Action)Delegate.Combine(ThemeManager.OnThemeRefreshEvents, new Action(RequestPanelManager.UpdateTheme));
			_harmony.PatchAll(typeof(TwitchPatches));
			LogInfo("Module loaded!");
		}

		public void UnloadModule()
		{
			ThemeManager.OnThemeRefreshEvents = (Action)Delegate.Remove(ThemeManager.OnThemeRefreshEvents, new Action(RequestPanelManager.UpdateTheme));
			RequestPanelManager.Dispose();
			Bot?.Disconnect();
			Bot = null;
			requestController?.Dispose();
			Object.DestroyImmediate((Object)(object)requestController);
			((MonoBehaviour)this).StopAllCoroutines();
			_harmony.UnpatchSelf();
			settingPage.Remove();
			LogInfo("Module unloaded!");
		}

		private void SetTwitchUsername(string text)
		{
			Instance.TwitchUsername.Value = text;
			TootTallyNotifManager.DisplayNotif("Twitch username is set to '" + text + "'", 6f);
		}

		public void StartBotCoroutine()
		{
			if (Bot == null)
			{
				Bot = new TwitchBot();
			}
		}

		private void SetTwitchAccessToken(string text)
		{
			Instance.TwitchAccessToken.Value = text;
		}
	}
	public class RequestController : MonoBehaviour
	{
		private ConcurrentQueue<Plugin.Notif> NotifQueue;

		private ConcurrentQueue<Plugin.UnprocessedRequest> RequestQueue;

		public List<string> RequesterBlacklist { get; set; }

		public void Awake()
		{
			NotifQueue = new ConcurrentQueue<Plugin.Notif>();
			RequestQueue = new ConcurrentQueue<Plugin.UnprocessedRequest>();
			RequesterBlacklist = new List<string>();
		}

		public void Update()
		{
			if (RequestPanelManager.isPlaying)
			{
				return;
			}
			if (RequestQueue.TryDequeue(out var request))
			{
				Plugin.LogInfo($"Attempting to get song data for ID {request.song_id}");
				((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)TootTallyAPIService.GetSongDataFromDB(request.song_id, (Action<SongDataFromDB>)delegate(SongDataFromDB songdata)
				{
					Plugin.LogInfo("Obtained request by " + request.requester + " for song " + songdata.author + " - " + songdata.name);
					TootTallyNotifManager.DisplayNotif("Requested song by " + request.requester + ": " + songdata.author + " - " + songdata.name, 6f);
					Plugin.Request request2 = new Plugin.Request
					{
						requester = request.requester,
						songData = songdata,
						song_id = request.song_id,
						date = DateTime.Now.ToString()
					};
					RequestPanelManager.AddRow(request2);
				}));
			}
			if (NotifQueue.TryDequeue(out var result))
			{
				Plugin.LogInfo("Attempting to generate notification...");
				TootTallyNotifManager.DisplayNotif(result.message, 6f);
			}
		}

		public void RequestSong(int song_id, string requester, bool isSubscriber = false)
		{
			if (!RequesterBlacklist.Contains(requester))
			{
				if (RequestPanelManager.IsBlocked(song_id))
				{
					Plugin.Instance.Bot.client.SendMessage(Plugin.Instance.Bot.CHANNEL, $"!Song #{song_id} is blocked.", false);
				}
				else if (RequestPanelManager.IsDuplicate(song_id) && !RequestQueue.Any((Plugin.UnprocessedRequest x) => x.song_id == song_id))
				{
					Plugin.Instance.Bot.client.SendMessage(Plugin.Instance.Bot.CHANNEL, $"!Song #{song_id} already requested.", false);
				}
				else if ((float)RequestPanelManager.RequestCount >= Plugin.Instance.MaxRequestCount.Value)
				{
					Plugin.Instance.Bot.client.SendMessage(Plugin.Instance.Bot.CHANNEL, "!Request cap reached.", false);
				}
				else if (!Plugin.Instance.SubOnlyMode.Value || isSubscriber)
				{
					Plugin.UnprocessedRequest unprocessedRequest = new Plugin.UnprocessedRequest();
					unprocessedRequest.song_id = song_id;
					unprocessedRequest.requester = requester;
					Plugin.LogInfo($"Accepted request {song_id} by {requester}.");
					Plugin.Instance.Bot.client.SendMessage(Plugin.Instance.Bot.CHANNEL, $"!Song #{song_id} successfully requested.", false);
					RequestQueue.Enqueue(unprocessedRequest);
				}
			}
		}

		public void Dispose()
		{
			NotifQueue?.Clear();
			NotifQueue = null;
			RequestQueue?.Clear();
			RequestQueue = null;
			RequesterBlacklist?.Clear();
			RequesterBlacklist = null;
		}
	}
	public static class RequestPanelManager
	{
		private const float MIN_POS_Y = -40f;

		public static GameObject requestRowPrefab;

		public static LevelSelectController songSelectInstance;

		public static int songIndex;

		public static bool isPlaying;

		private static List<RequestPanelRow> _requestRowList;

		private static List<Plugin.Request> _requestList;

		private static List<Plugin.BlockedRequests> _blockedList;

		private static List<int> _songIDHistory;

		public static int currentSongID;

		private static ScrollableSliderHandler _scrollableHandler;

		private static Slider _slider;

		private static RectTransform _containerRect;

		private static TootTallyAnimation _panelAnimationFG;

		private static TootTallyAnimation _panelAnimationBG;

		private static GameObject _overlayPanel;

		private static GameObject _overlayCanvas;

		private static GameObject _overlayPanelContainer;

		private static bool _isPanelActive;

		private static bool _isInitialized;

		private static bool _isAnimating;

		public static int RequestCount => _requestList.Count;

		public static void Initialize()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			if (!_isInitialized)
			{
				_overlayCanvas = new GameObject("TwitchOverlayCanvas");
				Canvas val = _overlayCanvas.AddComponent<Canvas>();
				val.renderMode = (RenderMode)0;
				val.overrideSorting = true;
				val.sortingOrder = 1;
				CanvasScaler val2 = _overlayCanvas.AddComponent<CanvasScaler>();
				val2.referenceResolution = new Vector2(1920f, 1080f);
				val2.uiScaleMode = (ScaleMode)1;
				_requestRowList = new List<RequestPanelRow>();
				_requestList = new List<Plugin.Request>();
				_blockedList = new List<Plugin.BlockedRequests>();
				_songIDHistory = new List<int>();
				Object.DontDestroyOnLoad((Object)(object)_overlayCanvas);
				_overlayPanel = GameObjectFactory.CreateOverlayPanel(_overlayCanvas.transform, Vector2.zero, new Vector2(1700f, 900f), 20f, "TwitchOverlayPanel");
				_overlayPanelContainer = ((Component)_overlayPanel.transform.Find("FSLatencyPanel/LatencyFG/MainPage")).gameObject;
				_slider = new GameObject("TwitchPanelSlider", new Type[1] { typeof(Slider) }).GetComponent<Slider>();
				((Component)_slider).transform.SetParent(_overlayPanel.transform);
				((UnityEvent<float>)(object)_slider.onValueChanged).AddListener((UnityAction<float>)OnScrolling);
				_scrollableHandler = ((Component)_slider).gameObject.AddComponent<ScrollableSliderHandler>();
				_overlayPanel.transform.Find("FSLatencyPanel/LatencyFG").localScale = Vector2.op_Implicit(Vector2.zero);
				_overlayPanel.transform.Find("FSLatencyPanel/LatencyBG").localScale = Vector2.op_Implicit(Vector2.zero);
				((Graphic)((Component)_overlayPanel.transform.Find("FSLatencyPanel/LatencyFG")).GetComponent<Image>()).color = new Color(0.1f, 0.1f, 0.1f);
				_containerRect = _overlayPanelContainer.GetComponent<RectTransform>();
				_containerRect.anchoredPosition = new Vector2(0f, -40f);
				_containerRect.sizeDelta = new Vector2(1700f, 900f);
				VerticalLayoutGroup component = _overlayPanelContainer.GetComponent<VerticalLayoutGroup>();
				((LayoutGroup)component).padding = new RectOffset(20, 20, 20, 20);
				((HorizontalOrVerticalLayoutGroup)component).spacing = 120f;
				((LayoutGroup)component).childAlignment = (TextAnchor)1;
				bool childControlHeight = (((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true);
				((HorizontalOrVerticalLayoutGroup)component).childControlHeight = childControlHeight;
				((Component)_overlayPanelContainer.transform.parent).gameObject.AddComponent<Mask>();
				GameObjectFactory.DestroyFromParent(((Component)_overlayPanelContainer.transform.parent).gameObject, "subtitle");
				GameObjectFactory.DestroyFromParent(((Component)_overlayPanelContainer.transform.parent).gameObject, "title");
				TMP_Text val3 = GameObjectFactory.CreateSingleText(_overlayPanelContainer.transform, "title", "Twitch Requests", (TextFont)0);
				val3.fontSize = 60f;
				_overlayPanel.SetActive(false);
				SetRequestRowPrefab();
				_requestList = FileManager.GetRequestsFromFile();
				_requestList.ForEach(AddRowFromFile);
				_blockedList = FileManager.GetBlockedRequestsFromFile();
				_isPanelActive = false;
				_isInitialized = true;
				isPlaying = false;
			}
		}

		public static void Update()
		{
			if (_isInitialized)
			{
				if (Input.GetKeyDown((KeyCode)289))
				{
					TogglePanel();
				}
				if (Input.GetKeyDown((KeyCode)27) && _isPanelActive)
				{
					TogglePanel();
				}
			}
		}

		private static void OnScrolling(float value)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			_containerRect.anchoredPosition = new Vector2(_containerRect.anchoredPosition.x, value * (65f * (float)_requestList.Count) - 40f);
		}

		public static void TogglePanel()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			_isPanelActive = !_isPanelActive;
			((Behaviour)_scrollableHandler).enabled = _isPanelActive && _requestRowList.Count > 6;
			_isAnimating = true;
			if (!((Object)(object)_overlayPanel != (Object)null))
			{
				return;
			}
			TootTallyAnimation panelAnimationBG = _panelAnimationBG;
			if (panelAnimationBG != null)
			{
				panelAnimationBG.Dispose();
			}
			TootTallyAnimation panelAnimationFG = _panelAnimationFG;
			if (panelAnimationFG != null)
			{
				panelAnimationFG.Dispose();
			}
			Vector2 val = (_isPanelActive ? Vector2.one : Vector2.zero);
			float num = (_isPanelActive ? 1f : 0.45f);
			SecondDegreeDynamicsAnimation val2 = (_isPanelActive ? new SecondDegreeDynamicsAnimation(1.75f, 1f, 0f) : new SecondDegreeDynamicsAnimation(3.2f, 1f, 0.25f));
			SecondDegreeDynamicsAnimation val3 = (_isPanelActive ? new SecondDegreeDynamicsAnimation(1.75f, 1f, 0f) : new SecondDegreeDynamicsAnimation(3.2f, 1f, 0.25f));
			_panelAnimationFG = TootTallyAnimationManager.AddNewScaleAnimation(((Component)_overlayPanel.transform.Find("FSLatencyPanel/LatencyFG")).gameObject, val, num, val2, (Action<GameObject>)null);
			_panelAnimationBG = TootTallyAnimationManager.AddNewScaleAnimation(((Component)_overlayPanel.transform.Find("FSLatencyPanel/LatencyBG")).gameObject, val, num, val3, (Action<GameObject>)delegate
			{
				_isAnimating = false;
				if (!_isPanelActive)
				{
					_overlayPanel.SetActive(_isPanelActive);
				}
			});
			if (_isPanelActive)
			{
				_overlayPanel.SetActive(_isPanelActive);
			}
		}

		public static void AddRow(Plugin.Request request)
		{
			_requestList.Add(request);
			UpdateSaveRequestFile();
			_requestRowList.Add(new RequestPanelRow(_overlayPanelContainer.transform, request));
			_scrollableHandler.accelerationMult = 6f / (float)_requestRowList.Count;
			((Behaviour)_scrollableHandler).enabled = _requestRowList.Count > 6;
		}

		public static void AddToBlockList(int id)
		{
			_blockedList.Add(new Plugin.BlockedRequests
			{
				song_id = id
			});
			TootTallyNotifManager.DisplayNotif($"Song #{id} blocked.", 6f);
			FileManager.SaveBlockedRequestsToFile(_blockedList);
		}

		public static void AddRowFromFile(Plugin.Request request)
		{
			_requestRowList.Add(new RequestPanelRow(_overlayPanelContainer.transform, request));
		}

		public static void Dispose()
		{
			if (_isInitialized)
			{
				Object.DestroyImmediate((Object)(object)_overlayCanvas);
				_isInitialized = false;
			}
		}

		public static void Remove(RequestPanelRow row)
		{
			_requestList.Remove(row.request);
			UpdateSaveRequestFile();
			_requestRowList.Remove(row);
			_slider.value = 0f;
		}

		public static void Remove(string trackref)
		{
			RequestPanelRow requestPanelRow = _requestRowList.Find((RequestPanelRow r) => r.request.songData.track_ref == trackref);
			if (requestPanelRow != null)
			{
				requestPanelRow.RemoveFromPanel();
				AddSongIDToHistory(requestPanelRow.request.song_id);
				TootTallyNotifManager.DisplayNotif("Fulfilled request from " + requestPanelRow.request.requester, 6f);
			}
		}

		public static void SetRequestRowPrefab()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			GameObject gameObject = ((Component)GameObjectFactory.CreateOverlayPanel(_overlayCanvas.transform, Vector2.zero, new Vector2(1200f, 84f), 5f, "TwitchRequestRowTemp").transform.Find("FSLatencyPanel")).gameObject;
			requestRowPrefab = Object.Instantiate<GameObject>(gameObject);
			Object.DestroyImmediate((Object)(object)gameObject.gameObject);
			((Object)requestRowPrefab).name = "RequestRowPrefab";
			requestRowPrefab.transform.localScale = Vector3.one;
			((MaskableGraphic)requestRowPrefab.GetComponent<Image>()).maskable = true;
			GameObject gameObject2 = ((Component)requestRowPrefab.transform.Find("LatencyFG/MainPage")).gameObject;
			gameObject2.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
			gameObject2.GetComponent<RectTransform>().sizeDelta = new Vector2(1200f, 100f);
			Object.DestroyImmediate((Object)(object)((Component)gameObject2.transform.parent.Find("subtitle")).gameObject);
			Object.DestroyImmediate((Object)(object)((Component)gameObject2.transform.parent.Find("title")).gameObject);
			Object.DestroyImmediate((Object)(object)gameObject2.GetComponent<VerticalLayoutGroup>());
			HorizontalLayoutGroup val = gameObject2.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)val).padding = new RectOffset(20, 20, 20, 20);
			((HorizontalOrVerticalLayoutGroup)val).spacing = 20f;
			((LayoutGroup)val).childAlignment = (TextAnchor)3;
			bool childControlHeight = (((HorizontalOrVerticalLayoutGroup)val).childControlWidth = false);
			((HorizontalOrVerticalLayoutGroup)val).childControlHeight = childControlHeight;
			childControlHeight = (((HorizontalOrVerticalLayoutGroup)val).childForceExpandWidth = false);
			((HorizontalOrVerticalLayoutGroup)val).childForceExpandHeight = childControlHeight;
			((MaskableGraphic)((Component)requestRowPrefab.transform.Find("LatencyFG")).GetComponent<Image>()).maskable = true;
			((MaskableGraphic)((Component)requestRowPrefab.transform.Find("LatencyBG")).GetComponent<Image>()).maskable = true;
			Object.DontDestroyOnLoad((Object)(object)requestRowPrefab);
			requestRowPrefab.SetActive(false);
		}

		public static void SetTrackToTrackref(string trackref)
		{
			if ((Object)(object)songSelectInstance == (Object)null)
			{
				return;
			}
			for (int i = 0; i < songSelectInstance.alltrackslist.Count; i++)
			{
				if (songSelectInstance.alltrackslist[i].trackref == trackref)
				{
					int num = 0;
					while (i - songIndex != 0 && songSelectInstance.songindex != i && num <= 3)
					{
						songSelectInstance.advanceSongs(i - songIndex, true);
						num++;
					}
					break;
				}
			}
		}

		public static void AddSongIDToHistory(int id)
		{
			_songIDHistory.Add(id);
		}

		public static string GetSongIDHistoryString()
		{
			return (_songIDHistory.Count > 0) ? string.Join(", ", _songIDHistory) : "No songs history recorded";
		}

		public static string GetSongQueueIDString()
		{
			return (_requestList.Count > 0) ? string.Join(", ", _requestList.Select((Plugin.Request x) => x.song_id)) : "No songs requested";
		}

		public static string GetLastSongPlayed()
		{
			return (_songIDHistory.Count > 0) ? $"https://toottally.com/song/{_songIDHistory.Last()}" : "No song played";
		}

		public static bool IsDuplicate(int song_id)
		{
			return _requestRowList.Any((RequestPanelRow x) => x.request.song_id == song_id);
		}

		public static bool IsBlocked(int song_id)
		{
			return _blockedList.Any((Plugin.BlockedRequests x) => x.song_id == song_id);
		}

		public static bool ShouldScrollSongs()
		{
			return !_isPanelActive && !_isAnimating;
		}

		public static void UpdateTheme()
		{
			if (_isInitialized)
			{
				Dispose();
				Initialize();
			}
		}

		public static void UpdateSaveRequestFile()
		{
			FileManager.SaveRequestsQueueToFile(_requestList);
		}
	}
	public class RequestPanelRow
	{
		public class TracksLoaderListener : Listener
		{
			private RequestPanelRow _row;

			public TracksLoaderListener(RequestPanelRow row)
			{
				_row = row;
			}

			public void OnTracksLoaded(FSharpList<TromboneTrack> value)
			{
				_row.PlayChart();
				_row.UnsubscribeLoaderEvent();
			}
		}

		private string _downloadLink;

		private GameObject _requestRowContainer;

		private GameObject _requestRow;

		private GameObject _downloadButton;

		private ProgressBar _progressBar;

		private TracksLoaderListener _reloadListener;

		private SongDataFromDB _chart;

		public Plugin.Request request { get; private set; }

		public RequestPanelRow(Transform canvasTransform, Plugin.Request request)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			_chart = request.songData;
			this.request = request;
			_requestRow = Object.Instantiate<GameObject>(RequestPanelManager.requestRowPrefab, canvasTransform);
			((Object)_requestRow).name = "Request" + _chart.name;
			_requestRowContainer = ((Component)_requestRow.transform.Find("LatencyFG/MainPage")).gameObject;
			((Graphic)((Component)_requestRow.transform.Find("LatencyFG")).GetComponent<Image>()).color = new Color(0.05f, 0.05f, 0.05f);
			TMP_Text val = GameObjectFactory.CreateSingleText(_requestRowContainer.transform, "SongName", _chart.name, (TextFont)0);
			TMP_Text val2 = GameObjectFactory.CreateSingleText(_requestRowContainer.transform, "Charter", _chart.charter ?? "Unknown", (TextFont)0);
			TMP_Text val3 = GameObjectFactory.CreateSingleText(_requestRowContainer.transform, "RequestedByName", request.requester, (TextFont)0);
			TMP_Text val4 = GameObjectFactory.CreateSingleText(_requestRowContainer.transform, "Time", request.date, (TextFont)0);
			((Component)val).GetComponent<RectTransform>().sizeDelta = new Vector2(250f, 64f);
			RectTransform component = ((Component)val2).GetComponent<RectTransform>();
			RectTransform component2 = ((Component)val3).GetComponent<RectTransform>();
			Vector2 sizeDelta = default(Vector2);
			((Vector2)(ref sizeDelta))..ctor(200f, 64f);
			component2.sizeDelta = sizeDelta;
			component.sizeDelta = sizeDelta;
			((Component)val4).GetComponent<RectTransform>().sizeDelta = new Vector2(150f, 64f);
			TextOverflowModes val5 = (TextOverflowModes)1;
			val4.overflowMode = (TextOverflowModes)1;
			val.overflowMode = (val2.overflowMode = (val3.overflowMode = val5));
			if (FSharpOption<TromboneTrack>[TrackLookup.tryLookup(_chart.track_ref)])
			{
				_downloadLink = FileHelper.GetDownloadLinkFromSongData(_chart);
				if (_downloadLink != null)
				{
					_downloadButton = ((Component)GameObjectFactory.CreateCustomButton(_requestRowContainer.transform, Vector2.zero, new Vector2(68f, 68f), AssetManager.GetSprite("Download64.png"), "DownloadButton", (Action)DownloadChart)).gameObject;
					_progressBar = GameObjectFactory.CreateProgressBar(_requestRow.transform.Find("LatencyFG"), Vector2.zero, new Vector2(900f, 20f), false, "ProgressBar");
				}
				else
				{
					_downloadButton = ((Component)GameObjectFactory.CreateCustomButton(_requestRowContainer.transform, Vector2.zero, new Vector2(68f, 68f), AssetManager.GetSprite("global64.png"), "OpenLeaderboardButton", (Action)delegate
					{
						Application.OpenURL($"https://toottally.com/song/{request.songData.id}/");
					})).gameObject;
				}
			}
			else
			{
				GameObjectFactory.CreateCustomButton(_requestRowContainer.transform, Vector2.zero, new Vector2(68f, 68f), AssetManager.GetSprite("Check64.png"), "PlayButton", (Action)PlayChart);
			}
			GameObjectFactory.CreateCustomButton(_requestRowContainer.transform, Vector2.zero, new Vector2(68f, 68f), AssetManager.GetSprite("Close64.png"), "SkipButton", (Action)RemoveFromPanel);
			GameObjectFactory.CreateCustomButton(_requestRowContainer.transform, Vector2.zero, new Vector2(68f, 68f), AssetManager.GetSprite("Block64.png"), "BlockButton", (Action)BlockChart);
			_requestRow.SetActive(true);
		}

		public void PlayChart()
		{
			RequestPanelManager.currentSongID = request.song_id;
			RequestPanelManager.SetTrackToTrackref(_chart.track_ref);
		}

		public void DownloadChart()
		{
			_downloadButton.SetActive(false);
			((MonoBehaviour)Plugin.Instance).StartCoroutine((IEnumerator)TootTallyAPIService.DownloadZipFromServer(_downloadLink, _progressBar, (Action<byte[]>)delegate(byte[] data)
			{
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				if (data != null)
				{
					string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location), "Downloads/");
					if (!Directory.Exists(text))
					{
						Directory.CreateDirectory(text);
					}
					string text2 = $"{_chart.id}.zip";
					FileHelper.WriteBytesToFile(text, text2, data);
					string text3 = Path.Combine(text, text2);
					string text4 = Path.Combine(Paths.BepInExRootPath, "CustomSongs/");
					FileHelper.ExtractZipToDirectory(text3, text4);
					FileHelper.DeleteFile(text, text2);
					_reloadListener = new TracksLoaderListener(this);
					TracksLoadedEvent.EVENT.Register((Listener)(object)_reloadListener);
					TootTallyNotifManager.DisplayNotif("Reloading Songs...", 6f);
					((MonoBehaviour)Plugin.Instance).Invoke("ReloadTracks", 0.5f);
					CustomButton val = GameObjectFactory.CreateCustomButton(_requestRowContainer.transform, Vector2.zero, new Vector2(68f, 68f), AssetManager.GetSprite("Check64.png"), "PlayButton", (Action)PlayChart);
					((Component)val).transform.SetSiblingIndex(4);
				}
				else
				{
					TootTallyNotifManager.DisplayNotif("Download not available.", 6f);
					_downloadButton.SetActive(true);
				}
			}));
		}

		public void UnsubscribeLoaderEvent()
		{
			if (_reloadListener != null)
			{
				TracksLoadedEvent.EVENT.Unregister((Listener)(object)_reloadListener);
			}
			_reloadListener = null;
		}

		public void RemoveFromPanel()
		{
			RequestPanelManager.Remove(this);
			Object.DestroyImmediate((Object)(object)_requestRow);
		}

		public void BlockChart()
		{
			RequestPanelManager.AddToBlockList(_chart.id);
			RemoveFromPanel();
		}
	}
	public class TwitchBot
	{
		internal TwitchClient client;

		public string CHANNEL { get; set; }

		public Stack<string> MessageStack { get; set; }

		public TwitchBot()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_0091: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			if (Initialize())
			{
				Plugin.LogInfo("Attempting connection with channel " + CHANNEL + "...");
				ConnectionCredentials val = new ConnectionCredentials(CHANNEL, Plugin.Instance.TwitchAccessToken.Value, "wss://irc-ws.chat.twitch.tv:443", false, (Capabilities)null);
				ClientOptions val2 = new ClientOptions
				{
					MessagesAllowedInPeriod = 750,
					ThrottlingPeriod = TimeSpan.FromSeconds(30.0),
					ReconnectionPolicy = new ReconnectionPolicy(5, (int?)3)
				};
				WebSocketClient val3 = new WebSocketClient((IClientOptions)(object)val2);
				client = new TwitchClient((IClient)(object)val3, (ClientProtocol)1, (ILogger<TwitchClient>)null);
				client.Initialize(val, CHANNEL, '!', '!', true);
				client.OnLog += Client_OnLog;
				client.OnJoinedChannel += Client_OnJoinedChannel;
				client.OnConnected += Client_OnConnected;
				client.OnChatCommandReceived += Client_HandleChatCommand;
				client.OnIncorrectLogin += Client_OnIncorrectLogin;
				client.OnError += Client_OnError;
				MessageStack = new Stack<string>();
				client.Connect();
			}
		}

		public void Disconnect()
		{
			if (client != null && client.IsConnected)
			{
				client.Disconnect();
			}
			MessageStack?.Clear();
			MessageStack = null;
		}

		private bool Initialize()
		{
			if (Plugin.Instance.TwitchAccessToken.Value == null || Plugin.Instance.TwitchAccessToken.Value == "")
			{
				TootTallyNotifManager.DisplayError("Twitch Access Token is empty. Please fill it in.", 6f);
				return false;
			}
			if (Plugin.Instance.TwitchUsername.Value == null || Plugin.Instance.TwitchUsername.Value == "")
			{
				TootTallyNotifManager.DisplayError("Twitch Username is empty. Please fill it in.", 6f);
				return false;
			}
			CHANNEL = Plugin.Instance.TwitchUsername.Value.ToLower();
			return true;
		}

		private void Client_OnError(object sender, OnErrorEventArgs args)
		{
			Plugin.LogError($"{args.Exception}\n{args.Exception.StackTrace}");
		}

		private void Client_OnIncorrectLogin(object sender, OnIncorrectLoginArgs args)
		{
			TootTallyNotifManager.DisplayError("Login credentials incorrect. Please re-authorize or refresh your access token, and re-check your Twitch username.", 6f);
			client.Disconnect();
		}

		private void Client_HandleChatCommand(object sender, OnChatCommandReceivedArgs args)
		{
			string commandText = args.Command.CommandText;
			string argumentsAsString = args.Command.ArgumentsAsString;
			switch (commandText)
			{
			case "ttr":
				if (!Plugin.Instance.EnableRequestsCommand.Value)
				{
					break;
				}
				if (args.Command.ArgumentsAsList.Count == 1)
				{
					if (int.TryParse(argumentsAsString, out var result))
					{
						Plugin.LogInfo($"Successfully parsed request for {result}, submitting to stack.");
						Plugin.Instance.requestController.RequestSong(result, ((TwitchLibMessage)args.Command.ChatMessage).Username, args.Command.ChatMessage.IsSubscriber);
					}
					else
					{
						Plugin.LogInfo("Could not parse request input, ignoring.");
						client.SendMessage(CHANNEL, "!Invalid song ID. Please try again.", false);
					}
				}
				else
				{
					client.SendMessage(CHANNEL, "!Use !ttr to request a chart use its TootTally Song ID! To get a song ID, search for the song in https://toottally.com (Example: !ttr 3781)", false);
				}
				break;
			case "profile":
				if (Plugin.Instance.EnableProfileCommand.Value && TootTallyUser.userInfo.id > 0)
				{
					client.SendMessage(CHANNEL, $"!TootTally Profile: https://toottally.com/profile/{TootTallyUser.userInfo.id}", false);
				}
				break;
			case "song":
				if (Plugin.Instance.EnableCurrentSongCommand.Value && RequestPanelManager.currentSongID != 0)
				{
					client.SendMessage(CHANNEL, $"!Current Song: https://toottally.com/song/{RequestPanelManager.currentSongID}", false);
				}
				break;
			case "ttrhelp":
				if (Plugin.Instance.EnableCurrentSongCommand.Value)
				{
					client.SendMessage(CHANNEL, "!Use !ttr to request a chart use its TootTally Song ID! To get a song ID, search for the song in https://toottally.com (Example: !ttr 3781)", false);
				}
				break;
			case "queue":
				if (Plugin.Instance.EnableCurrentSongCommand.Value)
				{
					client.SendMessage(CHANNEL, "!Song Queue: " + RequestPanelManager.GetSongQueueIDString(), false);
				}
				break;
			case "last":
				if (Plugin.Instance.EnableCurrentSongCommand.Value)
				{
					client.SendMessage(CHANNEL, "!Last song played: " + RequestPanelManager.GetLastSongPlayed(), false);
				}
				break;
			case "history":
				if (Plugin.Instance.EnableCurrentSongCommand.Value)
				{
					client.SendMessage(CHANNEL, "!Songs played: " + RequestPanelManager.GetSongIDHistoryString(), false);
				}
				break;
			}
		}

		private void Client_OnLog(object sender, OnLogArgs e)
		{
			Plugin.LogDebug($"{e.DateTime}: {e.BotUsername} - {e.Data}");
		}

		private void Client_OnConnected(object sender, OnConnectedArgs e)
		{
			Plugin.LogInfo("Connected to " + e.AutoJoinChannel);
		}

		private void Client_OnJoinedChannel(object sender, OnJoinedChannelArgs e)
		{
			client.SendMessage(e.Channel, "! TootTally Twitch Integration ready!", false);
			TootTallyNotifManager.DisplayNotif("Twitch Integration successful!", 6f);
			Plugin.LogInfo("Twitch integration successfully attached to chat!");
			CHANNEL = e.Channel;
		}

		private void Client_OnDisconnected(object sender, OnDisconnectedArgs e)
		{
			Plugin.LogInfo("TwitchBot successfully disconnected from Twitch!");
			TootTallyNotifManager.DisplayNotif("Twitch bot disconnected!", 6f);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "TootTallyTwitchIntegration";

		public const string PLUGIN_NAME = "TootTallyTwitchIntegration";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}

plugins/TwitchLib/Microsoft.Extensions.DependencyInjection.Abstractions.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using FxResources.Microsoft.Extensions.DependencyInjection.Abstractions;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Internal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyInjection.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyDefaultAlias("Microsoft.Extensions.DependencyInjection.Abstractions")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Abstractions for dependency injection.\r\n\r\nCommonly Used Types:\r\nMicrosoft.Extensions.DependencyInjection.IServiceCollection")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.DependencyInjection.Abstractions")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: AssemblyVersion("6.0.0.0")]
[module: System.Runtime.CompilerServices.NullablePublicOnly(true)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 NullablePublicOnlyAttribute : Attribute
	{
		public readonly bool IncludesInternals;

		public NullablePublicOnlyAttribute(bool P_0)
		{
			IncludesInternals = P_0;
		}
	}
}
namespace FxResources.Microsoft.Extensions.DependencyInjection.Abstractions
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string AmbiguousConstructorMatch => GetResourceString("AmbiguousConstructorMatch");

		internal static string CannotLocateImplementation => GetResourceString("CannotLocateImplementation");

		internal static string CannotResolveService => GetResourceString("CannotResolveService");

		internal static string NoConstructorMatch => GetResourceString("NoConstructorMatch");

		internal static string NoServiceRegistered => GetResourceString("NoServiceRegistered");

		internal static string TryAddIndistinguishableTypeToEnumerable => GetResourceString("TryAddIndistinguishableTypeToEnumerable");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
	internal sealed class DynamicallyAccessedMembersAttribute : Attribute
	{
		public DynamicallyAccessedMemberTypes MemberTypes { get; }

		public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
		{
			MemberTypes = memberTypes;
		}
	}
	[Flags]
	internal enum DynamicallyAccessedMemberTypes
	{
		None = 0,
		PublicParameterlessConstructor = 1,
		PublicConstructors = 3,
		NonPublicConstructors = 4,
		PublicMethods = 8,
		NonPublicMethods = 0x10,
		PublicFields = 0x20,
		NonPublicFields = 0x40,
		PublicNestedTypes = 0x80,
		NonPublicNestedTypes = 0x100,
		PublicProperties = 0x200,
		NonPublicProperties = 0x400,
		PublicEvents = 0x800,
		NonPublicEvents = 0x1000,
		Interfaces = 0x2000,
		All = -1
	}
	[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
	internal sealed class UnconditionalSuppressMessageAttribute : Attribute
	{
		public string Category { get; }

		public string CheckId { get; }

		public string? Scope { get; set; }

		public string? Target { get; set; }

		public string? MessageId { get; set; }

		public string? Justification { get; set; }

		public UnconditionalSuppressMessageAttribute(string category, string checkId)
		{
			Category = category;
			CheckId = checkId;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class AllowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class DisallowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class MaybeNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class NotNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class MaybeNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public MaybeNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class NotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public NotNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
	internal sealed class NotNullIfNotNullAttribute : Attribute
	{
		public string ParameterName { get; }

		public NotNullIfNotNullAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	internal sealed class DoesNotReturnAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class DoesNotReturnIfAttribute : Attribute
	{
		public bool ParameterValue { get; }

		public DoesNotReturnIfAttribute(bool parameterValue)
		{
			ParameterValue = parameterValue;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
}
namespace Microsoft.Extensions.Internal
{
	internal static class ParameterDefaultValue
	{
		public static bool TryGetDefaultValue(ParameterInfo parameter, out object? defaultValue)
		{
			bool tryToGetDefaultValue;
			bool flag = CheckHasDefaultValue(parameter, out tryToGetDefaultValue);
			defaultValue = null;
			if (flag)
			{
				if (tryToGetDefaultValue)
				{
					defaultValue = parameter.DefaultValue;
				}
				bool flag2 = parameter.ParameterType.IsGenericType && parameter.ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>);
				if (defaultValue == null && parameter.ParameterType.IsValueType && !flag2)
				{
					defaultValue = CreateValueType(parameter.ParameterType);
				}
				if (defaultValue != null && flag2)
				{
					Type underlyingType = Nullable.GetUnderlyingType(parameter.ParameterType);
					if (underlyingType != null && underlyingType.IsEnum)
					{
						defaultValue = Enum.ToObject(underlyingType, defaultValue);
					}
				}
			}
			return flag;
			[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", Justification = "CreateValueType is only called on a ValueType. You can always create an instance of a ValueType.")]
			static object? CreateValueType(Type t)
			{
				return FormatterServices.GetUninitializedObject(t);
			}
		}

		public static bool CheckHasDefaultValue(ParameterInfo parameter, out bool tryToGetDefaultValue)
		{
			tryToGetDefaultValue = true;
			try
			{
				return parameter.HasDefaultValue;
			}
			catch (FormatException) when (parameter.ParameterType == typeof(DateTime))
			{
				tryToGetDefaultValue = false;
				return true;
			}
		}
	}
}
namespace Microsoft.Extensions.DependencyInjection
{
	public static class ActivatorUtilities
	{
		private struct ConstructorMatcher
		{
			private readonly ConstructorInfo _constructor;

			private readonly ParameterInfo[] _parameters;

			private readonly object[] _parameterValues;

			public ConstructorMatcher(ConstructorInfo constructor)
			{
				_constructor = constructor;
				_parameters = _constructor.GetParameters();
				_parameterValues = new object[_parameters.Length];
			}

			public int Match(object[] givenParameters)
			{
				int num = 0;
				int result = 0;
				for (int i = 0; i != givenParameters.Length; i++)
				{
					Type c = givenParameters[i]?.GetType();
					bool flag = false;
					int num2 = num;
					while (!flag && num2 != _parameters.Length)
					{
						if (_parameterValues[num2] == null && _parameters[num2].ParameterType.IsAssignableFrom(c))
						{
							flag = true;
							_parameterValues[num2] = givenParameters[i];
							if (num == num2)
							{
								num++;
								if (num2 == i)
								{
									result = num2;
								}
							}
						}
						num2++;
					}
					if (!flag)
					{
						return -1;
					}
				}
				return result;
			}

			public object CreateInstance(IServiceProvider provider)
			{
				for (int i = 0; i != _parameters.Length; i++)
				{
					if (_parameterValues[i] != null)
					{
						continue;
					}
					object service = provider.GetService(_parameters[i].ParameterType);
					if (service == null)
					{
						if (!ParameterDefaultValue.TryGetDefaultValue(_parameters[i], out object defaultValue))
						{
							throw new InvalidOperationException($"Unable to resolve service for type '{_parameters[i].ParameterType}' while attempting to activate '{_constructor.DeclaringType}'.");
						}
						_parameterValues[i] = defaultValue;
					}
					else
					{
						_parameterValues[i] = service;
					}
				}
				try
				{
					return _constructor.Invoke(_parameterValues);
				}
				catch (TargetInvocationException ex) when (ex.InnerException != null)
				{
					ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
					throw;
				}
			}
		}

		private static readonly MethodInfo GetServiceInfo = GetMethodInfo<Func<IServiceProvider, Type, Type, bool, object>>((IServiceProvider sp, Type t, Type r, bool c) => GetService(sp, t, r, c));

		public static object CreateInstance(IServiceProvider provider, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, params object[] parameters)
		{
			int num = -1;
			bool flag = false;
			ConstructorMatcher constructorMatcher = default(ConstructorMatcher);
			if (!instanceType.IsAbstract)
			{
				ConstructorInfo[] constructors = instanceType.GetConstructors();
				foreach (ConstructorInfo constructorInfo in constructors)
				{
					ConstructorMatcher constructorMatcher2 = new ConstructorMatcher(constructorInfo);
					bool flag2 = constructorInfo.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), inherit: false);
					int num2 = constructorMatcher2.Match(parameters);
					if (flag2)
					{
						if (flag)
						{
							ThrowMultipleCtorsMarkedWithAttributeException();
						}
						if (num2 == -1)
						{
							ThrowMarkedCtorDoesNotTakeAllProvidedArguments();
						}
					}
					if (flag2 || num < num2)
					{
						num = num2;
						constructorMatcher = constructorMatcher2;
					}
					flag = flag || flag2;
				}
			}
			if (num == -1)
			{
				string message = $"A suitable constructor for type '{instanceType}' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.";
				throw new InvalidOperationException(message);
			}
			return constructorMatcher.CreateInstance(provider);
		}

		public static ObjectFactory CreateFactory([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, Type[] argumentTypes)
		{
			FindApplicableConstructor(instanceType, argumentTypes, out var matchingConstructor, out var matchingParameterMap);
			ParameterExpression parameterExpression = Expression.Parameter(typeof(IServiceProvider), "provider");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object[]), "argumentArray");
			Expression body = BuildFactoryExpression(matchingConstructor, matchingParameterMap, parameterExpression, parameterExpression2);
			Expression<Func<IServiceProvider, object[], object>> expression = Expression.Lambda<Func<IServiceProvider, object[], object>>(body, new ParameterExpression[2] { parameterExpression, parameterExpression2 });
			Func<IServiceProvider, object[], object> @object = expression.Compile();
			return @object.Invoke;
		}

		public static T CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(IServiceProvider provider, params object[] parameters)
		{
			return (T)CreateInstance(provider, typeof(T), parameters);
		}

		public static T GetServiceOrCreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(IServiceProvider provider)
		{
			return (T)GetServiceOrCreateInstance(provider, typeof(T));
		}

		public static object GetServiceOrCreateInstance(IServiceProvider provider, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type)
		{
			return provider.GetService(type) ?? CreateInstance(provider, type);
		}

		private static MethodInfo GetMethodInfo<T>(Expression<T> expr)
		{
			MethodCallExpression methodCallExpression = (MethodCallExpression)expr.Body;
			return methodCallExpression.Method;
		}

		private static object GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)
		{
			object service = sp.GetService(type);
			if (service == null && !isDefaultParameterRequired)
			{
				string message = $"Unable to resolve service for type '{type}' while attempting to activate '{requiredBy}'.";
				throw new InvalidOperationException(message);
			}
			return service;
		}

		private static Expression BuildFactoryExpression(ConstructorInfo constructor, int?[] parameterMap, Expression serviceProvider, Expression factoryArgumentArray)
		{
			ParameterInfo[] parameters = constructor.GetParameters();
			Expression[] array = new Expression[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				ParameterInfo parameterInfo = parameters[i];
				Type parameterType = parameterInfo.ParameterType;
				object defaultValue;
				bool flag = ParameterDefaultValue.TryGetDefaultValue(parameterInfo, out defaultValue);
				if (parameterMap[i].HasValue)
				{
					array[i] = Expression.ArrayAccess(factoryArgumentArray, Expression.Constant(parameterMap[i]));
				}
				else
				{
					Expression[] arguments = new Expression[4]
					{
						serviceProvider,
						Expression.Constant(parameterType, typeof(Type)),
						Expression.Constant(constructor.DeclaringType, typeof(Type)),
						Expression.Constant(flag)
					};
					array[i] = Expression.Call(GetServiceInfo, arguments);
				}
				if (flag)
				{
					ConstantExpression right = Expression.Constant(defaultValue);
					array[i] = Expression.Coalesce(array[i], right);
				}
				array[i] = Expression.Convert(array[i], parameterType);
			}
			return Expression.New(constructor, array);
		}

		private static void FindApplicableConstructor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, Type[] argumentTypes, out ConstructorInfo matchingConstructor, out int?[] matchingParameterMap)
		{
			ConstructorInfo matchingConstructor2 = null;
			int?[] parameterMap = null;
			if (!TryFindPreferredConstructor(instanceType, argumentTypes, ref matchingConstructor2, ref parameterMap) && !TryFindMatchingConstructor(instanceType, argumentTypes, ref matchingConstructor2, ref parameterMap))
			{
				string message = $"A suitable constructor for type '{instanceType}' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.";
				throw new InvalidOperationException(message);
			}
			matchingConstructor = matchingConstructor2;
			matchingParameterMap = parameterMap;
		}

		private static bool TryFindMatchingConstructor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, Type[] argumentTypes, [NotNullWhen(true)] ref ConstructorInfo matchingConstructor, [NotNullWhen(true)] ref int?[] parameterMap)
		{
			ConstructorInfo[] constructors = instanceType.GetConstructors();
			foreach (ConstructorInfo constructorInfo in constructors)
			{
				if (TryCreateParameterMap(constructorInfo.GetParameters(), argumentTypes, out var parameterMap2))
				{
					if (matchingConstructor != null)
					{
						throw new InvalidOperationException($"Multiple constructors accepting all given argument types have been found in type '{instanceType}'. There should only be one applicable constructor.");
					}
					matchingConstructor = constructorInfo;
					parameterMap = parameterMap2;
				}
			}
			if (matchingConstructor != null)
			{
				return true;
			}
			return false;
		}

		private static bool TryFindPreferredConstructor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType, Type[] argumentTypes, [NotNullWhen(true)] ref ConstructorInfo matchingConstructor, [NotNullWhen(true)] ref int?[] parameterMap)
		{
			bool flag = false;
			ConstructorInfo[] constructors = instanceType.GetConstructors();
			foreach (ConstructorInfo constructorInfo in constructors)
			{
				if (constructorInfo.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), inherit: false))
				{
					if (flag)
					{
						ThrowMultipleCtorsMarkedWithAttributeException();
					}
					if (!TryCreateParameterMap(constructorInfo.GetParameters(), argumentTypes, out var parameterMap2))
					{
						ThrowMarkedCtorDoesNotTakeAllProvidedArguments();
					}
					matchingConstructor = constructorInfo;
					parameterMap = parameterMap2;
					flag = true;
				}
			}
			if (matchingConstructor != null)
			{
				return true;
			}
			return false;
		}

		private static bool TryCreateParameterMap(ParameterInfo[] constructorParameters, Type[] argumentTypes, out int?[] parameterMap)
		{
			parameterMap = new int?[constructorParameters.Length];
			for (int i = 0; i < argumentTypes.Length; i++)
			{
				bool flag = false;
				Type c = argumentTypes[i];
				for (int j = 0; j < constructorParameters.Length; j++)
				{
					if (!parameterMap[j].HasValue && constructorParameters[j].ParameterType.IsAssignableFrom(c))
					{
						flag = true;
						parameterMap[j] = i;
						break;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			return true;
		}

		private static void ThrowMultipleCtorsMarkedWithAttributeException()
		{
			throw new InvalidOperationException("Multiple constructors were marked with ActivatorUtilitiesConstructorAttribute.");
		}

		private static void ThrowMarkedCtorDoesNotTakeAllProvidedArguments()
		{
			throw new InvalidOperationException("Constructor marked with ActivatorUtilitiesConstructorAttribute does not accept all given argument types.");
		}
	}
	[AttributeUsage(AttributeTargets.All)]
	public class ActivatorUtilitiesConstructorAttribute : Attribute
	{
	}
	public readonly struct AsyncServiceScope : IServiceScope, IDisposable, IAsyncDisposable
	{
		private readonly IServiceScope _serviceScope;

		public IServiceProvider ServiceProvider => _serviceScope.ServiceProvider;

		public AsyncServiceScope(IServiceScope serviceScope)
		{
			_serviceScope = serviceScope ?? throw new ArgumentNullException("serviceScope");
		}

		public void Dispose()
		{
			_serviceScope.Dispose();
		}

		public ValueTask DisposeAsync()
		{
			if (_serviceScope is IAsyncDisposable asyncDisposable)
			{
				return asyncDisposable.DisposeAsync();
			}
			_serviceScope.Dispose();
			return default(ValueTask);
		}
	}
	public interface IServiceCollection : IList<ServiceDescriptor>, ICollection<ServiceDescriptor>, IEnumerable<ServiceDescriptor>, IEnumerable
	{
	}
	public interface IServiceProviderFactory<TContainerBuilder> where TContainerBuilder : notnull
	{
		TContainerBuilder CreateBuilder(IServiceCollection services);

		IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder);
	}
	public interface IServiceProviderIsService
	{
		bool IsService(Type serviceType);
	}
	public interface IServiceScope : IDisposable
	{
		IServiceProvider ServiceProvider { get; }
	}
	public interface IServiceScopeFactory
	{
		IServiceScope CreateScope();
	}
	public interface ISupportRequiredService
	{
		object GetRequiredService(Type serviceType);
	}
	public delegate object ObjectFactory(IServiceProvider serviceProvider, object?[]? arguments);
	public class ServiceCollection : IServiceCollection, IList<ServiceDescriptor>, ICollection<ServiceDescriptor>, IEnumerable<ServiceDescriptor>, IEnumerable
	{
		private readonly List<ServiceDescriptor> _descriptors = new List<ServiceDescriptor>();

		public int Count => _descriptors.Count;

		public bool IsReadOnly => false;

		public ServiceDescriptor this[int index]
		{
			get
			{
				return _descriptors[index];
			}
			set
			{
				_descriptors[index] = value;
			}
		}

		public void Clear()
		{
			_descriptors.Clear();
		}

		public bool Contains(ServiceDescriptor item)
		{
			return _descriptors.Contains(item);
		}

		public void CopyTo(ServiceDescriptor[] array, int arrayIndex)
		{
			_descriptors.CopyTo(array, arrayIndex);
		}

		public bool Remove(ServiceDescriptor item)
		{
			return _descriptors.Remove(item);
		}

		public IEnumerator<ServiceDescriptor> GetEnumerator()
		{
			return _descriptors.GetEnumerator();
		}

		void ICollection<ServiceDescriptor>.Add(ServiceDescriptor item)
		{
			_descriptors.Add(item);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public int IndexOf(ServiceDescriptor item)
		{
			return _descriptors.IndexOf(item);
		}

		public void Insert(int index, ServiceDescriptor item)
		{
			_descriptors.Insert(index, item);
		}

		public void RemoveAt(int index)
		{
			_descriptors.RemoveAt(index);
		}
	}
	public static class ServiceCollectionServiceExtensions
	{
		public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			return Add(services, serviceType, implementationType, ServiceLifetime.Transient);
		}

		public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Add(services, serviceType, implementationFactory, ServiceLifetime.Transient);
		}

		public static IServiceCollection AddTransient<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			return services.AddTransient(typeof(TService), typeof(TImplementation));
		}

		public static IServiceCollection AddTransient(this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			return services.AddTransient(serviceType, serviceType);
		}

		public static IServiceCollection AddTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection services) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			return services.AddTransient(typeof(TService));
		}

		public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return services.AddTransient(typeof(TService), implementationFactory);
		}

		public static IServiceCollection AddTransient<TService, TImplementation>(this IServiceCollection services, Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return services.AddTransient(typeof(TService), implementationFactory);
		}

		public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			return Add(services, serviceType, implementationType, ServiceLifetime.Scoped);
		}

		public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Add(services, serviceType, implementationFactory, ServiceLifetime.Scoped);
		}

		public static IServiceCollection AddScoped<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			return services.AddScoped(typeof(TService), typeof(TImplementation));
		}

		public static IServiceCollection AddScoped(this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			return services.AddScoped(serviceType, serviceType);
		}

		public static IServiceCollection AddScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection services) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			return services.AddScoped(typeof(TService));
		}

		public static IServiceCollection AddScoped<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return services.AddScoped(typeof(TService), implementationFactory);
		}

		public static IServiceCollection AddScoped<TService, TImplementation>(this IServiceCollection services, Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return services.AddScoped(typeof(TService), implementationFactory);
		}

		public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			return Add(services, serviceType, implementationType, ServiceLifetime.Singleton);
		}

		public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Add(services, serviceType, implementationFactory, ServiceLifetime.Singleton);
		}

		public static IServiceCollection AddSingleton<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			return services.AddSingleton(typeof(TService), typeof(TImplementation));
		}

		public static IServiceCollection AddSingleton(this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			return services.AddSingleton(serviceType, serviceType);
		}

		public static IServiceCollection AddSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection services) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			return services.AddSingleton(typeof(TService));
		}

		public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return services.AddSingleton(typeof(TService), implementationFactory);
		}

		public static IServiceCollection AddSingleton<TService, TImplementation>(this IServiceCollection services, Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return services.AddSingleton(typeof(TService), implementationFactory);
		}

		public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, object implementationInstance)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationInstance == null)
			{
				throw new ArgumentNullException("implementationInstance");
			}
			ServiceDescriptor item = new ServiceDescriptor(serviceType, implementationInstance);
			services.Add(item);
			return services;
		}

		public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, TService implementationInstance) where TService : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (implementationInstance == null)
			{
				throw new ArgumentNullException("implementationInstance");
			}
			return services.AddSingleton(typeof(TService), implementationInstance);
		}

		private static IServiceCollection Add(IServiceCollection collection, Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime)
		{
			ServiceDescriptor item = new ServiceDescriptor(serviceType, implementationType, lifetime);
			collection.Add(item);
			return collection;
		}

		private static IServiceCollection Add(IServiceCollection collection, Type serviceType, Func<IServiceProvider, object> implementationFactory, ServiceLifetime lifetime)
		{
			ServiceDescriptor item = new ServiceDescriptor(serviceType, implementationFactory, lifetime);
			collection.Add(item);
			return collection;
		}
	}
	[DebuggerDisplay("Lifetime = {Lifetime}, ServiceType = {ServiceType}, ImplementationType = {ImplementationType}")]
	public class ServiceDescriptor
	{
		public ServiceLifetime Lifetime { get; }

		public Type ServiceType { get; }

		[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
		public Type? ImplementationType { get; }

		public object? ImplementationInstance { get; }

		public Func<IServiceProvider, object>? ImplementationFactory { get; }

		public ServiceDescriptor(Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime)
			: this(serviceType, lifetime)
		{
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			ImplementationType = implementationType;
		}

		public ServiceDescriptor(Type serviceType, object instance)
			: this(serviceType, ServiceLifetime.Singleton)
		{
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			ImplementationInstance = instance;
		}

		public ServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime)
			: this(serviceType, lifetime)
		{
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (factory == null)
			{
				throw new ArgumentNullException("factory");
			}
			ImplementationFactory = factory;
		}

		private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime)
		{
			Lifetime = lifetime;
			ServiceType = serviceType;
		}

		public override string ToString()
		{
			string text = string.Format("{0}: {1} {2}: {3} ", "ServiceType", ServiceType, "Lifetime", Lifetime);
			if (ImplementationType != null)
			{
				return text + string.Format("{0}: {1}", "ImplementationType", ImplementationType);
			}
			if (ImplementationFactory != null)
			{
				return text + string.Format("{0}: {1}", "ImplementationFactory", ImplementationFactory.Method);
			}
			return text + string.Format("{0}: {1}", "ImplementationInstance", ImplementationInstance);
		}

		internal Type GetImplementationType()
		{
			if (ImplementationType != null)
			{
				return ImplementationType;
			}
			if (ImplementationInstance != null)
			{
				return ImplementationInstance.GetType();
			}
			if (ImplementationFactory != null)
			{
				Type[] genericTypeArguments = ImplementationFactory.GetType().GenericTypeArguments;
				return genericTypeArguments[1];
			}
			return null;
		}

		public static ServiceDescriptor Transient<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>() where TService : class where TImplementation : class, TService
		{
			return Describe<TService, TImplementation>(ServiceLifetime.Transient);
		}

		public static ServiceDescriptor Transient(Type service, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			return Describe(service, implementationType, ServiceLifetime.Transient);
		}

		public static ServiceDescriptor Transient<TService, TImplementation>(Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
		{
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(typeof(TService), implementationFactory, ServiceLifetime.Transient);
		}

		public static ServiceDescriptor Transient<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(typeof(TService), implementationFactory, ServiceLifetime.Transient);
		}

		public static ServiceDescriptor Transient(Type service, Func<IServiceProvider, object> implementationFactory)
		{
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(service, implementationFactory, ServiceLifetime.Transient);
		}

		public static ServiceDescriptor Scoped<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>() where TService : class where TImplementation : class, TService
		{
			return Describe<TService, TImplementation>(ServiceLifetime.Scoped);
		}

		public static ServiceDescriptor Scoped(Type service, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			return Describe(service, implementationType, ServiceLifetime.Scoped);
		}

		public static ServiceDescriptor Scoped<TService, TImplementation>(Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
		{
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(typeof(TService), implementationFactory, ServiceLifetime.Scoped);
		}

		public static ServiceDescriptor Scoped<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(typeof(TService), implementationFactory, ServiceLifetime.Scoped);
		}

		public static ServiceDescriptor Scoped(Type service, Func<IServiceProvider, object> implementationFactory)
		{
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(service, implementationFactory, ServiceLifetime.Scoped);
		}

		public static ServiceDescriptor Singleton<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>() where TService : class where TImplementation : class, TService
		{
			return Describe<TService, TImplementation>(ServiceLifetime.Singleton);
		}

		public static ServiceDescriptor Singleton(Type service, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			return Describe(service, implementationType, ServiceLifetime.Singleton);
		}

		public static ServiceDescriptor Singleton<TService, TImplementation>(Func<IServiceProvider, TImplementation> implementationFactory) where TService : class where TImplementation : class, TService
		{
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(typeof(TService), implementationFactory, ServiceLifetime.Singleton);
		}

		public static ServiceDescriptor Singleton<TService>(Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(typeof(TService), implementationFactory, ServiceLifetime.Singleton);
		}

		public static ServiceDescriptor Singleton(Type serviceType, Func<IServiceProvider, object> implementationFactory)
		{
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			return Describe(serviceType, implementationFactory, ServiceLifetime.Singleton);
		}

		public static ServiceDescriptor Singleton<TService>(TService implementationInstance) where TService : class
		{
			if (implementationInstance == null)
			{
				throw new ArgumentNullException("implementationInstance");
			}
			return Singleton(typeof(TService), implementationInstance);
		}

		public static ServiceDescriptor Singleton(Type serviceType, object implementationInstance)
		{
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (implementationInstance == null)
			{
				throw new ArgumentNullException("implementationInstance");
			}
			return new ServiceDescriptor(serviceType, implementationInstance);
		}

		private static ServiceDescriptor Describe<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(ServiceLifetime lifetime) where TService : class where TImplementation : class, TService
		{
			return Describe(typeof(TService), typeof(TImplementation), lifetime);
		}

		public static ServiceDescriptor Describe(Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime)
		{
			return new ServiceDescriptor(serviceType, implementationType, lifetime);
		}

		public static ServiceDescriptor Describe(Type serviceType, Func<IServiceProvider, object> implementationFactory, ServiceLifetime lifetime)
		{
			return new ServiceDescriptor(serviceType, implementationFactory, lifetime);
		}
	}
	public enum ServiceLifetime
	{
		Singleton,
		Scoped,
		Transient
	}
	public static class ServiceProviderServiceExtensions
	{
		public static T? GetService<T>(this IServiceProvider provider)
		{
			if (provider == null)
			{
				throw new ArgumentNullException("provider");
			}
			return (T)provider.GetService(typeof(T));
		}

		public static object GetRequiredService(this IServiceProvider provider, Type serviceType)
		{
			if (provider == null)
			{
				throw new ArgumentNullException("provider");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (provider is ISupportRequiredService supportRequiredService)
			{
				return supportRequiredService.GetRequiredService(serviceType);
			}
			object service = provider.GetService(serviceType);
			if (service == null)
			{
				throw new InvalidOperationException(System.SR.Format(System.SR.NoServiceRegistered, serviceType));
			}
			return service;
		}

		public static T GetRequiredService<T>(this IServiceProvider provider) where T : notnull
		{
			if (provider == null)
			{
				throw new ArgumentNullException("provider");
			}
			return (T)provider.GetRequiredService(typeof(T));
		}

		public static IEnumerable<T> GetServices<T>(this IServiceProvider provider)
		{
			if (provider == null)
			{
				throw new ArgumentNullException("provider");
			}
			return provider.GetRequiredService<IEnumerable<T>>();
		}

		public static IEnumerable<object?> GetServices(this IServiceProvider provider, Type serviceType)
		{
			if (provider == null)
			{
				throw new ArgumentNullException("provider");
			}
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			Type serviceType2 = typeof(IEnumerable<>).MakeGenericType(serviceType);
			return (IEnumerable<object>)provider.GetRequiredService(serviceType2);
		}

		public static IServiceScope CreateScope(this IServiceProvider provider)
		{
			return provider.GetRequiredService<IServiceScopeFactory>().CreateScope();
		}

		public static AsyncServiceScope CreateAsyncScope(this IServiceProvider provider)
		{
			return new AsyncServiceScope(provider.CreateScope());
		}

		public static AsyncServiceScope CreateAsyncScope(this IServiceScopeFactory serviceScopeFactory)
		{
			return new AsyncServiceScope(serviceScopeFactory.CreateScope());
		}
	}
}
namespace Microsoft.Extensions.DependencyInjection.Extensions
{
	public static class ServiceCollectionDescriptorExtensions
	{
		public static IServiceCollection Add(this IServiceCollection collection, ServiceDescriptor descriptor)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (descriptor == null)
			{
				throw new ArgumentNullException("descriptor");
			}
			collection.Add(descriptor);
			return collection;
		}

		public static IServiceCollection Add(this IServiceCollection collection, IEnumerable<ServiceDescriptor> descriptors)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (descriptors == null)
			{
				throw new ArgumentNullException("descriptors");
			}
			foreach (ServiceDescriptor descriptor in descriptors)
			{
				collection.Add(descriptor);
			}
			return collection;
		}

		public static void TryAdd(this IServiceCollection collection, ServiceDescriptor descriptor)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (descriptor == null)
			{
				throw new ArgumentNullException("descriptor");
			}
			int count = collection.Count;
			for (int i = 0; i < count; i++)
			{
				if (collection[i].ServiceType == descriptor.ServiceType)
				{
					return;
				}
			}
			collection.Add(descriptor);
		}

		public static void TryAdd(this IServiceCollection collection, IEnumerable<ServiceDescriptor> descriptors)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (descriptors == null)
			{
				throw new ArgumentNullException("descriptors");
			}
			foreach (ServiceDescriptor descriptor in descriptors)
			{
				collection.TryAdd(descriptor);
			}
		}

		public static void TryAddTransient(this IServiceCollection collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Transient(service, service);
			collection.TryAdd(descriptor);
		}

		public static void TryAddTransient(this IServiceCollection collection, Type service, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Transient(service, implementationType);
			collection.TryAdd(descriptor);
		}

		public static void TryAddTransient(this IServiceCollection collection, Type service, Func<IServiceProvider, object> implementationFactory)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Transient(service, implementationFactory);
			collection.TryAdd(descriptor);
		}

		public static void TryAddTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection) where TService : class
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			collection.TryAddTransient(typeof(TService), typeof(TService));
		}

		public static void TryAddTransient<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection collection) where TService : class where TImplementation : class, TService
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			collection.TryAddTransient(typeof(TService), typeof(TImplementation));
		}

		public static void TryAddTransient<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			services.TryAdd(ServiceDescriptor.Transient(implementationFactory));
		}

		public static void TryAddScoped(this IServiceCollection collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Scoped(service, service);
			collection.TryAdd(descriptor);
		}

		public static void TryAddScoped(this IServiceCollection collection, Type service, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Scoped(service, implementationType);
			collection.TryAdd(descriptor);
		}

		public static void TryAddScoped(this IServiceCollection collection, Type service, Func<IServiceProvider, object> implementationFactory)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Scoped(service, implementationFactory);
			collection.TryAdd(descriptor);
		}

		public static void TryAddScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection) where TService : class
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			collection.TryAddScoped(typeof(TService), typeof(TService));
		}

		public static void TryAddScoped<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection collection) where TService : class where TImplementation : class, TService
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			collection.TryAddScoped(typeof(TService), typeof(TImplementation));
		}

		public static void TryAddScoped<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			services.TryAdd(ServiceDescriptor.Scoped(implementationFactory));
		}

		public static void TryAddSingleton(this IServiceCollection collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Singleton(service, service);
			collection.TryAdd(descriptor);
		}

		public static void TryAddSingleton(this IServiceCollection collection, Type service, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationType == null)
			{
				throw new ArgumentNullException("implementationType");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Singleton(service, implementationType);
			collection.TryAdd(descriptor);
		}

		public static void TryAddSingleton(this IServiceCollection collection, Type service, Func<IServiceProvider, object> implementationFactory)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (service == null)
			{
				throw new ArgumentNullException("service");
			}
			if (implementationFactory == null)
			{
				throw new ArgumentNullException("implementationFactory");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Singleton(service, implementationFactory);
			collection.TryAdd(descriptor);
		}

		public static void TryAddSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection) where TService : class
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			collection.TryAddSingleton(typeof(TService), typeof(TService));
		}

		public static void TryAddSingleton<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection collection) where TService : class where TImplementation : class, TService
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			collection.TryAddSingleton(typeof(TService), typeof(TImplementation));
		}

		public static void TryAddSingleton<TService>(this IServiceCollection collection, TService instance) where TService : class
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (instance == null)
			{
				throw new ArgumentNullException("instance");
			}
			ServiceDescriptor descriptor = ServiceDescriptor.Singleton(typeof(TService), instance);
			collection.TryAdd(descriptor);
		}

		public static void TryAddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
		{
			services.TryAdd(ServiceDescriptor.Singleton(implementationFactory));
		}

		public static void TryAddEnumerable(this IServiceCollection services, ServiceDescriptor descriptor)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (descriptor == null)
			{
				throw new ArgumentNullException("descriptor");
			}
			Type implementationType = descriptor.GetImplementationType();
			if (implementationType == typeof(object) || implementationType == descriptor.ServiceType)
			{
				throw new ArgumentException(System.SR.Format(System.SR.TryAddIndistinguishableTypeToEnumerable, implementationType, descriptor.ServiceType), "descriptor");
			}
			int count = services.Count;
			for (int i = 0; i < count; i++)
			{
				ServiceDescriptor serviceDescriptor = services[i];
				if (serviceDescriptor.ServiceType == descriptor.ServiceType && serviceDescriptor.GetImplementationType() == implementationType)
				{
					return;
				}
			}
			services.Add(descriptor);
		}

		public static void TryAddEnumerable(this IServiceCollection services, IEnumerable<ServiceDescriptor> descriptors)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (descriptors == null)
			{
				throw new ArgumentNullException("descriptors");
			}
			foreach (ServiceDescriptor descriptor in descriptors)
			{
				services.TryAddEnumerable(descriptor);
			}
		}

		public static IServiceCollection Replace(this IServiceCollection collection, ServiceDescriptor descriptor)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (descriptor == null)
			{
				throw new ArgumentNullException("descriptor");
			}
			int count = collection.Count;
			for (int i = 0; i < count; i++)
			{
				if (collection[i].ServiceType == descriptor.ServiceType)
				{
					collection.RemoveAt(i);
					break;
				}
			}
			collection.Add(descriptor);
			return collection;
		}

		public static IServiceCollection RemoveAll<T>(this IServiceCollection collection)
		{
			return collection.RemoveAll(typeof(T));
		}

		public static IServiceCollection RemoveAll(this IServiceCollection collection, Type serviceType)
		{
			if (serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			for (int num = collection.Count - 1; num >= 0; num--)
			{
				ServiceDescriptor serviceDescriptor = collection[num];
				if (serviceDescriptor.ServiceType == serviceType)
				{
					collection.RemoveAt(num);
				}
			}
			return collection;
		}
	}
}

plugins/TwitchLib/Microsoft.Extensions.DependencyInjection.dll

Decompiled 6 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FxResources.Microsoft.Extensions.DependencyInjection;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.ServiceLookup;
using Microsoft.Extensions.Internal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Microsoft.Extensions.DependencyInjection.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("MicroBenchmarks, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyDefaultAlias("Microsoft.Extensions.DependencyInjection")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Default implementation of dependency injection for Microsoft.Extensions.DependencyInjection.")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.DependencyInjection")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: TypeForwardedTo(typeof(ServiceCollection))]
[module: System.Runtime.CompilerServices.NullablePublicOnly(true)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 NullablePublicOnlyAttribute : Attribute
	{
		public readonly bool IncludesInternals;

		public NullablePublicOnlyAttribute(bool P_0)
		{
			IncludesInternals = P_0;
		}
	}
}
namespace FxResources.Microsoft.Extensions.DependencyInjection
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string AmbiguousConstructorException => GetResourceString("AmbiguousConstructorException");

		internal static string CannotResolveService => GetResourceString("CannotResolveService");

		internal static string CircularDependencyException => GetResourceString("CircularDependencyException");

		internal static string UnableToActivateTypeException => GetResourceString("UnableToActivateTypeException");

		internal static string OpenGenericServiceRequiresOpenGenericImplementation => GetResourceString("OpenGenericServiceRequiresOpenGenericImplementation");

		internal static string ArityOfOpenGenericServiceNotEqualArityOfOpenGenericImplementation => GetResourceString("ArityOfOpenGenericServiceNotEqualArityOfOpenGenericImplementation");

		internal static string TypeCannotBeActivated => GetResourceString("TypeCannotBeActivated");

		internal static string NoConstructorMatch => GetResourceString("NoConstructorMatch");

		internal static string ScopedInSingletonException => GetResourceString("ScopedInSingletonException");

		internal static string ScopedResolvedFromRootException => GetResourceString("ScopedResolvedFromRootException");

		internal static string DirectScopedResolvedFromRootException => GetResourceString("DirectScopedResolvedFromRootException");

		internal static string ConstantCantBeConvertedToServiceType => GetResourceString("ConstantCantBeConvertedToServiceType");

		internal static string ImplementationTypeCantBeConvertedToServiceType => GetResourceString("ImplementationTypeCantBeConvertedToServiceType");

		internal static string AsyncDisposableServiceDispose => GetResourceString("AsyncDisposableServiceDispose");

		internal static string GetCaptureDisposableNotSupported => GetResourceString("GetCaptureDisposableNotSupported");

		internal static string InvalidServiceDescriptor => GetResourceString("InvalidServiceDescriptor");

		internal static string ServiceDescriptorNotExist => GetResourceString("ServiceDescriptorNotExist");

		internal static string CallSiteTypeNotSupported => GetResourceString("CallSiteTypeNotSupported");

		internal static string TrimmingAnnotationsDoNotMatch => GetResourceString("TrimmingAnnotationsDoNotMatch");

		internal static string TrimmingAnnotationsDoNotMatch_NewConstraint => GetResourceString("TrimmingAnnotationsDoNotMatch_NewConstraint");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
	internal sealed class DynamicallyAccessedMembersAttribute : Attribute
	{
		public DynamicallyAccessedMemberTypes MemberTypes { get; }

		public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
		{
			MemberTypes = memberTypes;
		}
	}
	[Flags]
	internal enum DynamicallyAccessedMemberTypes
	{
		None = 0,
		PublicParameterlessConstructor = 1,
		PublicConstructors = 3,
		NonPublicConstructors = 4,
		PublicMethods = 8,
		NonPublicMethods = 0x10,
		PublicFields = 0x20,
		NonPublicFields = 0x40,
		PublicNestedTypes = 0x80,
		NonPublicNestedTypes = 0x100,
		PublicProperties = 0x200,
		NonPublicProperties = 0x400,
		PublicEvents = 0x800,
		NonPublicEvents = 0x1000,
		Interfaces = 0x2000,
		All = -1
	}
	[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
	internal sealed class UnconditionalSuppressMessageAttribute : Attribute
	{
		public string Category { get; }

		public string CheckId { get; }

		public string? Scope { get; set; }

		public string? Target { get; set; }

		public string? MessageId { get; set; }

		public string? Justification { get; set; }

		public UnconditionalSuppressMessageAttribute(string category, string checkId)
		{
			Category = category;
			CheckId = checkId;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class AllowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class DisallowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class MaybeNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class NotNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class MaybeNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public MaybeNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class NotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public NotNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
	internal sealed class NotNullIfNotNullAttribute : Attribute
	{
		public string ParameterName { get; }

		public NotNullIfNotNullAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	internal sealed class DoesNotReturnAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class DoesNotReturnIfAttribute : Attribute
	{
		public bool ParameterValue { get; }

		public DoesNotReturnIfAttribute(bool parameterValue)
		{
			ParameterValue = parameterValue;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
}
namespace Microsoft.Extensions.DependencyInjection
{
	internal sealed class CallSiteJsonFormatter : CallSiteVisitor<CallSiteJsonFormatter.CallSiteFormatterContext, object>
	{
		internal struct CallSiteFormatterContext
		{
			private readonly HashSet<ServiceCallSite> _processedCallSites;

			private bool _firstItem;

			public int Offset { get; }

			public StringBuilder Builder { get; }

			public CallSiteFormatterContext(StringBuilder builder, int offset, HashSet<ServiceCallSite> processedCallSites)
			{
				Builder = builder;
				Offset = offset;
				_processedCallSites = processedCallSites;
				_firstItem = true;
			}

			public bool ShouldFormat(ServiceCallSite serviceCallSite)
			{
				return _processedCallSites.Add(serviceCallSite);
			}

			public CallSiteFormatterContext IncrementOffset()
			{
				CallSiteFormatterContext result = new CallSiteFormatterContext(Builder, Offset + 4, _processedCallSites);
				result._firstItem = true;
				return result;
			}

			public CallSiteFormatterContext StartObject()
			{
				Builder.Append('{');
				return IncrementOffset();
			}

			public void EndObject()
			{
				Builder.Append('}');
			}

			public void StartProperty(string name)
			{
				if (!_firstItem)
				{
					Builder.Append(',');
				}
				else
				{
					_firstItem = false;
				}
				Builder.AppendFormat("\"{0}\":", name);
			}

			public void StartArrayItem()
			{
				if (!_firstItem)
				{
					Builder.Append(',');
				}
				else
				{
					_firstItem = false;
				}
			}

			public void WriteProperty(string name, object value)
			{
				StartProperty(name);
				if (value != null)
				{
					Builder.AppendFormat(" \"{0}\"", value);
				}
				else
				{
					Builder.Append("null");
				}
			}

			public CallSiteFormatterContext StartArray()
			{
				Builder.Append('[');
				return IncrementOffset();
			}

			public void EndArray()
			{
				Builder.Append(']');
			}
		}

		internal static CallSiteJsonFormatter Instance = new CallSiteJsonFormatter();

		private CallSiteJsonFormatter()
		{
		}

		public string Format(ServiceCallSite callSite)
		{
			StringBuilder stringBuilder = new StringBuilder();
			CallSiteFormatterContext argument = new CallSiteFormatterContext(stringBuilder, 0, new HashSet<ServiceCallSite>());
			VisitCallSite(callSite, argument);
			return stringBuilder.ToString();
		}

		protected override object VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteFormatterContext argument)
		{
			argument.WriteProperty("implementationType", constructorCallSite.ImplementationType);
			if (constructorCallSite.ParameterCallSites.Length != 0)
			{
				argument.StartProperty("arguments");
				CallSiteFormatterContext argument2 = argument.StartArray();
				ServiceCallSite[] parameterCallSites = constructorCallSite.ParameterCallSites;
				foreach (ServiceCallSite callSite in parameterCallSites)
				{
					argument2.StartArrayItem();
					VisitCallSite(callSite, argument2);
				}
				argument.EndArray();
			}
			return null;
		}

		protected override object VisitCallSiteMain(ServiceCallSite callSite, CallSiteFormatterContext argument)
		{
			if (argument.ShouldFormat(callSite))
			{
				CallSiteFormatterContext argument2 = argument.StartObject();
				argument2.WriteProperty("serviceType", callSite.ServiceType);
				argument2.WriteProperty("kind", callSite.Kind);
				argument2.WriteProperty("cache", callSite.Cache.Location);
				base.VisitCallSiteMain(callSite, argument2);
				argument.EndObject();
			}
			else
			{
				argument.StartObject().WriteProperty("ref", callSite.ServiceType);
				argument.EndObject();
			}
			return null;
		}

		protected override object VisitConstant(ConstantCallSite constantCallSite, CallSiteFormatterContext argument)
		{
			argument.WriteProperty("value", constantCallSite.DefaultValue ?? "");
			return null;
		}

		protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteFormatterContext argument)
		{
			return null;
		}

		protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteFormatterContext argument)
		{
			argument.WriteProperty("itemType", enumerableCallSite.ItemType);
			argument.WriteProperty("size", enumerableCallSite.ServiceCallSites.Length);
			if (enumerableCallSite.ServiceCallSites.Length != 0)
			{
				argument.StartProperty("items");
				CallSiteFormatterContext argument2 = argument.StartArray();
				ServiceCallSite[] serviceCallSites = enumerableCallSite.ServiceCallSites;
				foreach (ServiceCallSite callSite in serviceCallSites)
				{
					argument2.StartArrayItem();
					VisitCallSite(callSite, argument2);
				}
				argument.EndArray();
			}
			return null;
		}

		protected override object VisitFactory(FactoryCallSite factoryCallSite, CallSiteFormatterContext argument)
		{
			argument.WriteProperty("method", factoryCallSite.Factory.Method);
			return null;
		}
	}
	public class DefaultServiceProviderFactory : IServiceProviderFactory<IServiceCollection>
	{
		private readonly ServiceProviderOptions _options;

		public DefaultServiceProviderFactory()
			: this(ServiceProviderOptions.Default)
		{
		}

		public DefaultServiceProviderFactory(ServiceProviderOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			_options = options;
		}

		public IServiceCollection CreateBuilder(IServiceCollection services)
		{
			return services;
		}

		public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
		{
			return containerBuilder.BuildServiceProvider(_options);
		}
	}
	[EventSource(Name = "Microsoft-Extensions-DependencyInjection")]
	internal sealed class DependencyInjectionEventSource : EventSource
	{
		public static class Keywords
		{
			public const EventKeywords ServiceProviderInitialized = (EventKeywords)1L;
		}

		public static readonly DependencyInjectionEventSource Log = new DependencyInjectionEventSource();

		private const int MaxChunkSize = 10240;

		private readonly List<WeakReference<ServiceProvider>> _providers = new List<WeakReference<ServiceProvider>>();

		private DependencyInjectionEventSource()
			: base(EventSourceSettings.EtwSelfDescribingEventFormat)
		{
		}

		[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Parameters to this method are primitive and are trimmer safe.")]
		[Event(1, Level = EventLevel.Verbose)]
		private void CallSiteBuilt(string serviceType, string callSite, int chunkIndex, int chunkCount, int serviceProviderHashCode)
		{
			WriteEvent(1, serviceType, callSite, chunkIndex, chunkCount, serviceProviderHashCode);
		}

		[Event(2, Level = EventLevel.Verbose)]
		public void ServiceResolved(string serviceType, int serviceProviderHashCode)
		{
			WriteEvent(2, serviceType, serviceProviderHashCode);
		}

		[Event(3, Level = EventLevel.Verbose)]
		public void ExpressionTreeGenerated(string serviceType, int nodeCount, int serviceProviderHashCode)
		{
			WriteEvent(3, serviceType, nodeCount, serviceProviderHashCode);
		}

		[Event(4, Level = EventLevel.Verbose)]
		public void DynamicMethodBuilt(string serviceType, int methodSize, int serviceProviderHashCode)
		{
			WriteEvent(4, serviceType, methodSize, serviceProviderHashCode);
		}

		[Event(5, Level = EventLevel.Verbose)]
		public void ScopeDisposed(int serviceProviderHashCode, int scopedServicesResolved, int disposableServices)
		{
			WriteEvent(5, serviceProviderHashCode, scopedServicesResolved, disposableServices);
		}

		[Event(6, Level = EventLevel.Error)]
		public void ServiceRealizationFailed(string? exceptionMessage, int serviceProviderHashCode)
		{
			WriteEvent(6, exceptionMessage, serviceProviderHashCode);
		}

		[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Parameters to this method are primitive and are trimmer safe.")]
		[Event(7, Level = EventLevel.Informational, Keywords = (EventKeywords)1L)]
		private void ServiceProviderBuilt(int serviceProviderHashCode, int singletonServices, int scopedServices, int transientServices, int closedGenericsServices, int openGenericsServices)
		{
			WriteEvent(7, serviceProviderHashCode, singletonServices, scopedServices, transientServices, closedGenericsServices, openGenericsServices);
		}

		[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Parameters to this method are primitive and are trimmer safe.")]
		[Event(8, Level = EventLevel.Informational, Keywords = (EventKeywords)1L)]
		private void ServiceProviderDescriptors(int serviceProviderHashCode, string descriptors, int chunkIndex, int chunkCount)
		{
			WriteEvent(8, serviceProviderHashCode, descriptors, chunkIndex, chunkCount);
		}

		[NonEvent]
		public void ServiceResolved(ServiceProvider provider, Type serviceType)
		{
			if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
			{
				ServiceResolved(serviceType.ToString(), provider.GetHashCode());
			}
		}

		[NonEvent]
		public void CallSiteBuilt(ServiceProvider provider, Type serviceType, ServiceCallSite callSite)
		{
			if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
			{
				string text = CallSiteJsonFormatter.Instance.Format(callSite);
				int num = text.Length / 10240 + ((text.Length % 10240 > 0) ? 1 : 0);
				int hashCode = provider.GetHashCode();
				for (int i = 0; i < num; i++)
				{
					CallSiteBuilt(serviceType.ToString(), text.Substring(i * 10240, Math.Min(10240, text.Length - i * 10240)), i, num, hashCode);
				}
			}
		}

		[NonEvent]
		public void DynamicMethodBuilt(ServiceProvider provider, Type serviceType, int methodSize)
		{
			if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
			{
				DynamicMethodBuilt(serviceType.ToString(), methodSize, provider.GetHashCode());
			}
		}

		[NonEvent]
		public void ServiceRealizationFailed(Exception exception, int serviceProviderHashCode)
		{
			if (IsEnabled(EventLevel.Error, EventKeywords.All))
			{
				ServiceRealizationFailed(exception.ToString(), serviceProviderHashCode);
			}
		}

		[NonEvent]
		public void ServiceProviderBuilt(ServiceProvider provider)
		{
			lock (_providers)
			{
				_providers.Add(new WeakReference<ServiceProvider>(provider));
			}
			WriteServiceProviderBuilt(provider);
		}

		[NonEvent]
		public void ServiceProviderDisposed(ServiceProvider provider)
		{
			lock (_providers)
			{
				for (int num = _providers.Count - 1; num >= 0; num--)
				{
					WeakReference<ServiceProvider> weakReference = _providers[num];
					if (!weakReference.TryGetTarget(out var target) || target == provider)
					{
						_providers.RemoveAt(num);
					}
				}
			}
		}

		[NonEvent]
		private void WriteServiceProviderBuilt(ServiceProvider provider)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected I4, but got Unknown
			if (!IsEnabled(EventLevel.Informational, (EventKeywords)1L))
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			StringBuilder stringBuilder = new StringBuilder("{ \"descriptors\":[ ");
			bool flag = true;
			ServiceDescriptor[] descriptors = provider.CallSiteFactory.Descriptors;
			foreach (ServiceDescriptor val in descriptors)
			{
				if (flag)
				{
					flag = false;
				}
				else
				{
					stringBuilder.Append(", ");
				}
				AppendServiceDescriptor(stringBuilder, val);
				ServiceLifetime lifetime = val.Lifetime;
				switch ((int)lifetime)
				{
				case 0:
					num++;
					break;
				case 1:
					num2++;
					break;
				case 2:
					num3++;
					break;
				}
				if (val.ServiceType.IsGenericType)
				{
					if (val.ServiceType.IsConstructedGenericType)
					{
						num4++;
					}
					else
					{
						num5++;
					}
				}
			}
			stringBuilder.Append(" ] }");
			int hashCode = provider.GetHashCode();
			ServiceProviderBuilt(hashCode, num, num2, num3, num4, num5);
			string text = stringBuilder.ToString();
			int num6 = text.Length / 10240 + ((text.Length % 10240 > 0) ? 1 : 0);
			for (int j = 0; j < num6; j++)
			{
				ServiceProviderDescriptors(hashCode, text.Substring(j * 10240, Math.Min(10240, text.Length - j * 10240)), j, num6);
			}
		}

		[NonEvent]
		private static void AppendServiceDescriptor(StringBuilder builder, ServiceDescriptor descriptor)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			builder.Append("{ \"serviceType\": \"");
			builder.Append(descriptor.ServiceType);
			builder.Append("\", \"lifetime\": \"");
			builder.Append(descriptor.Lifetime);
			builder.Append("\", ");
			if ((object)descriptor.ImplementationType != null)
			{
				builder.Append("\"implementationType\": \"");
				builder.Append(descriptor.ImplementationType);
			}
			else if (descriptor.ImplementationFactory != null)
			{
				builder.Append("\"implementationFactory\": \"");
				builder.Append(descriptor.ImplementationFactory.Method);
			}
			else if (descriptor.ImplementationInstance != null)
			{
				builder.Append("\"implementationInstance\": \"");
				builder.Append(descriptor.ImplementationInstance.GetType());
				builder.Append(" (instance)");
			}
			else
			{
				builder.Append("\"unknown\": \"");
			}
			builder.Append("\" }");
		}

		protected override void OnEventCommand(EventCommandEventArgs command)
		{
			if (command.Command != EventCommand.Enable)
			{
				return;
			}
			lock (_providers)
			{
				foreach (WeakReference<ServiceProvider> provider in _providers)
				{
					if (provider.TryGetTarget(out var target))
					{
						WriteServiceProviderBuilt(target);
					}
				}
			}
		}
	}
	internal static class DependencyInjectionEventSourceExtensions
	{
		private sealed class NodeCountingVisitor : ExpressionVisitor
		{
			public int NodeCount { get; private set; }

			public override Expression Visit(Expression e)
			{
				base.Visit(e);
				NodeCount++;
				return e;
			}
		}

		public static void ExpressionTreeGenerated(this DependencyInjectionEventSource source, ServiceProvider provider, Type serviceType, Expression expression)
		{
			if (source.IsEnabled(EventLevel.Verbose, EventKeywords.All))
			{
				NodeCountingVisitor nodeCountingVisitor = new NodeCountingVisitor();
				nodeCountingVisitor.Visit(expression);
				source.ExpressionTreeGenerated(serviceType.ToString(), nodeCountingVisitor.NodeCount, provider.GetHashCode());
			}
		}
	}
	public static class ServiceCollectionContainerBuilderExtensions
	{
		public static ServiceProvider BuildServiceProvider(this IServiceCollection services)
		{
			return services.BuildServiceProvider(ServiceProviderOptions.Default);
		}

		public static ServiceProvider BuildServiceProvider(this IServiceCollection services, bool validateScopes)
		{
			return services.BuildServiceProvider(new ServiceProviderOptions
			{
				ValidateScopes = validateScopes
			});
		}

		public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			return new ServiceProvider((ICollection<ServiceDescriptor>)services, options);
		}
	}
	public sealed class ServiceProvider : IServiceProvider, IDisposable, IAsyncDisposable
	{
		private readonly CallSiteValidator _callSiteValidator;

		private readonly Func<Type, Func<ServiceProviderEngineScope, object>> _createServiceAccessor;

		internal ServiceProviderEngine _engine;

		private bool _disposed;

		private ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>> _realizedServices;

		internal CallSiteFactory CallSiteFactory { get; }

		internal ServiceProviderEngineScope Root { get; }

		internal static bool VerifyOpenGenericServiceTrimmability { get; } = AppContext.TryGetSwitch("Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability", out var isEnabled) && isEnabled;


		internal ServiceProvider(ICollection<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
		{
			Root = new ServiceProviderEngineScope(this, isRootScope: true);
			_engine = GetEngine();
			_createServiceAccessor = CreateServiceAccessor;
			_realizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>();
			CallSiteFactory = new CallSiteFactory(serviceDescriptors);
			CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
			CallSiteFactory.Add(typeof(IServiceScopeFactory), new ConstantCallSite(typeof(IServiceScopeFactory), Root));
			CallSiteFactory.Add(typeof(IServiceProviderIsService), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory));
			if (options.ValidateScopes)
			{
				_callSiteValidator = new CallSiteValidator();
			}
			if (options.ValidateOnBuild)
			{
				List<Exception> list = null;
				foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors)
				{
					try
					{
						ValidateService(serviceDescriptor);
					}
					catch (Exception item)
					{
						list = list ?? new List<Exception>();
						list.Add(item);
					}
				}
				if (list != null)
				{
					throw new AggregateException("Some services are not able to be constructed", list.ToArray());
				}
			}
			DependencyInjectionEventSource.Log.ServiceProviderBuilt(this);
		}

		public object GetService(Type serviceType)
		{
			return GetService(serviceType, Root);
		}

		public void Dispose()
		{
			DisposeCore();
			Root.Dispose();
		}

		public ValueTask DisposeAsync()
		{
			DisposeCore();
			return Root.DisposeAsync();
		}

		private void DisposeCore()
		{
			_disposed = true;
			DependencyInjectionEventSource.Log.ServiceProviderDisposed(this);
		}

		private void OnCreate(ServiceCallSite callSite)
		{
			_callSiteValidator?.ValidateCallSite(callSite);
		}

		private void OnResolve(Type serviceType, IServiceScope scope)
		{
			_callSiteValidator?.ValidateResolution(serviceType, scope, (IServiceScope)(object)Root);
		}

		internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
		{
			if (_disposed)
			{
				ThrowHelper.ThrowObjectDisposedException();
			}
			Func<ServiceProviderEngineScope, object> orAdd = _realizedServices.GetOrAdd(serviceType, _createServiceAccessor);
			OnResolve(serviceType, (IServiceScope)(object)serviceProviderEngineScope);
			DependencyInjectionEventSource.Log.ServiceResolved(this, serviceType);
			return orAdd(serviceProviderEngineScope);
		}

		private void ValidateService(ServiceDescriptor descriptor)
		{
			if (descriptor.ServiceType.IsGenericType && !descriptor.ServiceType.IsConstructedGenericType)
			{
				return;
			}
			try
			{
				ServiceCallSite callSite = CallSiteFactory.GetCallSite(descriptor, new CallSiteChain());
				if (callSite != null)
				{
					OnCreate(callSite);
				}
			}
			catch (Exception ex)
			{
				throw new InvalidOperationException($"Error while validating the service descriptor '{descriptor}': {ex.Message}", ex);
			}
		}

		private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(Type serviceType)
		{
			ServiceCallSite callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain());
			if (callSite != null)
			{
				DependencyInjectionEventSource.Log.CallSiteBuilt(this, serviceType, callSite);
				OnCreate(callSite);
				if (callSite.Cache.Location == CallSiteResultCacheLocation.Root)
				{
					object value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root);
					return (ServiceProviderEngineScope scope) => value;
				}
				return _engine.RealizeService(callSite);
			}
			return (ServiceProviderEngineScope _) => null;
		}

		internal void ReplaceServiceAccessor(ServiceCallSite callSite, Func<ServiceProviderEngineScope, object> accessor)
		{
			_realizedServices[callSite.ServiceType] = accessor;
		}

		internal IServiceScope CreateScope()
		{
			if (_disposed)
			{
				ThrowHelper.ThrowObjectDisposedException();
			}
			return (IServiceScope)(object)new ServiceProviderEngineScope(this, isRootScope: false);
		}

		private ServiceProviderEngine GetEngine()
		{
			return new DynamicServiceProviderEngine(this);
		}
	}
	public class ServiceProviderOptions
	{
		internal static readonly ServiceProviderOptions Default = new ServiceProviderOptions();

		public bool ValidateScopes { get; set; }

		public bool ValidateOnBuild { get; set; }
	}
}
namespace Microsoft.Extensions.DependencyInjection.ServiceLookup
{
	internal sealed class CallSiteChain
	{
		private readonly struct ChainItemInfo
		{
			public int Order { get; }

			public Type ImplementationType { get; }

			public ChainItemInfo(int order, Type implementationType)
			{
				Order = order;
				ImplementationType = implementationType;
			}
		}

		private readonly Dictionary<Type, ChainItemInfo> _callSiteChain;

		public CallSiteChain()
		{
			_callSiteChain = new Dictionary<Type, ChainItemInfo>();
		}

		public void CheckCircularDependency(Type serviceType)
		{
			if (_callSiteChain.ContainsKey(serviceType))
			{
				throw new InvalidOperationException(CreateCircularDependencyExceptionMessage(serviceType));
			}
		}

		public void Remove(Type serviceType)
		{
			_callSiteChain.Remove(serviceType);
		}

		public void Add(Type serviceType, Type implementationType = null)
		{
			_callSiteChain[serviceType] = new ChainItemInfo(_callSiteChain.Count, implementationType);
		}

		private string CreateCircularDependencyExceptionMessage(Type type)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(System.SR.Format(System.SR.CircularDependencyException, TypeNameHelper.GetTypeDisplayName(type)));
			stringBuilder.AppendLine();
			AppendResolutionPath(stringBuilder, type);
			return stringBuilder.ToString();
		}

		private void AppendResolutionPath(StringBuilder builder, Type currentlyResolving)
		{
			List<KeyValuePair<Type, ChainItemInfo>> list = new List<KeyValuePair<Type, ChainItemInfo>>(_callSiteChain);
			list.Sort((KeyValuePair<Type, ChainItemInfo> a, KeyValuePair<Type, ChainItemInfo> b) => a.Value.Order.CompareTo(b.Value.Order));
			foreach (KeyValuePair<Type, ChainItemInfo> item in list)
			{
				Type key = item.Key;
				Type implementationType = item.Value.ImplementationType;
				if (implementationType == null || key == implementationType)
				{
					builder.Append(TypeNameHelper.GetTypeDisplayName(key));
				}
				else
				{
					builder.AppendFormat("{0}({1})", TypeNameHelper.GetTypeDisplayName(key), TypeNameHelper.GetTypeDisplayName(implementationType));
				}
				builder.Append(" -> ");
			}
			builder.Append(TypeNameHelper.GetTypeDisplayName(currentlyResolving));
		}
	}
	internal sealed class CallSiteFactory : IServiceProviderIsService
	{
		private struct ServiceDescriptorCacheItem
		{
			private ServiceDescriptor _item;

			private List<ServiceDescriptor> _items;

			public ServiceDescriptor Last
			{
				get
				{
					if (_items != null && _items.Count > 0)
					{
						return _items[_items.Count - 1];
					}
					return _item;
				}
			}

			public int Count
			{
				get
				{
					if (_item == null)
					{
						return 0;
					}
					return 1 + (_items?.Count ?? 0);
				}
			}

			public ServiceDescriptor this[int index]
			{
				get
				{
					if (index >= Count)
					{
						throw new ArgumentOutOfRangeException("index");
					}
					if (index == 0)
					{
						return _item;
					}
					return _items[index - 1];
				}
			}

			public int GetSlot(ServiceDescriptor descriptor)
			{
				if (descriptor == _item)
				{
					return Count - 1;
				}
				if (_items != null)
				{
					int num = _items.IndexOf(descriptor);
					if (num != -1)
					{
						return _items.Count - (num + 1);
					}
				}
				throw new InvalidOperationException(System.SR.ServiceDescriptorNotExist);
			}

			public ServiceDescriptorCacheItem Add(ServiceDescriptor descriptor)
			{
				ServiceDescriptorCacheItem result = default(ServiceDescriptorCacheItem);
				if (_item == null)
				{
					result._item = descriptor;
				}
				else
				{
					result._item = _item;
					result._items = _items ?? new List<ServiceDescriptor>();
					result._items.Add(descriptor);
				}
				return result;
			}
		}

		private const int DefaultSlot = 0;

		private readonly ServiceDescriptor[] _descriptors;

		private readonly ConcurrentDictionary<ServiceCacheKey, ServiceCallSite> _callSiteCache = new ConcurrentDictionary<ServiceCacheKey, ServiceCallSite>();

		private readonly Dictionary<Type, ServiceDescriptorCacheItem> _descriptorLookup = new Dictionary<Type, ServiceDescriptorCacheItem>();

		private readonly ConcurrentDictionary<Type, object> _callSiteLocks = new ConcurrentDictionary<Type, object>();

		private readonly StackGuard _stackGuard;

		internal ServiceDescriptor[] Descriptors => _descriptors;

		public CallSiteFactory(ICollection<ServiceDescriptor> descriptors)
		{
			_stackGuard = new StackGuard();
			_descriptors = (ServiceDescriptor[])(object)new ServiceDescriptor[descriptors.Count];
			descriptors.CopyTo(_descriptors, 0);
			Populate();
		}

		private void Populate()
		{
			ServiceDescriptor[] descriptors = _descriptors;
			foreach (ServiceDescriptor val in descriptors)
			{
				Type serviceType = val.ServiceType;
				if (serviceType.IsGenericTypeDefinition)
				{
					Type implementationType = val.ImplementationType;
					if (implementationType == null || !implementationType.IsGenericTypeDefinition)
					{
						throw new ArgumentException(System.SR.Format(System.SR.OpenGenericServiceRequiresOpenGenericImplementation, serviceType), "descriptors");
					}
					if (implementationType.IsAbstract || implementationType.IsInterface)
					{
						throw new ArgumentException(System.SR.Format(System.SR.TypeCannotBeActivated, implementationType, serviceType));
					}
					Type[] genericArguments = serviceType.GetGenericArguments();
					Type[] genericArguments2 = implementationType.GetGenericArguments();
					if (genericArguments.Length != genericArguments2.Length)
					{
						throw new ArgumentException(System.SR.Format(System.SR.ArityOfOpenGenericServiceNotEqualArityOfOpenGenericImplementation, serviceType, implementationType), "descriptors");
					}
					if (ServiceProvider.VerifyOpenGenericServiceTrimmability)
					{
						ValidateTrimmingAnnotations(serviceType, genericArguments, implementationType, genericArguments2);
					}
				}
				else if (val.ImplementationInstance == null && val.ImplementationFactory == null)
				{
					Type implementationType2 = val.ImplementationType;
					if (implementationType2.IsGenericTypeDefinition || implementationType2.IsAbstract || implementationType2.IsInterface)
					{
						throw new ArgumentException(System.SR.Format(System.SR.TypeCannotBeActivated, implementationType2, serviceType));
					}
				}
				Type key = serviceType;
				_descriptorLookup.TryGetValue(key, out var value);
				_descriptorLookup[key] = value.Add(val);
			}
		}

		private static void ValidateTrimmingAnnotations(Type serviceType, Type[] serviceTypeGenericArguments, Type implementationType, Type[] implementationTypeGenericArguments)
		{
			for (int i = 0; i < serviceTypeGenericArguments.Length; i++)
			{
				Type type = serviceTypeGenericArguments[i];
				Type type2 = implementationTypeGenericArguments[i];
				DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes = GetDynamicallyAccessedMemberTypes(type);
				DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes2 = GetDynamicallyAccessedMemberTypes(type2);
				if (!AreCompatible(dynamicallyAccessedMemberTypes, dynamicallyAccessedMemberTypes2))
				{
					throw new ArgumentException(System.SR.Format(System.SR.TrimmingAnnotationsDoNotMatch, implementationType.FullName, serviceType.FullName));
				}
				bool flag = type.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint);
				if (type2.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint) && !flag)
				{
					throw new ArgumentException(System.SR.Format(System.SR.TrimmingAnnotationsDoNotMatch_NewConstraint, implementationType.FullName, serviceType.FullName));
				}
			}
		}

		private static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypes(Type serviceGenericType)
		{
			foreach (CustomAttributeData customAttributesDatum in serviceGenericType.GetCustomAttributesData())
			{
				if (customAttributesDatum.AttributeType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute" && customAttributesDatum.ConstructorArguments.Count == 1 && customAttributesDatum.ConstructorArguments[0].ArgumentType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes")
				{
					return (DynamicallyAccessedMemberTypes)(int)customAttributesDatum.ConstructorArguments[0].Value;
				}
			}
			return DynamicallyAccessedMemberTypes.None;
		}

		private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamicallyAccessedMembers, DynamicallyAccessedMemberTypes implementationDynamicallyAccessedMembers)
		{
			return serviceDynamicallyAccessedMembers.HasFlag(implementationDynamicallyAccessedMembers);
		}

		internal int? GetSlot(ServiceDescriptor serviceDescriptor)
		{
			if (_descriptorLookup.TryGetValue(serviceDescriptor.ServiceType, out var value))
			{
				return value.GetSlot(serviceDescriptor);
			}
			return null;
		}

		internal ServiceCallSite GetCallSite(Type serviceType, CallSiteChain callSiteChain)
		{
			if (!_callSiteCache.TryGetValue(new ServiceCacheKey(serviceType, 0), out var value))
			{
				return CreateCallSite(serviceType, callSiteChain);
			}
			return value;
		}

		internal ServiceCallSite GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain)
		{
			if (_descriptorLookup.TryGetValue(serviceDescriptor.ServiceType, out var value))
			{
				return TryCreateExact(serviceDescriptor, serviceDescriptor.ServiceType, callSiteChain, value.GetSlot(serviceDescriptor));
			}
			return null;
		}

		private ServiceCallSite CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
		{
			if (!_stackGuard.TryEnterOnCurrentStack())
			{
				return _stackGuard.RunOnEmptyStack((Type type, CallSiteChain chain) => CreateCallSite(type, chain), serviceType, callSiteChain);
			}
			object orAdd = _callSiteLocks.GetOrAdd(serviceType, (Type _) => new object());
			lock (orAdd)
			{
				callSiteChain.CheckCircularDependency(serviceType);
				return TryCreateExact(serviceType, callSiteChain) ?? TryCreateOpenGeneric(serviceType, callSiteChain) ?? TryCreateEnumerable(serviceType, callSiteChain);
			}
		}

		private ServiceCallSite TryCreateExact(Type serviceType, CallSiteChain callSiteChain)
		{
			if (_descriptorLookup.TryGetValue(serviceType, out var value))
			{
				return TryCreateExact(value.Last, serviceType, callSiteChain, 0);
			}
			return null;
		}

		private ServiceCallSite TryCreateOpenGeneric(Type serviceType, CallSiteChain callSiteChain)
		{
			if (serviceType.IsConstructedGenericType && _descriptorLookup.TryGetValue(serviceType.GetGenericTypeDefinition(), out var value))
			{
				return TryCreateOpenGeneric(value.Last, serviceType, callSiteChain, 0, throwOnConstraintViolation: true);
			}
			return null;
		}

		private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)
		{
			ServiceCacheKey serviceCacheKey = new ServiceCacheKey(serviceType, 0);
			if (_callSiteCache.TryGetValue(serviceCacheKey, out var value))
			{
				return value;
			}
			ServiceCallSite serviceCallSite4;
			try
			{
				callSiteChain.Add(serviceType);
				if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
				{
					Type type = serviceType.GenericTypeArguments[0];
					CallSiteResultCacheLocation callSiteResultCacheLocation = CallSiteResultCacheLocation.Root;
					List<ServiceCallSite> list = new List<ServiceCallSite>();
					if (!type.IsConstructedGenericType && _descriptorLookup.TryGetValue(type, out var value2))
					{
						for (int i = 0; i < value2.Count; i++)
						{
							ServiceDescriptor descriptor = value2[i];
							int slot = value2.Count - i - 1;
							ServiceCallSite serviceCallSite = TryCreateExact(descriptor, type, callSiteChain, slot);
							callSiteResultCacheLocation = GetCommonCacheLocation(callSiteResultCacheLocation, serviceCallSite.Cache.Location);
							list.Add(serviceCallSite);
						}
					}
					else
					{
						int num = 0;
						for (int num2 = _descriptors.Length - 1; num2 >= 0; num2--)
						{
							ServiceDescriptor descriptor2 = _descriptors[num2];
							ServiceCallSite serviceCallSite2 = TryCreateExact(descriptor2, type, callSiteChain, num) ?? TryCreateOpenGeneric(descriptor2, type, callSiteChain, num, throwOnConstraintViolation: false);
							if (serviceCallSite2 != null)
							{
								num++;
								callSiteResultCacheLocation = GetCommonCacheLocation(callSiteResultCacheLocation, serviceCallSite2.Cache.Location);
								list.Add(serviceCallSite2);
							}
						}
						list.Reverse();
					}
					ResultCache cache = ResultCache.None;
					if (callSiteResultCacheLocation == CallSiteResultCacheLocation.Scope || callSiteResultCacheLocation == CallSiteResultCacheLocation.Root)
					{
						cache = new ResultCache(callSiteResultCacheLocation, serviceCacheKey);
					}
					serviceCallSite4 = (_callSiteCache[serviceCacheKey] = new IEnumerableCallSite(cache, type, list.ToArray()));
					serviceCallSite4 = serviceCallSite4;
				}
				else
				{
					serviceCallSite4 = null;
				}
			}
			finally
			{
				callSiteChain.Remove(serviceType);
			}
			return serviceCallSite4;
		}

		private CallSiteResultCacheLocation GetCommonCacheLocation(CallSiteResultCacheLocation locationA, CallSiteResultCacheLocation locationB)
		{
			return (CallSiteResultCacheLocation)Math.Max((int)locationA, (int)locationB);
		}

		private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (serviceType == descriptor.ServiceType)
			{
				ServiceCacheKey key = new ServiceCacheKey(serviceType, slot);
				if (_callSiteCache.TryGetValue(key, out var value))
				{
					return value;
				}
				ResultCache resultCache = new ResultCache(descriptor.Lifetime, serviceType, slot);
				ServiceCallSite serviceCallSite;
				if (descriptor.ImplementationInstance != null)
				{
					serviceCallSite = new ConstantCallSite(descriptor.ServiceType, descriptor.ImplementationInstance);
				}
				else if (descriptor.ImplementationFactory != null)
				{
					serviceCallSite = new FactoryCallSite(resultCache, descriptor.ServiceType, descriptor.ImplementationFactory);
				}
				else
				{
					if (!(descriptor.ImplementationType != null))
					{
						throw new InvalidOperationException(System.SR.InvalidServiceDescriptor);
					}
					serviceCallSite = CreateConstructorCallSite(resultCache, descriptor.ServiceType, descriptor.ImplementationType, callSiteChain);
				}
				return _callSiteCache[key] = serviceCallSite;
			}
			return null;
		}

		[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:MakeGenericType", Justification = "MakeGenericType here is used to create a closed generic implementation type given the closed service type. Trimming annotations on the generic types are verified when 'Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability' is set, which is set by default when PublishTrimmed=true. That check informs developers when these generic types don't have compatible trimming annotations.")]
		private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() == descriptor.ServiceType)
			{
				ServiceCacheKey key = new ServiceCacheKey(serviceType, slot);
				if (_callSiteCache.TryGetValue(key, out var value))
				{
					return value;
				}
				ResultCache lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot);
				Type implementationType;
				try
				{
					implementationType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments);
				}
				catch (ArgumentException)
				{
					if (throwOnConstraintViolation)
					{
						throw;
					}
					return null;
				}
				return _callSiteCache[key] = CreateConstructorCallSite(lifetime, serviceType, implementationType, callSiteChain);
			}
			return null;
		}

		private ServiceCallSite CreateConstructorCallSite(ResultCache lifetime, Type serviceType, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, CallSiteChain callSiteChain)
		{
			try
			{
				callSiteChain.Add(serviceType, implementationType);
				ConstructorInfo[] constructors = implementationType.GetConstructors();
				ServiceCallSite[] parameterCallSites = null;
				if (constructors.Length == 0)
				{
					throw new InvalidOperationException(System.SR.Format(System.SR.NoConstructorMatch, implementationType));
				}
				if (constructors.Length == 1)
				{
					ConstructorInfo constructorInfo = constructors[0];
					ParameterInfo[] parameters = constructorInfo.GetParameters();
					if (parameters.Length == 0)
					{
						return new ConstructorCallSite(lifetime, serviceType, constructorInfo);
					}
					parameterCallSites = CreateArgumentCallSites(implementationType, callSiteChain, parameters, throwIfCallSiteNotFound: true);
					return new ConstructorCallSite(lifetime, serviceType, constructorInfo, parameterCallSites);
				}
				Array.Sort(constructors, (ConstructorInfo a, ConstructorInfo b) => b.GetParameters().Length.CompareTo(a.GetParameters().Length));
				ConstructorInfo constructorInfo2 = null;
				HashSet<Type> hashSet = null;
				for (int i = 0; i < constructors.Length; i++)
				{
					ParameterInfo[] parameters2 = constructors[i].GetParameters();
					ServiceCallSite[] array = CreateArgumentCallSites(implementationType, callSiteChain, parameters2, throwIfCallSiteNotFound: false);
					if (array == null)
					{
						continue;
					}
					if (constructorInfo2 == null)
					{
						constructorInfo2 = constructors[i];
						parameterCallSites = array;
						continue;
					}
					if (hashSet == null)
					{
						hashSet = new HashSet<Type>();
						ParameterInfo[] parameters3 = constructorInfo2.GetParameters();
						foreach (ParameterInfo parameterInfo in parameters3)
						{
							hashSet.Add(parameterInfo.ParameterType);
						}
					}
					ParameterInfo[] array2 = parameters2;
					foreach (ParameterInfo parameterInfo2 in array2)
					{
						if (!hashSet.Contains(parameterInfo2.ParameterType))
						{
							throw new InvalidOperationException(string.Join(Environment.NewLine, System.SR.Format(System.SR.AmbiguousConstructorException, implementationType), constructorInfo2, constructors[i]));
						}
					}
				}
				if (constructorInfo2 == null)
				{
					throw new InvalidOperationException(System.SR.Format(System.SR.UnableToActivateTypeException, implementationType));
				}
				return new ConstructorCallSite(lifetime, serviceType, constructorInfo2, parameterCallSites);
			}
			finally
			{
				callSiteChain.Remove(serviceType);
			}
		}

		private ServiceCallSite[] CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
		{
			ServiceCallSite[] array = new ServiceCallSite[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				ServiceCallSite serviceCallSite = GetCallSite(parameterType, callSiteChain);
				if (serviceCallSite == null && ParameterDefaultValue.TryGetDefaultValue(parameters[i], out object defaultValue))
				{
					serviceCallSite = new ConstantCallSite(parameterType, defaultValue);
				}
				if (serviceCallSite == null)
				{
					if (throwIfCallSiteNotFound)
					{
						throw new InvalidOperationException(System.SR.Format(System.SR.CannotResolveService, parameterType, implementationType));
					}
					return null;
				}
				array[i] = serviceCallSite;
			}
			return array;
		}

		public void Add(Type type, ServiceCallSite serviceCallSite)
		{
			_callSiteCache[new ServiceCacheKey(type, 0)] = serviceCallSite;
		}

		public bool IsService(Type serviceType)
		{
			if ((object)serviceType == null)
			{
				throw new ArgumentNullException("serviceType");
			}
			if (serviceType.IsGenericTypeDefinition)
			{
				return false;
			}
			if (_descriptorLookup.ContainsKey(serviceType))
			{
				return true;
			}
			if (serviceType.IsConstructedGenericType)
			{
				Type genericTypeDefinition = serviceType.GetGenericTypeDefinition();
				if ((object)genericTypeDefinition != null)
				{
					if (!(genericTypeDefinition == typeof(IEnumerable<>)))
					{
						return _descriptorLookup.ContainsKey(genericTypeDefinition);
					}
					return true;
				}
			}
			if (!(serviceType == typeof(IServiceProvider)) && !(serviceType == typeof(IServiceScopeFactory)))
			{
				return serviceType == typeof(IServiceProviderIsService);
			}
			return true;
		}
	}
	internal enum CallSiteKind
	{
		Factory,
		Constructor,
		Constant,
		IEnumerable,
		ServiceProvider,
		Scope,
		Transient,
		Singleton
	}
	internal enum CallSiteResultCacheLocation
	{
		Root,
		Scope,
		Dispose,
		None
	}
	internal sealed class CallSiteRuntimeResolver : CallSiteVisitor<RuntimeResolverContext, object>
	{
		public static CallSiteRuntimeResolver Instance { get; } = new CallSiteRuntimeResolver();


		private CallSiteRuntimeResolver()
		{
		}

		public object Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
		{
			if (scope.IsRootScope)
			{
				object value = callSite.Value;
				if (value != null)
				{
					return value;
				}
			}
			return VisitCallSite(callSite, new RuntimeResolverContext
			{
				Scope = scope
			});
		}

		protected override object VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
		{
			return context.Scope.CaptureDisposable(VisitCallSiteMain(transientCallSite, context));
		}

		protected override object VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
		{
			object[] array;
			if (constructorCallSite.ParameterCallSites.Length == 0)
			{
				array = Array.Empty<object>();
			}
			else
			{
				array = new object[constructorCallSite.ParameterCallSites.Length];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = VisitCallSite(constructorCallSite.ParameterCallSites[i], context);
				}
			}
			try
			{
				return constructorCallSite.ConstructorInfo.Invoke(array);
			}
			catch (Exception ex) when (ex.InnerException != null)
			{
				ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
				throw;
			}
		}

		protected override object VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
		{
			object value = callSite.Value;
			if (value != null)
			{
				return value;
			}
			RuntimeResolverLock runtimeResolverLock = RuntimeResolverLock.Root;
			ServiceProviderEngineScope root = context.Scope.RootProvider.Root;
			lock (callSite)
			{
				object value2 = callSite.Value;
				if (value2 != null)
				{
					return value2;
				}
				value2 = VisitCallSiteMain(callSite, new RuntimeResolverContext
				{
					Scope = root,
					AcquiredLocks = (context.AcquiredLocks | runtimeResolverLock)
				});
				root.CaptureDisposable(value2);
				callSite.Value = value2;
				return value2;
			}
		}

		protected override object VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
		{
			if (!context.Scope.IsRootScope)
			{
				return VisitCache(callSite, context, context.Scope, RuntimeResolverLock.Scope);
			}
			return VisitRootCache(callSite, context);
		}

		private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
		{
			bool lockTaken = false;
			object sync = serviceProviderEngine.Sync;
			Dictionary<ServiceCacheKey, object> resolvedServices = serviceProviderEngine.ResolvedServices;
			if ((context.AcquiredLocks & lockType) == 0)
			{
				Monitor.Enter(sync, ref lockTaken);
			}
			try
			{
				if (resolvedServices.TryGetValue(callSite.Cache.Key, out var value))
				{
					return value;
				}
				value = VisitCallSiteMain(callSite, new RuntimeResolverContext
				{
					Scope = serviceProviderEngine,
					AcquiredLocks = (context.AcquiredLocks | lockType)
				});
				serviceProviderEngine.CaptureDisposable(value);
				resolvedServices.Add(callSite.Cache.Key, value);
				return value;
			}
			finally
			{
				if (lockTaken)
				{
					Monitor.Exit(sync);
				}
			}
		}

		protected override object VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context)
		{
			return constantCallSite.DefaultValue;
		}

		protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, RuntimeResolverContext context)
		{
			return context.Scope;
		}

		protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
		{
			Array array = Array.CreateInstance(enumerableCallSite.ItemType, enumerableCallSite.ServiceCallSites.Length);
			for (int i = 0; i < enumerableCallSite.ServiceCallSites.Length; i++)
			{
				object value = VisitCallSite(enumerableCallSite.ServiceCallSites[i], context);
				array.SetValue(value, i);
			}
			return array;
		}

		protected override object VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
		{
			return factoryCallSite.Factory(context.Scope);
		}
	}
	internal struct RuntimeResolverContext
	{
		public ServiceProviderEngineScope Scope { get; set; }

		public RuntimeResolverLock AcquiredLocks { get; set; }
	}
	[Flags]
	internal enum RuntimeResolverLock
	{
		Scope = 1,
		Root = 2
	}
	internal sealed class CallSiteValidator : CallSiteVisitor<CallSiteValidator.CallSiteValidatorState, Type>
	{
		internal struct CallSiteValidatorState
		{
			public ServiceCallSite Singleton { get; set; }
		}

		private readonly ConcurrentDictionary<Type, Type> _scopedServices = new ConcurrentDictionary<Type, Type>();

		public void ValidateCallSite(ServiceCallSite callSite)
		{
			Type type = VisitCallSite(callSite, default(CallSiteValidatorState));
			if (type != null)
			{
				_scopedServices[callSite.ServiceType] = type;
			}
		}

		public void ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
		{
			if (scope == rootScope && _scopedServices.TryGetValue(serviceType, out var value))
			{
				if (serviceType == value)
				{
					throw new InvalidOperationException(System.SR.Format(System.SR.DirectScopedResolvedFromRootException, serviceType, "Scoped".ToLowerInvariant()));
				}
				throw new InvalidOperationException(System.SR.Format(System.SR.ScopedResolvedFromRootException, serviceType, value, "Scoped".ToLowerInvariant()));
			}
		}

		protected override Type VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
		{
			Type type = null;
			ServiceCallSite[] parameterCallSites = constructorCallSite.ParameterCallSites;
			foreach (ServiceCallSite callSite in parameterCallSites)
			{
				Type type2 = VisitCallSite(callSite, state);
				if (type == null)
				{
					type = type2;
				}
			}
			return type;
		}

		protected override Type VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteValidatorState state)
		{
			Type type = null;
			ServiceCallSite[] serviceCallSites = enumerableCallSite.ServiceCallSites;
			foreach (ServiceCallSite callSite in serviceCallSites)
			{
				Type type2 = VisitCallSite(callSite, state);
				if (type == null)
				{
					type = type2;
				}
			}
			return type;
		}

		protected override Type VisitRootCache(ServiceCallSite singletonCallSite, CallSiteValidatorState state)
		{
			state.Singleton = singletonCallSite;
			return VisitCallSiteMain(singletonCallSite, state);
		}

		protected override Type VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state)
		{
			if (scopedCallSite.ServiceType == typeof(IServiceScopeFactory))
			{
				return null;
			}
			if (state.Singleton != null)
			{
				throw new InvalidOperationException(System.SR.Format(System.SR.ScopedInSingletonException, scopedCallSite.ServiceType, state.Singleton.ServiceType, "Scoped".ToLowerInvariant(), "Singleton".ToLowerInvariant()));
			}
			VisitCallSiteMain(scopedCallSite, state);
			return scopedCallSite.ServiceType;
		}

		protected override Type VisitConstant(ConstantCallSite constantCallSite, CallSiteValidatorState state)
		{
			return null;
		}

		protected override Type VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteValidatorState state)
		{
			return null;
		}

		protected override Type VisitFactory(FactoryCallSite factoryCallSite, CallSiteValidatorState state)
		{
			return null;
		}
	}
	internal abstract class CallSiteVisitor<TArgument, TResult>
	{
		private readonly StackGuard _stackGuard;

		protected CallSiteVisitor()
		{
			_stackGuard = new StackGuard();
		}

		protected virtual TResult VisitCallSite(ServiceCallSite callSite, TArgument argument)
		{
			if (!_stackGuard.TryEnterOnCurrentStack())
			{
				return _stackGuard.RunOnEmptyStack((ServiceCallSite c, TArgument a) => VisitCallSite(c, a), callSite, argument);
			}
			return callSite.Cache.Location switch
			{
				CallSiteResultCacheLocation.Root => VisitRootCache(callSite, argument), 
				CallSiteResultCacheLocation.Scope => VisitScopeCache(callSite, argument), 
				CallSiteResultCacheLocation.Dispose => VisitDisposeCache(callSite, argument), 
				CallSiteResultCacheLocation.None => VisitNoCache(callSite, argument), 
				_ => throw new ArgumentOutOfRangeException(), 
			};
		}

		protected virtual TResult VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
		{
			return callSite.Kind switch
			{
				CallSiteKind.Factory => VisitFactory((FactoryCallSite)callSite, argument), 
				CallSiteKind.IEnumerable => VisitIEnumerable((IEnumerableCallSite)callSite, argument), 
				CallSiteKind.Constructor => VisitConstructor((ConstructorCallSite)callSite, argument), 
				CallSiteKind.Constant => VisitConstant((ConstantCallSite)callSite, argument), 
				CallSiteKind.ServiceProvider => VisitServiceProvider((ServiceProviderCallSite)callSite, argument), 
				_ => throw new NotSupportedException(System.SR.Format(System.SR.CallSiteTypeNotSupported, callSite.GetType())), 
			};
		}

		protected virtual TResult VisitNoCache(ServiceCallSite callSite, TArgument argument)
		{
			return VisitCallSiteMain(callSite, argument);
		}

		protected virtual TResult VisitDisposeCache(ServiceCallSite callSite, TArgument argument)
		{
			return VisitCallSiteMain(callSite, argument);
		}

		protected virtual TResult VisitRootCache(ServiceCallSite callSite, TArgument argument)
		{
			return VisitCallSiteMain(callSite, argument);
		}

		protected virtual TResult VisitScopeCache(ServiceCallSite callSite, TArgument argument)
		{
			return VisitCallSiteMain(callSite, argument);
		}

		protected abstract TResult VisitConstructor(ConstructorCallSite constructorCallSite, TArgument argument);

		protected abstract TResult VisitConstant(ConstantCallSite constantCallSite, TArgument argument);

		protected abstract TResult VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, TArgument argument);

		protected abstract TResult VisitIEnumerable(IEnumerableCallSite enumerableCallSite, TArgument argument);

		protected abstract TResult VisitFactory(FactoryCallSite factoryCallSite, TArgument argument);
	}
	internal abstract class CompiledServiceProviderEngine : ServiceProviderEngine
	{
		public ILEmitResolverBuilder ResolverBuilder { get; }

		public CompiledServiceProviderEngine(ServiceProvider provider)
		{
			ResolverBuilder = new ILEmitResolverBuilder(provider);
		}

		public override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
		{
			return ResolverBuilder.Build(callSite);
		}
	}
	internal sealed class ConstantCallSite : ServiceCallSite
	{
		private readonly Type _serviceType;

		internal object DefaultValue => base.Value;

		public override Type ServiceType => _serviceType;

		public override Type ImplementationType => DefaultValue?.GetType() ?? _serviceType;

		public override CallSiteKind Kind { get; } = CallSiteKind.Constant;


		public ConstantCallSite(Type serviceType, object defaultValue)
			: base(ResultCache.None)
		{
			_serviceType = serviceType ?? throw new ArgumentNullException("serviceType");
			if (defaultValue != null && !serviceType.IsInstanceOfType(defaultValue))
			{
				throw new ArgumentException(System.SR.Format(System.SR.ConstantCantBeConvertedToServiceType, defaultValue.GetType(), serviceType));
			}
			base.Value = defaultValue;
		}
	}
	internal sealed class ConstructorCallSite : ServiceCallSite
	{
		internal ConstructorInfo ConstructorInfo { get; }

		internal ServiceCallSite[] ParameterCallSites { get; }

		public override Type ServiceType { get; }

		public override Type ImplementationType => ConstructorInfo.DeclaringType;

		public override CallSiteKind Kind { get; } = CallSiteKind.Constructor;


		public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo)
			: this(cache, serviceType, constructorInfo, Array.Empty<ServiceCallSite>())
		{
		}

		public ConstructorCallSite(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites)
			: base(cache)
		{
			if (!serviceType.IsAssignableFrom(constructorInfo.DeclaringType))
			{
				throw new ArgumentException(System.SR.Format(System.SR.ImplementationTypeCantBeConvertedToServiceType, constructorInfo.DeclaringType, serviceType));
			}
			ServiceType = serviceType;
			ConstructorInfo = constructorInfo;
			ParameterCallSites = parameterCallSites;
		}
	}
	internal sealed class DynamicServiceProviderEngine : CompiledServiceProviderEngine
	{
		private readonly ServiceProvider _serviceProvider;

		public DynamicServiceProviderEngine(ServiceProvider serviceProvider)
			: base(serviceProvider)
		{
			_serviceProvider = serviceProvider;
		}

		public override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
		{
			ServiceCallSite callSite2 = callSite;
			int callCount = 0;
			return delegate(ServiceProviderEngineScope scope)
			{
				object result = CallSiteRuntimeResolver.Instance.Resolve(callSite2, scope);
				if (Interlocked.Increment(ref callCount) == 2)
				{
					ThreadPool.UnsafeQueueUserWorkItem(delegate
					{
						try
						{
							_serviceProvider.ReplaceServiceAccessor(callSite2, base.RealizeService(callSite2));
						}
						catch (Exception exception)
						{
							DependencyInjectionEventSource.Log.ServiceRealizationFailed(exception, _serviceProvider.GetHashCode());
						}
					}, null);
				}
				return result;
			};
		}
	}
	internal sealed class ExpressionResolverBuilder : CallSiteVisitor<object, Expression>
	{
		private static readonly ParameterExpression ScopeParameter = Expression.Parameter(typeof(ServiceProviderEngineScope));

		private static readonly ParameterExpression ResolvedServices = Expression.Variable(typeof(IDictionary<ServiceCacheKey, object>), ScopeParameter.Name + "resolvedServices");

		private static readonly ParameterExpression Sync = Expression.Variable(typeof(object), ScopeParameter.Name + "sync");

		private static readonly BinaryExpression ResolvedServicesVariableAssignment = Expression.Assign(ResolvedServices, Expression.Property(ScopeParameter, typeof(ServiceProviderEngineScope).GetProperty("ResolvedServices", BindingFlags.Instance | BindingFlags.NonPublic)));

		private static readonly BinaryExpression SyncVariableAssignment = Expression.Assign(Sync, Expression.Property(ScopeParameter, typeof(ServiceProviderEngineScope).GetProperty("Sync", BindingFlags.Instance | BindingFlags.NonPublic)));

		private static readonly ParameterExpression CaptureDisposableParameter = Expression.Parameter(typeof(object));

		private static readonly LambdaExpression CaptureDisposable = Expression.Lambda(Expression.Call(ScopeParameter, ServiceLookupHelpers.CaptureDisposableMethodInfo, CaptureDisposableParameter), CaptureDisposableParameter);

		private static readonly ConstantExpression CallSiteRuntimeResolverInstanceExpression = Expression.Constant(CallSiteRuntimeResolver.Instance, typeof(CallSiteRuntimeResolver));

		private readonly ServiceProviderEngineScope _rootScope;

		private readonly ConcurrentDictionary<ServiceCacheKey, Func<ServiceProviderEngineScope, object>> _scopeResolverCache;

		private readonly Func<ServiceCacheKey, ServiceCallSite, Func<ServiceProviderEngineScope, object>> _buildTypeDelegate;

		public ExpressionResolverBuilder(ServiceProvider serviceProvider)
		{
			_rootScope = serviceProvider.Root;
			_scopeResolverCache = new ConcurrentDictionary<ServiceCacheKey, Func<ServiceProviderEngineScope, object>>();
			_buildTypeDelegate = (ServiceCacheKey key, ServiceCallSite cs) => BuildNoCache(cs);
		}

		public Func<ServiceProviderEngineScope, object> Build(ServiceCallSite callSite)
		{
			ServiceCallSite callSite2 = callSite;
			if (callSite2.Cache.Location == CallSiteResultCacheLocation.Scope)
			{
				return _scopeResolverCache.GetOrAdd(callSite2.Cache.Key, (ServiceCacheKey key) => _buildTypeDelegate(key, callSite2));
			}
			return BuildNoCache(callSite2);
		}

		public Func<ServiceProviderEngineScope, object> BuildNoCache(ServiceCallSite callSite)
		{
			Expression<Func<ServiceProviderEngineScope, object>> expression = BuildExpression(callSite);
			DependencyInjectionEventSource.Log.ExpressionTreeGenerated(_rootScope.RootProvider, callSite.ServiceType, expression);
			return expression.Compile();
		}

		private Expression<Func<ServiceProviderEngineScope, object>> BuildExpression(ServiceCallSite callSite)
		{
			if (callSite.Cache.Location == CallSiteResultCacheLocation.Scope)
			{
				return Expression.Lambda<Func<ServiceProviderEngineScope, object>>(Expression.Block(new ParameterExpression[2] { ResolvedServices, Sync }, ResolvedServicesVariableAssignment, SyncVariableAssignment, BuildScopedExpression(callSite)), new ParameterExpression[1] { ScopeParameter });
			}
			return Expression.Lambda<Func<ServiceProviderEngineScope, object>>(Convert(VisitCallSite(callSite, null), typeof(object), forceValueTypeConversion: true), new ParameterExpression[1] { ScopeParameter });
		}

		protected override Expression VisitRootCache(ServiceCallSite singletonCallSite, object context)
		{
			return Expression.Constant(CallSiteRuntimeResolver.Instance.Resolve(singletonCallSite, _rootScope));
		}

		protected override Expression VisitConstant(ConstantCallSite constantCallSite, object context)
		{
			return Expression.Constant(constantCallSite.DefaultValue);
		}

		protected override Expression VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, object context)
		{
			return ScopeParameter;
		}

		protected override Expression VisitFactory(FactoryCallSite factoryCallSite, object context)
		{
			return Expression.Invoke(Expression.Constant(factoryCallSite.Factory), ScopeParameter);
		}

		protected override Expression VisitIEnumerable(IEnumerableCallSite callSite, object context)
		{
			object context2 = context;
			IEnumerableCallSite callSite2 = callSite;
			if (callSite2.ServiceCallSites.Length == 0)
			{
				return Expression.Constant(ServiceLookupHelpers.GetArrayEmptyMethodInfo(callSite2.ItemType).Invoke(null, Array.Empty<object>()));
			}
			return Expression.NewArrayInit(callSite2.ItemType, callSite2.ServiceCallSites.Select((ServiceCallSite cs) => Convert(VisitCallSite(cs, context2), callSite2.ItemType)));
		}

		protected override Expression VisitDisposeCache(ServiceCallSite callSite, object context)
		{
			return TryCaptureDisposable(callSite, ScopeParameter, VisitCallSiteMain(callSite, context));
		}

		private Expression TryCaptureDisposable(ServiceCallSite callSite, ParameterExpression scope, Expression service)
		{
			if (!callSite.CaptureDisposable)
			{
				return service;
			}
			return Expression.Invoke(GetCaptureDisposable(scope), service);
		}

		protected override Expression VisitConstructor(ConstructorCallSite callSite, object context)
		{
			ParameterInfo[] parameters = callSite.ConstructorInfo.GetParameters();
			Expression[] array;
			if (callSite.ParameterCallSites.Length == 0)
			{
				array = Array.Empty<Expression>();
			}
			else
			{
				array = new Expression[callSite.ParameterCallSites.Length];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = Convert(VisitCallSite(callSite.ParameterCallSites[i], context), parameters[i].ParameterType);
				}
			}
			return Expression.New(callSite.ConstructorInfo, array);
		}

		private static Expression Convert(Expression expression, Type type, bool forceValueTypeConversion = false)
		{
			if (type.IsAssignableFrom(expression.Type) && (!expression.Type.IsValueType || !forceValueTypeConversion))
			{
				return expression;
			}
			return Expression.Convert(expression, type);
		}

		protected override Expression VisitScopeCache(ServiceCallSite callSite, object context)
		{
			Func<ServiceProviderEngineScope, object> value = Build(callSite);
			return Expression.Invoke(Expression.Constant(value), ScopeParameter);
		}

		private Expression BuildScopedExpression(ServiceCallSite callSite)
		{
			ConstantExpression arg = Expression.Constant(callSite, typeof(ServiceCallSite));
			MethodCallExpression ifTrue = Expression.Call(CallSiteRuntimeResolverInstanceExpression, ServiceLookupHelpers.ResolveCallSiteAndScopeMethodInfo, arg, ScopeParameter);
			ConstantExpression arg2 = Expression.Constant(callSite.Cache.Key, typeof(ServiceCacheKey));
			ParameterExpression parameterExpression = Expression.Variable(typeof(object), "resolved");
			ParameterExpression resolvedServices = ResolvedServices;
			MethodCallExpression expression = Expression.Call(resolvedServices, ServiceLookupHelpers.TryGetValueMethodInfo, arg2, parameterExpression);
			Expression right = TryCaptureDisposable(callSite, ScopeParameter, VisitCallSiteMain(callSite, null));
			BinaryExpression arg3 = Expression.Assign(parameterExpression, right);
			MethodCallExpression arg4 = Expression.Call(resolvedServices, ServiceLookupHelpers.AddMethodInfo, arg2, parameterExpression);
			BlockExpression arg5 = Expression.Block(typeof(object), new ParameterExpression[1] { parameterExpression }, Expression.IfThen(Expression.Not(expression), Expression.Block(arg3, arg4)), parameterExpression);
			ParameterExpression parameterExpression2 = Expression.Variable(typeof(bool), "lockWasTaken");
			ParameterExpression sync = Sync;
			MethodCallExpression arg6 = Expression.Call(ServiceLookupHelpers.MonitorEnterMethodInfo, sync, parameterExpression2);
			MethodCallExpression ifTrue2 = Expression.Call(ServiceLookupHelpers.MonitorExitMethodInfo, sync);
			BlockExpression body = Expression.Block(arg6, arg5);
			ConditionalExpression @finally = Expression.IfThen(parameterExpression2, ifTrue2);
			return Expression.Condition(Expression.Property(ScopeParameter, typeof(ServiceProviderEngineScope).GetProperty("IsRootScope", BindingFlags.Instance | BindingFlags.Public)), ifTrue, Expression.Block(typeof(object), new ParameterExpression[1] { parameterExpression2 }, Expression.TryFinally(body, @finally)));
		}

		public Expression GetCaptureDisposable(ParameterExpression scope)
		{
			if (scope != ScopeParameter)
			{
				throw new NotSupportedException(System.SR.GetCaptureDisposableNotSupported);
			}
			return CaptureDisposable;
		}
	}
	internal sealed class ExpressionsServiceProviderEngine : ServiceProviderEngine
	{
		private readonly ExpressionResolverBuilder _expressionResolverBuilder;

		public ExpressionsServiceProviderEngine(ServiceProvider serviceProvider)
		{
			_expressionResolverBuilder = new ExpressionResolverBuilder(serviceProvider);
		}

		public override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
		{
			return _expressionResolverBuilder.Build(callSite);
		}
	}
	internal sealed class FactoryCallSite : ServiceCallSite
	{
		public Func<IServiceProvider, object> Factory { get; }

		public override Type ServiceType { get; }

		public override Type ImplementationType => null;

		public override CallSiteKind Kind { get; }

		public FactoryCallSite(ResultCache cache, Type serviceType, Func<IServiceProvider, object> factory)
			: base(cache)
		{
			Factory = factory;
			ServiceType = serviceType;
		}
	}
	internal sealed class IEnumerableCallSite : ServiceCallSite
	{
		internal Type ItemType { get; }

		internal ServiceCallSite[] ServiceCallSites { get; }

		public override Type ServiceType => typeof(IEnumerable<>).MakeGenericType(ItemType);

		public override Type ImplementationType => ItemType.MakeArrayType();

		public override CallSiteKind Kind { get; } = CallSiteKind.IEnumerable;


		public IEnumerableCallSite(ResultCache cache, Type itemType, ServiceCallSite[] serviceCallSites)
			: base(cache)
		{
			ItemType = itemType;
			ServiceCallSites = serviceCallSites;
		}
	}
	internal struct ResultCache
	{
		public static ResultCache None { get; } = new ResultCache(CallSiteResultCacheLocation.None, ServiceCacheKey.Empty);


		public CallSiteResultCacheLocation Location { get; set; }

		public ServiceCacheKey Key { get; set; }

		internal ResultCache(CallSiteResultCacheLocation lifetime, ServiceCacheKey cacheKey)
		{
			Location = lifetime;
			Key = cacheKey;
		}

		public ResultCache(ServiceLifetime lifetime, Type type, int slot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			switch ((int)lifetime)
			{
			case 0:
				Location = CallSiteResultCacheLocation.Root;
				break;
			case 1:
				Location = CallSiteResultCacheLocation.Scope;
				break;
			case 2:
				Location = CallSiteResultCacheLocation.Dispose;
				break;
			default:
				Location = CallSiteResultCacheLocation.None;
				break;
			}
			Key = new ServiceCacheKey(type, slot);
		}
	}
	internal sealed class RuntimeServiceProviderEngine : ServiceProviderEngine
	{
		public static RuntimeServiceProviderEngine Instance { get; } = new RuntimeServiceProviderEngine();


		private RuntimeServiceProviderEngine()
		{
		}

		public override Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite)
		{
			ServiceCallSite callSite2 = callSite;
			return (ServiceProviderEngineScope scope) => CallSiteRuntimeResolver.Instance.Resolve(callSite2, scope);
		}
	}
	internal readonly struct ServiceCacheKey : IEquatable<ServiceCacheKey>
	{
		public static ServiceCacheKey Empty { get; } = new ServiceCacheKey(null, 0);


		public Type Type { get; }

		public int Slot { get; }

		public ServiceCacheKey(Type type, int slot)
		{
			Type = type;
			Slot = slot;
		}

		public bool Equals(ServiceCacheKey other)
		{
			if (Type == other.Type)
			{
				return Slot == other.Slot;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((Type?.GetHashCode() ?? 23) * 397) ^ Slot;
		}
	}
	internal abstract class ServiceCallSite
	{
		public abstract Type ServiceType { get; }

		public abstract Type ImplementationType { get; }

		public abstract CallSiteKind Kind { get; }

		public ResultCache Cache { get; }

		public object Value { get; set; }

		public bool CaptureDisposable
		{
			get
			{
				if (!(ImplementationType == null) && !typeof(IDisposable).IsAssignableFrom(ImplementationType))
				{
					return typeof(IAsyncDisposable).IsAssignableFrom(ImplementationType);
				}
				return true;
			}
		}

		protected ServiceCallSite(ResultCache cache)
		{
			Cache = cache;
		}
	}
	internal static class ServiceLookupHelpers
	{
		private const BindingFlags LookupFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly MethodInfo ArrayEmptyMethodInfo = typeof(Array).GetMethod("Empty");

		internal static readonly MethodInfo InvokeFactoryMethodInfo = typeof(Func<IServiceProvider, object>).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly MethodInfo CaptureDisposableMethodInfo = typeof(ServiceProviderEngineScope).GetMethod("CaptureDisposable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly MethodInfo TryGetValueMethodInfo = typeof(IDictionary<ServiceCacheKey, object>).GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly MethodInfo ResolveCallSiteAndScopeMethodInfo = typeof(CallSiteRuntimeResolver).GetMethod("Resolve", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly MethodInfo AddMethodInfo = typeof(IDictionary<ServiceCacheKey, object>).GetMethod("Add", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly MethodInfo MonitorEnterMethodInfo = typeof(Monitor).GetMethod("Enter", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
		{
			typeof(object),
			typeof(bool).MakeByRefType()
		}, null);

		internal static readonly MethodInfo MonitorExitMethodInfo = typeof(Monitor).GetMethod("Exit", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(object) }, null);

		[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "Calling Array.Empty<T>() is safe since the T doesn't have trimming annotations.")]
		internal static MethodInfo GetArrayEmptyMethodInfo(Type itemType)
		{
			return ArrayEmptyMethodInfo.MakeGenericMethod(itemType);
		}
	}
	internal sealed class ServiceProviderCallSite : ServiceCallSite
	{
		public override Type ServiceType { get; } = typeof(IServiceProvider);


		public override Type ImplementationType { get; } = typeof(ServiceProvider);


		public override CallSiteKind Kind { get; } = CallSiteKind.ServiceProvider;


		public ServiceProviderCallSite()
			: base(ResultCache.None)
		{
		}
	}
	internal abstract class ServiceProviderEngine
	{
		public abstract Func<ServiceProviderEngineScope, object> RealizeService(ServiceCallSite callSite);
	}
	internal sealed class ServiceProviderEngineScope : IServiceScope, IDisposable, IServiceProvider, IAsyncDisposable, IServiceScopeFactory
	{
		private bool _disposed;

		private List<object> _disposables;

		internal IList<object> Disposables
		{
			get
			{
				IList<object> disposables = _disposables;
				return disposables ?? Array.Empty<object>();
			}
		}

		internal Dictionary<ServiceCacheKey, object> ResolvedServices { get; }

		internal object Sync => ResolvedServices;

		public bool IsRootScope { get; }

		internal ServiceProvider RootProvider { get; }

		public IServiceProvider ServiceProvider => this;

		public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope)
		{
			ResolvedServices = new Dictionary<ServiceCacheKey, object>();
			RootProvider = provider;
			IsRootScope = isRootScope;
		}

		public object GetService(Type serviceType)
		{
			if (_disposed)
			{
				ThrowHelper.ThrowObjectDisposedException();
			}
			return RootProvider.GetService(serviceType, this);
		}

		public IServiceScope CreateScope()
		{
			return RootProvider.CreateScope();
		}

		internal object CaptureDisposable(object service)
		{
			object service2 = service;
			if (this == service2 || (!(service2 is IDisposable) && !(service2 is IAsyncDisposable)))
			{
				return service2;
			}
			bool flag = false;
			lock (Sync)
			{
				if (_disposed)
				{
					flag = true;
				}
				else
				{
					if (_disposables == null)
					{
						_disposables = new List<object>();
					}
					_disposables.Add(service2);
				}
			}
			if (flag)
			{
				if (service2 is IDisposable disposable)
				{
					disposable.Dispose();
				}
				else
				{
					Task.Run(() => ((IAsyncDisposable)service2).DisposeAsync().AsTask()).GetAwaiter().GetResult();
				}
				ThrowHelper.ThrowObjectDisposedException();
			}
			return service2;
		}

		public void Dispose()
		{
			List<object> list = BeginDispose();
			if (list == null)
			{
				return;
			}
			int num = list.Count - 1;
			while (num >= 0)
			{
				if (list[num] is IDisposable disposable)
				{
					disposable.Dispose();
					num--;
					continue;
				}
				throw new InvalidOperationException(System.SR.Format(System.SR.AsyncDisposableServiceDispose, TypeNameHelper.GetTypeDisplayName(list[num])));
			}
		}

		public ValueTask DisposeAsync()
		{
			List<object> list = BeginDispose();
			if (list != null)
			{
				try
				{
					for (int num = list.Count - 1; num >= 0; num--)
					{
						object obj = list[num];
						if (obj is IAsyncDisposable asyncDisposable)
						{
							ValueTask vt2 = asyncDisposable.DisposeAsync();
							if (!vt2.IsCompletedSuccessfully)
							{
								return Await(num, vt2, list);
							}
							vt2.GetAwaiter().GetResult();
						}
						else
						{
							((IDisposable)obj).Dispose();
						}
					}
				}
				catch (Exception exception)
				{
					return new ValueTask(Task.FromException(exception));
				}
			}
			return default(ValueTask);
			static async ValueTask Await(int i, ValueTask vt, List<object> toDispose)
			{
				await vt.ConfigureAwait(continueOnCapturedContext: false);
				i--;
				while (i >= 0)
				{
					object obj2 = toDispose[i];
					if (obj2 is IAsyncDisposable asyncDisposable2)
					{
						await asyncDisposable2.DisposeAsync().ConfigureAwait(continueOnCapturedContext: false);
					}
					else
					{
						((IDisposable)obj2).Dispose();
					}
					i--;
				}
			}
		}

		private List<object> BeginDispose()
		{
			lock (Sync)
			{
				if (_disposed)
				{
					return null;
				}
				DependencyInjectionEventSource.Log.ScopeDisposed(RootProvider.GetHashCode(), ResolvedServices.Count, _disposables?.Count ?? 0);
				_disposed = true;
				return _disposables;
			}
		}
	}
	internal sealed class StackGuard
	{
		private const int MaxExecutionStackCount = 1024;

		private int _executionStackCount;

		public bool TryEnterOnCurrentStack()
		{
			try
			{
				RuntimeHelpers.EnsureSufficientExecutionStack();
				return true;
			}
			catch (InsufficientExecutionStackException)
			{
			}
			if (_executionStackCount < 1024)
			{
				return false;
			}
			throw new InsufficientExecutionStackException();
		}

		public TR RunOnEmptyStack<T1, T2, TR>(Func<T1, T2, TR> action, T1 arg1, T2 arg2)
		{
			return RunOnEmptyStackCore(delegate(object s)
			{
				Tuple<Func<T1, T2, TR>, T1, T2> tuple = (Tuple<Func<T1, T2, TR>, T1, T2>)s;
				return tuple.Item1(tuple.Item2, tuple.Item3);
			}, Tuple.Create(action, arg1, arg2));
		}

		private R RunOnEmptyStackCore<R>(Func<object, R> action, object state)
		{
			_executionStackCount++;
			try
			{
				Task<R> task = Task.Factory.StartNew(action, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
				if (!task.IsCompleted)
				{
					((IAsyncResult)task).AsyncWaitHandle.WaitOne();
				}
				return task.GetAwaiter().GetResult();
			}
			finally
			{
				_executionStackCount--;
			}
		}
	}
	internal static class ThrowHelper
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void ThrowObjectDisposedException()
		{
			throw new ObjectDisposedException("IServiceProvider");
		}
	}
	internal sealed class ILEmitResolverBuilder : CallSiteVisitor<ILEmitResolverBuilderContext, object>
	{
		private sealed class ILEmitResolverBuilderRuntimeContext
		{
			public object[] Constants;

			public Func<IServiceProvider, object>[] Factories;
		}

		private struct GeneratedMethod
		{
			public Func<ServiceProviderEngineScope, object> Lambda;

			public ILEmitResolverBuilderRuntimeContext Context;

			public DynamicMethod DynamicMethod;
		}

		private static readonly MethodInfo ResolvedServicesGetter = typeof(ServiceProviderEngineScope).GetProperty("ResolvedServices", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod;

		private static readonly MethodInfo ScopeLockGetter = typeof(ServiceProviderEngineScope).GetProperty("Sync", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod;

		private static readonly MethodInfo ScopeIsRootScope = typeof(ServiceProviderEngineScope).GetProperty("IsRootScope", BindingFlags.Instance | BindingFlags.Public).GetMethod;

		private static readonly MethodInfo CallSiteRuntimeResolverResolveMethod = typeof(CallSiteRuntimeResolver).GetMethod("Resolve", BindingFlags.Instance | BindingFlags.Public);

		private static readonly MethodInfo CallSiteRuntimeResolverInstanceField = typeof(CallSiteRuntimeResolver).GetProperty("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public).GetMethod;

		private static readonly FieldInfo FactoriesField = typeof(ILEmitResolverBuilderRuntimeContext).GetField("Factories");

		private static readonly FieldInfo ConstantsField = typeof(ILEmitResolverBuilderRuntimeContext).GetField("Constants");

		private static readonly MethodInfo GetTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle");

		private static readonly ConstructorInfo CacheKeyCtor = typeof(ServiceCacheKey).GetConstructors()[0];

		private readonly ServiceProviderEngineScope _rootScope;

		private readonly ConcurrentDictionary<ServiceCacheKey, GeneratedMethod> _scopeResolverCache;

		private readonly Func<ServiceCacheKey, ServiceCallSite, GeneratedMethod> _buildTypeDelegate;

		public ILEmitResolverBuilder(ServiceProvider serviceProvider)
		{
			_rootScope = serviceProvider.Root;
			_scopeResolverCache = new ConcurrentDictionary<ServiceCacheKey, GeneratedMethod>();
			_buildTypeDelegate = (ServiceCacheKey key, ServiceCallSite cs) => BuildTypeNoCache(cs);
		}

		public Func<ServiceProviderEngineScope, object> Build(ServiceCallSite callSite)
		{
			return BuildType(callSite).Lambda;
		}

		private GeneratedMethod BuildType(ServiceCallSite callSite)
		{
			if (callSite.Cache.Location == CallSiteResultCacheLocation.Scope)
			{
				return _scopeResolverCache.GetOrAdd(callSite.Cache.Key, (ServiceCacheKey key) => _buildTypeDelegate(key, callSite));
			}
			return BuildTypeNoCache(callSite);
		}

		private GeneratedMethod BuildTypeNoCache(ServiceCallSite callSite)
		{
			DynamicMethod dynamicMethod = new DynamicMethod("ResolveService", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(object), new Type[2]
			{
				typeof(ILEmitResolverBuilderRuntimeContext),
				typeof(ServiceProviderEngineScope)
			}, GetType(), skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator(512);
			ILEmitResolverBuilderRuntimeContext iLEmitResolverBuilderRuntimeContext = GenerateMethodBody(callSite, iLGenerator);
			DependencyInjectionEventSource.Log.DynamicMethodBuilt(_rootScope.RootProvider, callSite.ServiceType, iLGenerator.ILOffset);
			GeneratedMethod result = default(GeneratedMethod);
			result.Lambda = (Func<ServiceProviderEngineScope, object>)dynamicMethod.CreateDelegate(typeof(Func<ServiceProviderEngineScope, object>), iLEmitResolverBuilderRuntimeContext);
			result.Context = iLEmitResolverBuilderRuntimeContext;
			result.DynamicMethod = dynamicMethod;
			return result;
		}

		protected override object VisitDisposeCache(ServiceCallSite transientCallSite, ILEmitResolverBuilderContext argument)
		{
			if (transientCallSite.CaptureDisposable)
			{
				BeginCaptureDisposable(argument);
				VisitCallSiteMain(transientCallSite, argument);
				EndCaptureDisposable(argument);
			}
			else
			{
				VisitCallSiteMain(transientCallSite, argument);
			}
			return null;
		}

		protected override object VisitConstructor(ConstructorCallSite constructorCallSite, ILEmitResolverBuilderContext argument)
		{
			ServiceCallSite[] parameterCallSites = constructorCallSite.ParameterCallSites;
			foreach (ServiceCallSite serviceCallSite in parameterCallSites)
			{
				VisitCallSite(serviceCallSite, argument);
				if (serviceCallSite.ServiceType.IsValueType)
				{
					argument.Generator.Emit(OpCodes.Unbox_Any, serviceCallSite.ServiceType);
				}
			}
			argument.Generator.Emit(OpCodes.Newobj, constructorCallSite.ConstructorInfo);
			return null;
		}

		protected override object VisitRootCache(ServiceCallSite callSite, ILEmitResolverBuilderContext argument)
		{
			AddConstant(argument, CallSiteRuntimeResolver.Instance.Resolve(callSite, _rootScope));
			return null;
		}

		protected override object VisitScopeCache(ServiceCallSite scopedCallSite, ILEmitResolverBuilderContext argument)
		{
			GeneratedMethod generatedMethod = BuildType(scopedCallSite);
			AddConstant(argument, generatedMethod.Context);
			argument.Generator.Emit(OpCodes.Ldarg_1);
			argument.Generator.Emit(OpCodes.Call, generatedMethod.DynamicMethod);
			return null;
		}

		protected override object VisitConstant(ConstantCallSite constantCallSite, ILEmitResolverBuilderContext argument)
		{
			AddConstant(argument, constantCallSite.DefaultValue);
			return null;
		}

		protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, ILEmitResolverBuilderContext argument)
		{
			argument.Generator.Emit(OpCodes.Ldarg_1);
			return null;
		}

		protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ILEmitResolverBuilderContext argument)
		{
			if (enumerableCallSite.ServiceCallSites.Length == 0)
			{
				argument.Generator.Emit(OpCodes.Call, ServiceLookupHelpers.GetArrayEmptyMethodInfo(enumerableCallSite.ItemType));
			}
			else
			{
				argument.Generator.Emit(OpCodes.Ldc_I4, enumerableCallSite.ServiceCallSites.Length);
				argument.Generator.Emit(OpCodes.Newarr, enumerableCallSite.ItemType);
				for (int i = 0; i < enumerableCallSite.ServiceCallSites.Length; i++)
				{
					argument.Generator.Emit(OpCodes.Dup);
					argument.Generator.Emit(OpCodes.Ldc_I4, i);
					ServiceCallSite serviceCallSite = enumerableCallSite.ServiceCallSites[i];
					VisitCallSite(serviceCallSite, argument);
					if (serviceCallSite.ServiceType.IsValueType)
					{
						argument.Generator.Emit(OpCodes.Unbox_Any, serviceCallSite.ServiceType);
					}
					argument.Generator.Emit(OpCodes.Stelem, enumerableCallSite.ItemType);
				}
			}
			return null;
		}

		protected override object VisitFactory(FactoryCallSite factoryCallSite, ILEmitResolverBuilderContext argument)
		{
			if (argument.Factories == null)
			{
				argument.Factories = new List<Func<IServiceProvider, object>>();
			}
			argument.Generator.Emit(OpCodes.Ldarg_0);
			argument.Generator.Emit(OpCodes.Ldfld, FactoriesField);
			argument.Generator.Emit(OpCodes.Ldc_I4, argument.Factories.Count);
			argument.Generator.Emit(OpCodes.Ldelem, typeof(Func<IServiceProvider, object>));
			argument.Generator.Emit(OpCodes.Ldarg_1);
			argument.Generator.Emit(OpCodes.Call, ServiceLookupHelpers.InvokeFactoryMethodInfo);
			argument.Factories.Add(factoryCallSite.Factory);
			return null;
		}

		private void AddConstant(ILEmitResolverBuilderContext argument, object value)
		{
			if (argument.Constants == null)
			{
				argument.Constants = new List<object>();
			}
			argument.Generator.Emit(OpCodes.Ldarg_0);
			argument.Generator.Emit(OpCodes.Ldfld, ConstantsField);
			argument.Generator.Emit(OpCodes.Ldc_I4, argument.Constants.Count);
			argument.Generator.Emit(OpCodes.Ldelem, typeof(object));
			argument.Constants.Add(value);
		}

		private void AddCacheKey(ILEmitResolverBuilderContext argument, ServiceCacheKey key)
		{
			argument.Generator.Emit(OpCodes.Ldtoken, key.Type);
			argument.Generator.Emit(OpCodes.Call, GetTypeFromHandleMethod);
			argument.Generator.Emit(OpCodes.Ldc_I4, key.Slot);
			argument.Generator.Emit(OpCodes.Newobj, CacheKeyCtor);
		}

		private ILEmitResolverBuilderRuntimeContext GenerateMethodBody(ServiceCallSite callSite, ILGenerator generator)
		{
			ILEmitResolverBuilderContext iLEmitResolverBuilderContext = new ILEmitResolverBuilderContext
			{
				Generator = generator,
				Constants = null,
				Factories = null
			};
			if (callSite.Cache.Location == CallSiteResultCacheLocation.Scope)
			{
				LocalBuilder localBuilder = iLEmitResolverBuilderContext.Generator.DeclareLocal(typeof(ServiceCacheKey));
				LocalBuilder localBuilder2 = iLEmitResolverBuilderContext.Generator.DeclareLocal(typeof(IDictionary<ServiceCacheKey, object>));
				LocalBuilder localBuilder3 = iLEmitResolverBuilderContext.Generator.DeclareLocal(typeof(object));
				LocalBuilder localBuilder4 = iLEmitResolverBuilderContext.Generator.DeclareLocal(typeof(bool));
				LocalBuilder localBuilder5 = iLEmitResolverBuilderContext.Generator.DeclareLocal(typeof(object));
				Label label = iLEmitResolverBuilderContext.Generator.DefineLabel();
				Label label2 = iLEmitResolverBuilderContext.Generator.DefineLabel();
				Label label3 = iLEmitResolverBuilderContext.Generator.DefineLabel();
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ldarg_1);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Callvirt, ScopeIsRootScope);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Brfalse_S, label3);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Call, CallSiteRuntimeResolverInstanceField);
				AddConstant(iLEmitResolverBuilderContext, callSite);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ldarg_1);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Callvirt, CallSiteRuntimeResolverResolveMethod);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ret);
				iLEmitResolverBuilderContext.Generator.MarkLabel(label3);
				AddCacheKey(iLEmitResolverBuilderContext, callSite.Cache.Key);
				Stloc(iLEmitResolverBuilderContext.Generator, localBuilder.LocalIndex);
				iLEmitResolverBuilderContext.Generator.BeginExceptionBlock();
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ldarg_1);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Callvirt, ResolvedServicesGetter);
				Stloc(iLEmitResolverBuilderContext.Generator, localBuilder2.LocalIndex);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ldarg_1);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Callvirt, ScopeLockGetter);
				Stloc(iLEmitResolverBuilderContext.Generator, localBuilder3.LocalIndex);
				Ldloc(iLEmitResolverBuilderContext.Generator, localBuilder3.LocalIndex);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ldloca_S, localBuilder4.LocalIndex);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Call, ServiceLookupHelpers.MonitorEnterMethodInfo);
				Ldloc(iLEmitResolverBuilderContext.Generator, localBuilder2.LocalIndex);
				Ldloc(iLEmitResolverBuilderContext.Generator, localBuilder.LocalIndex);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Ldloca_S, localBuilder5.LocalIndex);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Callvirt, ServiceLookupHelpers.TryGetValueMethodInfo);
				iLEmitResolverBuilderContext.Generator.Emit(OpCodes.Brtrue, label);
				VisitCallSiteMain(callSite, iLEmitResolverBuilderContext);
				Stloc(iLEmitResolverBuilderContext.Generator, localBuilder5.LocalIndex);
	

plugins/TwitchLib/Microsoft.Extensions.Logging.Abstractions.dll

Decompiled 6 months ago
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using FxResources.Microsoft.Extensions.Logging.Abstractions;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.Internal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Microsoft.Extensions.Logging.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyDefaultAlias("Microsoft.Extensions.Logging.Abstractions")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Logging abstractions for Microsoft.Extensions.Logging.\r\n\r\nCommonly Used Types:\r\nMicrosoft.Extensions.Logging.ILogger\r\nMicrosoft.Extensions.Logging.ILoggerFactory\r\nMicrosoft.Extensions.Logging.ILogger<TCategoryName>\r\nMicrosoft.Extensions.Logging.LogLevel\r\nMicrosoft.Extensions.Logging.Logger<T>\r\nMicrosoft.Extensions.Logging.LoggerMessage\r\nMicrosoft.Extensions.Logging.Abstractions.NullLogger")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.Logging.Abstractions")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("6.0.0.0")]
[module: UnverifiableCode]
[module: System.Runtime.CompilerServices.NullablePublicOnly(true)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsByRefLikeAttribute : Attribute
	{
	}
	[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 NullablePublicOnlyAttribute : Attribute
	{
		public readonly bool IncludesInternals;

		public NullablePublicOnlyAttribute(bool P_0)
		{
			IncludesInternals = P_0;
		}
	}
}
namespace FxResources.Microsoft.Extensions.Logging.Abstractions
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string UnexpectedNumberOfNamedParameters => GetResourceString("UnexpectedNumberOfNamedParameters");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class AllowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class DisallowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class MaybeNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class NotNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class MaybeNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public MaybeNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class NotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public NotNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
	internal sealed class NotNullIfNotNullAttribute : Attribute
	{
		public string ParameterName { get; }

		public NotNullIfNotNullAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	internal sealed class DoesNotReturnAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal sealed class DoesNotReturnIfAttribute : Attribute
	{
		public bool ParameterValue { get; }

		public DoesNotReturnIfAttribute(bool parameterValue)
		{
			ParameterValue = parameterValue;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
}
namespace System.Text
{
	internal ref struct ValueStringBuilder
	{
		private char[] _arrayToReturnToPool;

		private Span<char> _chars;

		private int _pos;

		public int Length
		{
			get
			{
				return _pos;
			}
			set
			{
				_pos = value;
			}
		}

		public int Capacity => _chars.Length;

		public ref char this[int index] => ref _chars[index];

		public Span<char> RawChars => _chars;

		public ValueStringBuilder(Span<char> initialBuffer)
		{
			_arrayToReturnToPool = null;
			_chars = initialBuffer;
			_pos = 0;
		}

		public ValueStringBuilder(int initialCapacity)
		{
			_arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialCapacity);
			_chars = _arrayToReturnToPool;
			_pos = 0;
		}

		public void EnsureCapacity(int capacity)
		{
			if ((uint)capacity > (uint)_chars.Length)
			{
				Grow(capacity - _pos);
			}
		}

		public ref char GetPinnableReference()
		{
			return ref MemoryMarshal.GetReference(_chars);
		}

		public ref char GetPinnableReference(bool terminate)
		{
			if (terminate)
			{
				EnsureCapacity(Length + 1);
				_chars[Length] = '\0';
			}
			return ref MemoryMarshal.GetReference(_chars);
		}

		public override string ToString()
		{
			string result = _chars.Slice(0, _pos).ToString();
			Dispose();
			return result;
		}

		public ReadOnlySpan<char> AsSpan(bool terminate)
		{
			if (terminate)
			{
				EnsureCapacity(Length + 1);
				_chars[Length] = '\0';
			}
			return _chars.Slice(0, _pos);
		}

		public ReadOnlySpan<char> AsSpan()
		{
			return _chars.Slice(0, _pos);
		}

		public ReadOnlySpan<char> AsSpan(int start)
		{
			return _chars.Slice(start, _pos - start);
		}

		public ReadOnlySpan<char> AsSpan(int start, int length)
		{
			return _chars.Slice(start, length);
		}

		public bool TryCopyTo(Span<char> destination, out int charsWritten)
		{
			if (_chars.Slice(0, _pos).TryCopyTo(destination))
			{
				charsWritten = _pos;
				Dispose();
				return true;
			}
			charsWritten = 0;
			Dispose();
			return false;
		}

		public void Insert(int index, char value, int count)
		{
			if (_pos > _chars.Length - count)
			{
				Grow(count);
			}
			int length = _pos - index;
			_chars.Slice(index, length).CopyTo(_chars.Slice(index + count));
			_chars.Slice(index, count).Fill(value);
			_pos += count;
		}

		public void Insert(int index, string? s)
		{
			if (s != null)
			{
				int length = s.Length;
				if (_pos > _chars.Length - length)
				{
					Grow(length);
				}
				int length2 = _pos - index;
				_chars.Slice(index, length2).CopyTo(_chars.Slice(index + length));
				s.AsSpan().CopyTo(_chars.Slice(index));
				_pos += length;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Append(char c)
		{
			int pos = _pos;
			if ((uint)pos < (uint)_chars.Length)
			{
				_chars[pos] = c;
				_pos = pos + 1;
			}
			else
			{
				GrowAndAppend(c);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Append(string? s)
		{
			if (s != null)
			{
				int pos = _pos;
				if (s.Length == 1 && (uint)pos < (uint)_chars.Length)
				{
					_chars[pos] = s[0];
					_pos = pos + 1;
				}
				else
				{
					AppendSlow(s);
				}
			}
		}

		private void AppendSlow(string s)
		{
			int pos = _pos;
			if (pos > _chars.Length - s.Length)
			{
				Grow(s.Length);
			}
			s.AsSpan().CopyTo(_chars.Slice(pos));
			_pos += s.Length;
		}

		public void Append(char c, int count)
		{
			if (_pos > _chars.Length - count)
			{
				Grow(count);
			}
			Span<char> span = _chars.Slice(_pos, count);
			for (int i = 0; i < span.Length; i++)
			{
				span[i] = c;
			}
			_pos += count;
		}

		public unsafe void Append(char* value, int length)
		{
			int pos = _pos;
			if (pos > _chars.Length - length)
			{
				Grow(length);
			}
			Span<char> span = _chars.Slice(_pos, length);
			for (int i = 0; i < span.Length; i++)
			{
				span[i] = *(value++);
			}
			_pos += length;
		}

		public void Append(ReadOnlySpan<char> value)
		{
			int pos = _pos;
			if (pos > _chars.Length - value.Length)
			{
				Grow(value.Length);
			}
			value.CopyTo(_chars.Slice(_pos));
			_pos += value.Length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Span<char> AppendSpan(int length)
		{
			int pos = _pos;
			if (pos > _chars.Length - length)
			{
				Grow(length);
			}
			_pos = pos + length;
			return _chars.Slice(pos, length);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void GrowAndAppend(char c)
		{
			Grow(1);
			Append(c);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void Grow(int additionalCapacityBeyondPos)
		{
			char[] array = ArrayPool<char>.Shared.Rent((int)Math.Max((uint)(_pos + additionalCapacityBeyondPos), (uint)(_chars.Length * 2)));
			_chars.Slice(0, _pos).CopyTo(array);
			char[] arrayToReturnToPool = _arrayToReturnToPool;
			_chars = (_arrayToReturnToPool = array);
			if (arrayToReturnToPool != null)
			{
				ArrayPool<char>.Shared.Return(arrayToReturnToPool);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Dispose()
		{
			char[] arrayToReturnToPool = _arrayToReturnToPool;
			this = default(System.Text.ValueStringBuilder);
			if (arrayToReturnToPool != null)
			{
				ArrayPool<char>.Shared.Return(arrayToReturnToPool);
			}
		}
	}
}
namespace Microsoft.Extensions.Internal
{
	internal static class TypeNameHelper
	{
		private readonly struct DisplayNameOptions
		{
			public bool FullName { get; }

			public bool IncludeGenericParameters { get; }

			public bool IncludeGenericParameterNames { get; }

			public char NestedTypeDelimiter { get; }

			public DisplayNameOptions(bool fullName, bool includeGenericParameterNames, bool includeGenericParameters, char nestedTypeDelimiter)
			{
				FullName = fullName;
				IncludeGenericParameters = includeGenericParameters;
				IncludeGenericParameterNames = includeGenericParameterNames;
				NestedTypeDelimiter = nestedTypeDelimiter;
			}
		}

		private const char DefaultNestedTypeDelimiter = '+';

		private static readonly Dictionary<Type, string> _builtInTypeNames = new Dictionary<Type, string>
		{
			{
				typeof(void),
				"void"
			},
			{
				typeof(bool),
				"bool"
			},
			{
				typeof(byte),
				"byte"
			},
			{
				typeof(char),
				"char"
			},
			{
				typeof(decimal),
				"decimal"
			},
			{
				typeof(double),
				"double"
			},
			{
				typeof(float),
				"float"
			},
			{
				typeof(int),
				"int"
			},
			{
				typeof(long),
				"long"
			},
			{
				typeof(object),
				"object"
			},
			{
				typeof(sbyte),
				"sbyte"
			},
			{
				typeof(short),
				"short"
			},
			{
				typeof(string),
				"string"
			},
			{
				typeof(uint),
				"uint"
			},
			{
				typeof(ulong),
				"ulong"
			},
			{
				typeof(ushort),
				"ushort"
			}
		};

		[return: NotNullIfNotNull("item")]
		public static string? GetTypeDisplayName(object? item, bool fullName = true)
		{
			if (item != null)
			{
				return GetTypeDisplayName(item.GetType(), fullName);
			}
			return null;
		}

		public static string GetTypeDisplayName(Type type, bool fullName = true, bool includeGenericParameterNames = false, bool includeGenericParameters = true, char nestedTypeDelimiter = '+')
		{
			StringBuilder stringBuilder = new StringBuilder();
			DisplayNameOptions options = new DisplayNameOptions(fullName, includeGenericParameterNames, includeGenericParameters, nestedTypeDelimiter);
			ProcessType(stringBuilder, type, in options);
			return stringBuilder.ToString();
		}

		private static void ProcessType(StringBuilder builder, Type type, in DisplayNameOptions options)
		{
			if (type.IsGenericType)
			{
				Type[] genericArguments = type.GetGenericArguments();
				ProcessGenericType(builder, type, genericArguments, genericArguments.Length, in options);
				return;
			}
			if (type.IsArray)
			{
				ProcessArrayType(builder, type, in options);
				return;
			}
			if (_builtInTypeNames.TryGetValue(type, out var value))
			{
				builder.Append(value);
				return;
			}
			if (type.IsGenericParameter)
			{
				if (options.IncludeGenericParameterNames)
				{
					builder.Append(type.Name);
				}
				return;
			}
			string text = (options.FullName ? type.FullName : type.Name);
			builder.Append(text);
			if (options.NestedTypeDelimiter != '+')
			{
				builder.Replace('+', options.NestedTypeDelimiter, builder.Length - text.Length, text.Length);
			}
		}

		private static void ProcessArrayType(StringBuilder builder, Type type, in DisplayNameOptions options)
		{
			Type type2 = type;
			while (type2.IsArray)
			{
				type2 = type2.GetElementType();
			}
			ProcessType(builder, type2, in options);
			while (type.IsArray)
			{
				builder.Append('[');
				builder.Append(',', type.GetArrayRank() - 1);
				builder.Append(']');
				type = type.GetElementType();
			}
		}

		private static void ProcessGenericType(StringBuilder builder, Type type, Type[] genericArguments, int length, in DisplayNameOptions options)
		{
			int num = 0;
			if (type.IsNested)
			{
				num = type.DeclaringType.GetGenericArguments().Length;
			}
			if (options.FullName)
			{
				if (type.IsNested)
				{
					ProcessGenericType(builder, type.DeclaringType, genericArguments, num, in options);
					builder.Append(options.NestedTypeDelimiter);
				}
				else if (!string.IsNullOrEmpty(type.Namespace))
				{
					builder.Append(type.Namespace);
					builder.Append('.');
				}
			}
			int num2 = type.Name.IndexOf('`');
			if (num2 <= 0)
			{
				builder.Append(type.Name);
				return;
			}
			builder.Append(type.Name, 0, num2);
			if (!options.IncludeGenericParameters)
			{
				return;
			}
			builder.Append('<');
			for (int i = num; i < length; i++)
			{
				ProcessType(builder, genericArguments[i], in options);
				if (i + 1 != length)
				{
					builder.Append(',');
					if (options.IncludeGenericParameterNames || !genericArguments[i + 1].IsGenericParameter)
					{
						builder.Append(' ');
					}
				}
			}
			builder.Append('>');
		}
	}
}
namespace Microsoft.Extensions.Logging
{
	public readonly struct EventId
	{
		public int Id { get; }

		public string? Name { get; }

		public static implicit operator EventId(int i)
		{
			return new EventId(i);
		}

		public static bool operator ==(EventId left, EventId right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(EventId left, EventId right)
		{
			return !left.Equals(right);
		}

		public EventId(int id, string? name = null)
		{
			Id = id;
			Name = name;
		}

		public override string ToString()
		{
			return Name ?? Id.ToString();
		}

		public bool Equals(EventId other)
		{
			return Id == other.Id;
		}

		public override bool Equals([NotNullWhen(true)] object? obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (obj is EventId other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Id;
		}
	}
	internal readonly struct FormattedLogValues : IReadOnlyList<KeyValuePair<string, object?>>, IReadOnlyCollection<KeyValuePair<string, object?>>, IEnumerable<KeyValuePair<string, object?>>, IEnumerable
	{
		internal const int MaxCachedFormatters = 1024;

		private const string NullFormat = "[null]";

		private static int _count;

		private static ConcurrentDictionary<string, LogValuesFormatter> _formatters = new ConcurrentDictionary<string, LogValuesFormatter>();

		private readonly LogValuesFormatter _formatter;

		private readonly object[] _values;

		private readonly string _originalMessage;

		internal LogValuesFormatter? Formatter => _formatter;

		public KeyValuePair<string, object?> this[int index]
		{
			get
			{
				if (index < 0 || index >= Count)
				{
					throw new IndexOutOfRangeException("index");
				}
				if (index == Count - 1)
				{
					return new KeyValuePair<string, object>("{OriginalFormat}", _originalMessage);
				}
				return _formatter.GetValue(_values, index);
			}
		}

		public int Count
		{
			get
			{
				if (_formatter == null)
				{
					return 1;
				}
				return _formatter.ValueNames.Count + 1;
			}
		}

		public FormattedLogValues(string? format, params object?[]? values)
		{
			if (values != null && values.Length != 0 && format != null)
			{
				if (_count >= 1024)
				{
					if (!_formatters.TryGetValue(format, out _formatter))
					{
						_formatter = new LogValuesFormatter(format);
					}
				}
				else
				{
					_formatter = _formatters.GetOrAdd(format, delegate(string f)
					{
						Interlocked.Increment(ref _count);
						return new LogValuesFormatter(f);
					});
				}
			}
			else
			{
				_formatter = null;
			}
			_originalMessage = format ?? "[null]";
			_values = values;
		}

		public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
		{
			int i = 0;
			while (i < Count)
			{
				yield return this[i];
				int num = i + 1;
				i = num;
			}
		}

		public override string ToString()
		{
			if (_formatter == null)
			{
				return _originalMessage;
			}
			return _formatter.Format(_values);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public interface IExternalScopeProvider
	{
		void ForEachScope<TState>(Action<object?, TState> callback, TState state);

		IDisposable Push(object? state);
	}
	public interface ILogger
	{
		void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter);

		bool IsEnabled(LogLevel logLevel);

		IDisposable BeginScope<TState>(TState state);
	}
	public interface ILoggerFactory : IDisposable
	{
		ILogger CreateLogger(string categoryName);

		void AddProvider(ILoggerProvider provider);
	}
	public interface ILoggerProvider : IDisposable
	{
		ILogger CreateLogger(string categoryName);
	}
	public interface ILogger<out TCategoryName> : ILogger
	{
	}
	public interface ISupportExternalScope
	{
		void SetScopeProvider(IExternalScopeProvider scopeProvider);
	}
	public class LogDefineOptions
	{
		public bool SkipEnabledCheck { get; set; }
	}
	public static class LoggerExtensions
	{
		private static readonly Func<FormattedLogValues, Exception, string> _messageFormatter = MessageFormatter;

		public static void LogDebug(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Debug, eventId, exception, message, args);
		}

		public static void LogDebug(this ILogger logger, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Debug, eventId, message, args);
		}

		public static void LogDebug(this ILogger logger, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Debug, exception, message, args);
		}

		public static void LogDebug(this ILogger logger, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Debug, message, args);
		}

		public static void LogTrace(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Trace, eventId, exception, message, args);
		}

		public static void LogTrace(this ILogger logger, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Trace, eventId, message, args);
		}

		public static void LogTrace(this ILogger logger, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Trace, exception, message, args);
		}

		public static void LogTrace(this ILogger logger, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Trace, message, args);
		}

		public static void LogInformation(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Information, eventId, exception, message, args);
		}

		public static void LogInformation(this ILogger logger, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Information, eventId, message, args);
		}

		public static void LogInformation(this ILogger logger, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Information, exception, message, args);
		}

		public static void LogInformation(this ILogger logger, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Information, message, args);
		}

		public static void LogWarning(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Warning, eventId, exception, message, args);
		}

		public static void LogWarning(this ILogger logger, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Warning, eventId, message, args);
		}

		public static void LogWarning(this ILogger logger, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Warning, exception, message, args);
		}

		public static void LogWarning(this ILogger logger, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Warning, message, args);
		}

		public static void LogError(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Error, eventId, exception, message, args);
		}

		public static void LogError(this ILogger logger, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Error, eventId, message, args);
		}

		public static void LogError(this ILogger logger, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Error, exception, message, args);
		}

		public static void LogError(this ILogger logger, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Error, message, args);
		}

		public static void LogCritical(this ILogger logger, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Critical, eventId, exception, message, args);
		}

		public static void LogCritical(this ILogger logger, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Critical, eventId, message, args);
		}

		public static void LogCritical(this ILogger logger, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Critical, exception, message, args);
		}

		public static void LogCritical(this ILogger logger, string? message, params object?[] args)
		{
			logger.Log(LogLevel.Critical, message, args);
		}

		public static void Log(this ILogger logger, LogLevel logLevel, string? message, params object?[] args)
		{
			logger.Log(logLevel, 0, null, message, args);
		}

		public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, string? message, params object?[] args)
		{
			logger.Log(logLevel, eventId, null, message, args);
		}

		public static void Log(this ILogger logger, LogLevel logLevel, Exception? exception, string? message, params object?[] args)
		{
			logger.Log(logLevel, 0, exception, message, args);
		}

		public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, Exception? exception, string? message, params object?[] args)
		{
			if (logger == null)
			{
				throw new ArgumentNullException("logger");
			}
			logger.Log(logLevel, eventId, new FormattedLogValues(message, args), exception, _messageFormatter);
		}

		public static IDisposable BeginScope(this ILogger logger, string messageFormat, params object?[] args)
		{
			if (logger == null)
			{
				throw new ArgumentNullException("logger");
			}
			return logger.BeginScope(new FormattedLogValues(messageFormat, args));
		}

		private static string MessageFormatter(FormattedLogValues state, Exception error)
		{
			return state.ToString();
		}
	}
	public class LoggerExternalScopeProvider : IExternalScopeProvider
	{
		private sealed class Scope : IDisposable
		{
			private readonly LoggerExternalScopeProvider _provider;

			private bool _isDisposed;

			public Scope Parent { get; }

			public object State { get; }

			internal Scope(LoggerExternalScopeProvider provider, object state, Scope parent)
			{
				_provider = provider;
				State = state;
				Parent = parent;
			}

			public override string ToString()
			{
				return State?.ToString();
			}

			public void Dispose()
			{
				if (!_isDisposed)
				{
					_provider._currentScope.Value = Parent;
					_isDisposed = true;
				}
			}
		}

		private readonly AsyncLocal<Scope> _currentScope = new AsyncLocal<Scope>();

		public void ForEachScope<TState>(Action<object?, TState> callback, TState state)
		{
			Action<object, TState> callback2 = callback;
			TState state2 = state;
			Report(_currentScope.Value);
			void Report(Scope? current)
			{
				if (current != null)
				{
					Report(current.Parent);
					callback2(current.State, state2);
				}
			}
		}

		public IDisposable Push(object? state)
		{
			Scope value = _currentScope.Value;
			Scope scope = new Scope(this, state, value);
			_currentScope.Value = scope;
			return scope;
		}
	}
	public static class LoggerFactoryExtensions
	{
		public static ILogger<T> CreateLogger<T>(this ILoggerFactory factory)
		{
			if (factory == null)
			{
				throw new ArgumentNullException("factory");
			}
			return new Logger<T>(factory);
		}

		public static ILogger CreateLogger(this ILoggerFactory factory, Type type)
		{
			if (factory == null)
			{
				throw new ArgumentNullException("factory");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			return factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(type, fullName: true, includeGenericParameterNames: false, includeGenericParameters: false, '.'));
		}
	}
	public static class LoggerMessage
	{
		private readonly struct LogValues : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues, Exception, string> Callback = (LogValues state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			public KeyValuePair<string, object> this[int index]
			{
				get
				{
					if (index == 0)
					{
						return new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat);
					}
					throw new IndexOutOfRangeException("index");
				}
			}

			public int Count => 1;

			public LogValues(LogValuesFormatter formatter)
			{
				_formatter = formatter;
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				yield return this[0];
			}

			public override string ToString()
			{
				return _formatter.Format();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly struct LogValues<T0> : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues<T0>, Exception, string> Callback = (LogValues<T0> state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			private readonly T0 _value0;

			public KeyValuePair<string, object> this[int index] => index switch
			{
				0 => new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0), 
				1 => new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat), 
				_ => throw new IndexOutOfRangeException("index"), 
			};

			public int Count => 2;

			public LogValues(LogValuesFormatter formatter, T0 value0)
			{
				_formatter = formatter;
				_value0 = value0;
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			public override string ToString()
			{
				return _formatter.Format(_value0);
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly struct LogValues<T0, T1> : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues<T0, T1>, Exception, string> Callback = (LogValues<T0, T1> state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			private readonly T0 _value0;

			private readonly T1 _value1;

			public KeyValuePair<string, object> this[int index] => index switch
			{
				0 => new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0), 
				1 => new KeyValuePair<string, object>(_formatter.ValueNames[1], _value1), 
				2 => new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat), 
				_ => throw new IndexOutOfRangeException("index"), 
			};

			public int Count => 3;

			public LogValues(LogValuesFormatter formatter, T0 value0, T1 value1)
			{
				_formatter = formatter;
				_value0 = value0;
				_value1 = value1;
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			public override string ToString()
			{
				return _formatter.Format(_value0, _value1);
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly struct LogValues<T0, T1, T2> : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues<T0, T1, T2>, Exception, string> Callback = (LogValues<T0, T1, T2> state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			private readonly T0 _value0;

			private readonly T1 _value1;

			private readonly T2 _value2;

			public int Count => 4;

			public KeyValuePair<string, object> this[int index] => index switch
			{
				0 => new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0), 
				1 => new KeyValuePair<string, object>(_formatter.ValueNames[1], _value1), 
				2 => new KeyValuePair<string, object>(_formatter.ValueNames[2], _value2), 
				3 => new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat), 
				_ => throw new IndexOutOfRangeException("index"), 
			};

			public LogValues(LogValuesFormatter formatter, T0 value0, T1 value1, T2 value2)
			{
				_formatter = formatter;
				_value0 = value0;
				_value1 = value1;
				_value2 = value2;
			}

			public override string ToString()
			{
				return _formatter.Format(_value0, _value1, _value2);
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly struct LogValues<T0, T1, T2, T3> : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues<T0, T1, T2, T3>, Exception, string> Callback = (LogValues<T0, T1, T2, T3> state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			private readonly T0 _value0;

			private readonly T1 _value1;

			private readonly T2 _value2;

			private readonly T3 _value3;

			public int Count => 5;

			public KeyValuePair<string, object> this[int index] => index switch
			{
				0 => new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0), 
				1 => new KeyValuePair<string, object>(_formatter.ValueNames[1], _value1), 
				2 => new KeyValuePair<string, object>(_formatter.ValueNames[2], _value2), 
				3 => new KeyValuePair<string, object>(_formatter.ValueNames[3], _value3), 
				4 => new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat), 
				_ => throw new IndexOutOfRangeException("index"), 
			};

			public LogValues(LogValuesFormatter formatter, T0 value0, T1 value1, T2 value2, T3 value3)
			{
				_formatter = formatter;
				_value0 = value0;
				_value1 = value1;
				_value2 = value2;
				_value3 = value3;
			}

			private object[] ToArray()
			{
				return new object[4] { _value0, _value1, _value2, _value3 };
			}

			public override string ToString()
			{
				return _formatter.FormatWithOverwrite(ToArray());
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly struct LogValues<T0, T1, T2, T3, T4> : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues<T0, T1, T2, T3, T4>, Exception, string> Callback = (LogValues<T0, T1, T2, T3, T4> state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			private readonly T0 _value0;

			private readonly T1 _value1;

			private readonly T2 _value2;

			private readonly T3 _value3;

			private readonly T4 _value4;

			public int Count => 6;

			public KeyValuePair<string, object> this[int index] => index switch
			{
				0 => new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0), 
				1 => new KeyValuePair<string, object>(_formatter.ValueNames[1], _value1), 
				2 => new KeyValuePair<string, object>(_formatter.ValueNames[2], _value2), 
				3 => new KeyValuePair<string, object>(_formatter.ValueNames[3], _value3), 
				4 => new KeyValuePair<string, object>(_formatter.ValueNames[4], _value4), 
				5 => new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat), 
				_ => throw new IndexOutOfRangeException("index"), 
			};

			public LogValues(LogValuesFormatter formatter, T0 value0, T1 value1, T2 value2, T3 value3, T4 value4)
			{
				_formatter = formatter;
				_value0 = value0;
				_value1 = value1;
				_value2 = value2;
				_value3 = value3;
				_value4 = value4;
			}

			private object[] ToArray()
			{
				return new object[5] { _value0, _value1, _value2, _value3, _value4 };
			}

			public override string ToString()
			{
				return _formatter.FormatWithOverwrite(ToArray());
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private readonly struct LogValues<T0, T1, T2, T3, T4, T5> : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			public static readonly Func<LogValues<T0, T1, T2, T3, T4, T5>, Exception, string> Callback = (LogValues<T0, T1, T2, T3, T4, T5> state, Exception exception) => state.ToString();

			private readonly LogValuesFormatter _formatter;

			private readonly T0 _value0;

			private readonly T1 _value1;

			private readonly T2 _value2;

			private readonly T3 _value3;

			private readonly T4 _value4;

			private readonly T5 _value5;

			public int Count => 7;

			public KeyValuePair<string, object> this[int index] => index switch
			{
				0 => new KeyValuePair<string, object>(_formatter.ValueNames[0], _value0), 
				1 => new KeyValuePair<string, object>(_formatter.ValueNames[1], _value1), 
				2 => new KeyValuePair<string, object>(_formatter.ValueNames[2], _value2), 
				3 => new KeyValuePair<string, object>(_formatter.ValueNames[3], _value3), 
				4 => new KeyValuePair<string, object>(_formatter.ValueNames[4], _value4), 
				5 => new KeyValuePair<string, object>(_formatter.ValueNames[5], _value5), 
				6 => new KeyValuePair<string, object>("{OriginalFormat}", _formatter.OriginalFormat), 
				_ => throw new IndexOutOfRangeException("index"), 
			};

			public LogValues(LogValuesFormatter formatter, T0 value0, T1 value1, T2 value2, T3 value3, T4 value4, T5 value5)
			{
				_formatter = formatter;
				_value0 = value0;
				_value1 = value1;
				_value2 = value2;
				_value3 = value3;
				_value4 = value4;
				_value5 = value5;
			}

			private object[] ToArray()
			{
				return new object[6] { _value0, _value1, _value2, _value3, _value4, _value5 };
			}

			public override string ToString()
			{
				return _formatter.FormatWithOverwrite(ToArray());
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		public static Func<ILogger, IDisposable> DefineScope(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 0);
			LogValues logValues = new LogValues(formatter);
			return (ILogger logger) => logger.BeginScope(logValues);
		}

		public static Func<ILogger, T1, IDisposable> DefineScope<T1>(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 1);
			return (ILogger logger, T1 arg1) => logger.BeginScope(new LogValues<T1>(formatter, arg1));
		}

		public static Func<ILogger, T1, T2, IDisposable> DefineScope<T1, T2>(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 2);
			return (ILogger logger, T1 arg1, T2 arg2) => logger.BeginScope(new LogValues<T1, T2>(formatter, arg1, arg2));
		}

		public static Func<ILogger, T1, T2, T3, IDisposable> DefineScope<T1, T2, T3>(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 3);
			return (ILogger logger, T1 arg1, T2 arg2, T3 arg3) => logger.BeginScope(new LogValues<T1, T2, T3>(formatter, arg1, arg2, arg3));
		}

		public static Func<ILogger, T1, T2, T3, T4, IDisposable> DefineScope<T1, T2, T3, T4>(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 4);
			return (ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4) => logger.BeginScope(new LogValues<T1, T2, T3, T4>(formatter, arg1, arg2, arg3, arg4));
		}

		public static Func<ILogger, T1, T2, T3, T4, T5, IDisposable> DefineScope<T1, T2, T3, T4, T5>(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 5);
			return (ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) => logger.BeginScope(new LogValues<T1, T2, T3, T4, T5>(formatter, arg1, arg2, arg3, arg4, arg5));
		}

		public static Func<ILogger, T1, T2, T3, T4, T5, T6, IDisposable> DefineScope<T1, T2, T3, T4, T5, T6>(string formatString)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 6);
			return (ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) => logger.BeginScope(new LogValues<T1, T2, T3, T4, T5, T6>(formatter, arg1, arg2, arg3, arg4, arg5, arg6));
		}

		public static Action<ILogger, Exception?> Define(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, Exception?> Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 0);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, exception);
				}
			};
			void Log(ILogger logger, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues(formatter), exception, LogValues.Callback);
			}
		}

		public static Action<ILogger, T1, Exception?> Define<T1>(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define<T1>(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, T1, Exception?> Define<T1>(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 1);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, T1 arg1, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, arg1, exception);
				}
			};
			void Log(ILogger logger, T1 arg1, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues<T1>(formatter, arg1), exception, LogValues<T1>.Callback);
			}
		}

		public static Action<ILogger, T1, T2, Exception?> Define<T1, T2>(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define<T1, T2>(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, T1, T2, Exception?> Define<T1, T2>(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 2);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, T1 arg1, T2 arg2, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, arg1, arg2, exception);
				}
			};
			void Log(ILogger logger, T1 arg1, T2 arg2, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues<T1, T2>(formatter, arg1, arg2), exception, LogValues<T1, T2>.Callback);
			}
		}

		public static Action<ILogger, T1, T2, T3, Exception?> Define<T1, T2, T3>(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define<T1, T2, T3>(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, T1, T2, T3, Exception?> Define<T1, T2, T3>(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 3);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, T1 arg1, T2 arg2, T3 arg3, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, arg1, arg2, arg3, exception);
				}
			};
			void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues<T1, T2, T3>(formatter, arg1, arg2, arg3), exception, LogValues<T1, T2, T3>.Callback);
			}
		}

		public static Action<ILogger, T1, T2, T3, T4, Exception?> Define<T1, T2, T3, T4>(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define<T1, T2, T3, T4>(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, T1, T2, T3, T4, Exception?> Define<T1, T2, T3, T4>(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 4);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, arg1, arg2, arg3, arg4, exception);
				}
			};
			void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues<T1, T2, T3, T4>(formatter, arg1, arg2, arg3, arg4), exception, LogValues<T1, T2, T3, T4>.Callback);
			}
		}

		public static Action<ILogger, T1, T2, T3, T4, T5, Exception?> Define<T1, T2, T3, T4, T5>(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define<T1, T2, T3, T4, T5>(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, T1, T2, T3, T4, T5, Exception?> Define<T1, T2, T3, T4, T5>(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 5);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, arg1, arg2, arg3, arg4, arg5, exception);
				}
			};
			void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues<T1, T2, T3, T4, T5>(formatter, arg1, arg2, arg3, arg4, arg5), exception, LogValues<T1, T2, T3, T4, T5>.Callback);
			}
		}

		public static Action<ILogger, T1, T2, T3, T4, T5, T6, Exception?> Define<T1, T2, T3, T4, T5, T6>(LogLevel logLevel, EventId eventId, string formatString)
		{
			return Define<T1, T2, T3, T4, T5, T6>(logLevel, eventId, formatString, null);
		}

		public static Action<ILogger, T1, T2, T3, T4, T5, T6, Exception?> Define<T1, T2, T3, T4, T5, T6>(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
		{
			LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, 6);
			if (options != null && options.SkipEnabledCheck)
			{
				return Log;
			}
			return delegate(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, Exception exception)
			{
				if (logger.IsEnabled(logLevel))
				{
					Log(logger, arg1, arg2, arg3, arg4, arg5, arg6, exception);
				}
			};
			void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, Exception exception)
			{
				logger.Log(logLevel, eventId, new LogValues<T1, T2, T3, T4, T5, T6>(formatter, arg1, arg2, arg3, arg4, arg5, arg6), exception, LogValues<T1, T2, T3, T4, T5, T6>.Callback);
			}
		}

		private static LogValuesFormatter CreateLogValuesFormatter(string formatString, int expectedNamedParameterCount)
		{
			LogValuesFormatter logValuesFormatter = new LogValuesFormatter(formatString);
			int count = logValuesFormatter.ValueNames.Count;
			if (count != expectedNamedParameterCount)
			{
				throw new ArgumentException(System.SR.Format(System.SR.UnexpectedNumberOfNamedParameters, formatString, expectedNamedParameterCount, count));
			}
			return logValuesFormatter;
		}
	}
	[AttributeUsage(AttributeTargets.Method)]
	public sealed class LoggerMessageAttribute : Attribute
	{
		public int EventId { get; set; } = -1;


		public string? EventName { get; set; }

		public LogLevel Level { get; set; } = LogLevel.None;


		public string Message { get; set; } = "";


		public bool SkipEnabledCheck { get; set; }

		public LoggerMessageAttribute()
		{
		}

		public LoggerMessageAttribute(int eventId, LogLevel level, string message)
		{
			EventId = eventId;
			Level = level;
			Message = message;
		}
	}
	public class Logger<T> : ILogger<T>, ILogger
	{
		private readonly ILogger _logger;

		public Logger(ILoggerFactory factory)
		{
			if (factory == null)
			{
				throw new ArgumentNullException("factory");
			}
			_logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T), fullName: true, includeGenericParameterNames: false, includeGenericParameters: false, '.'));
		}

		IDisposable ILogger.BeginScope<TState>(TState state)
		{
			return _logger.BeginScope(state);
		}

		bool ILogger.IsEnabled(LogLevel logLevel)
		{
			return _logger.IsEnabled(logLevel);
		}

		void ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
		{
			_logger.Log(logLevel, eventId, state, exception, formatter);
		}
	}
	public enum LogLevel
	{
		Trace,
		Debug,
		Information,
		Warning,
		Error,
		Critical,
		None
	}
	internal sealed class LogValuesFormatter
	{
		private const string NullValue = "(null)";

		private static readonly char[] FormatDelimiters = new char[2] { ',', ':' };

		private readonly string _format;

		private readonly List<string> _valueNames = new List<string>();

		public string OriginalFormat { get; private set; }

		public List<string> ValueNames => _valueNames;

		public LogValuesFormatter(string format)
		{
			if (format == null)
			{
				throw new ArgumentNullException("format");
			}
			OriginalFormat = format;
			Span<char> initialBuffer = stackalloc char[256];
			System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer);
			int num = 0;
			int length = format.Length;
			while (num < length)
			{
				int num2 = FindBraceIndex(format, '{', num, length);
				if (num == 0 && num2 == length)
				{
					_format = format;
					return;
				}
				int num3 = FindBraceIndex(format, '}', num2, length);
				if (num3 == length)
				{
					valueStringBuilder.Append(format.AsSpan(num, length - num));
					num = length;
					continue;
				}
				int num4 = FindIndexOfAny(format, FormatDelimiters, num2, num3);
				valueStringBuilder.Append(format.AsSpan(num, num2 - num + 1));
				valueStringBuilder.Append(_valueNames.Count.ToString());
				_valueNames.Add(format.Substring(num2 + 1, num4 - num2 - 1));
				valueStringBuilder.Append(format.AsSpan(num4, num3 - num4 + 1));
				num = num3 + 1;
			}
			_format = valueStringBuilder.ToString();
		}

		private static int FindBraceIndex(string format, char brace, int startIndex, int endIndex)
		{
			int result = endIndex;
			int i = startIndex;
			int num = 0;
			for (; i < endIndex; i++)
			{
				if (num > 0 && format[i] != brace)
				{
					if (num % 2 != 0)
					{
						break;
					}
					num = 0;
					result = endIndex;
				}
				else
				{
					if (format[i] != brace)
					{
						continue;
					}
					if (brace == '}')
					{
						if (num == 0)
						{
							result = i;
						}
					}
					else
					{
						result = i;
					}
					num++;
				}
			}
			return result;
		}

		private static int FindIndexOfAny(string format, char[] chars, int startIndex, int endIndex)
		{
			int num = format.IndexOfAny(chars, startIndex, endIndex - startIndex);
			if (num != -1)
			{
				return num;
			}
			return endIndex;
		}

		public string Format(object?[]? values)
		{
			object[] array = values;
			if (values != null)
			{
				for (int i = 0; i < values.Length; i++)
				{
					object obj = FormatArgument(values[i]);
					if (obj != values[i])
					{
						array = new object[values.Length];
						Array.Copy(values, array, i);
						array[i++] = obj;
						for (; i < values.Length; i++)
						{
							array[i] = FormatArgument(values[i]);
						}
						break;
					}
				}
			}
			return string.Format(CultureInfo.InvariantCulture, _format, array ?? Array.Empty<object>());
		}

		internal string FormatWithOverwrite(object?[]? values)
		{
			if (values != null)
			{
				for (int i = 0; i < values.Length; i++)
				{
					values[i] = FormatArgument(values[i]);
				}
			}
			return string.Format(CultureInfo.InvariantCulture, _format, values ?? Array.Empty<object>());
		}

		internal string Format()
		{
			return _format;
		}

		internal string Format(object? arg0)
		{
			return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0));
		}

		internal string Format(object? arg0, object? arg1)
		{
			return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0), FormatArgument(arg1));
		}

		internal string Format(object? arg0, object? arg1, object? arg2)
		{
			return string.Format(CultureInfo.InvariantCulture, _format, FormatArgument(arg0), FormatArgument(arg1), FormatArgument(arg2));
		}

		public KeyValuePair<string, object?> GetValue(object?[] values, int index)
		{
			if (index < 0 || index > _valueNames.Count)
			{
				throw new IndexOutOfRangeException("index");
			}
			if (_valueNames.Count > index)
			{
				return new KeyValuePair<string, object>(_valueNames[index], values[index]);
			}
			return new KeyValuePair<string, object>("{OriginalFormat}", OriginalFormat);
		}

		public IEnumerable<KeyValuePair<string, object?>> GetValues(object[] values)
		{
			KeyValuePair<string, object>[] array = new KeyValuePair<string, object>[values.Length + 1];
			for (int i = 0; i != _valueNames.Count; i++)
			{
				array[i] = new KeyValuePair<string, object>(_valueNames[i], values[i]);
			}
			array[^1] = new KeyValuePair<string, object>("{OriginalFormat}", OriginalFormat);
			return array;
		}

		private object FormatArgument(object value)
		{
			if (value == null)
			{
				return "(null)";
			}
			if (value is string)
			{
				return value;
			}
			if (value is IEnumerable enumerable)
			{
				Span<char> initialBuffer = stackalloc char[256];
				System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer);
				bool flag = true;
				foreach (object item in enumerable)
				{
					if (!flag)
					{
						valueStringBuilder.Append(", ");
					}
					valueStringBuilder.Append((item != null) ? item.ToString() : "(null)");
					flag = false;
				}
				return valueStringBuilder.ToString();
			}
			return value;
		}
	}
	internal sealed class NullExternalScopeProvider : IExternalScopeProvider
	{
		public static IExternalScopeProvider Instance { get; } = new NullExternalScopeProvider();


		private NullExternalScopeProvider()
		{
		}

		void IExternalScopeProvider.ForEachScope<TState>(Action<object, TState> callback, TState state)
		{
		}

		IDisposable IExternalScopeProvider.Push(object state)
		{
			return NullScope.Instance;
		}
	}
	internal sealed class NullScope : IDisposable
	{
		public static NullScope Instance { get; } = new NullScope();


		private NullScope()
		{
		}

		public void Dispose()
		{
		}
	}
}
namespace Microsoft.Extensions.Logging.Abstractions
{
	public readonly struct LogEntry<TState>
	{
		public LogLevel LogLevel { get; }

		public string Category { get; }

		public EventId EventId { get; }

		public TState State { get; }

		public Exception? Exception { get; }

		public Func<TState, Exception?, string>? Formatter { get; }

		public LogEntry(LogLevel logLevel, string category, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
		{
			LogLevel = logLevel;
			Category = category;
			EventId = eventId;
			State = state;
			Exception = exception;
			Formatter = formatter;
		}
	}
	public class NullLogger : ILogger
	{
		public static NullLogger Instance { get; } = new NullLogger();


		private NullLogger()
		{
		}

		public IDisposable BeginScope<TState>(TState state)
		{
			return NullScope.Instance;
		}

		public bool IsEnabled(LogLevel logLevel)
		{
			return false;
		}

		public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
		{
		}
	}
	public class NullLoggerFactory : ILoggerFactory, IDisposable
	{
		public static readonly NullLoggerFactory Instance = new NullLoggerFactory();

		public ILogger CreateLogger(string name)
		{
			return NullLogger.Instance;
		}

		public void AddProvider(ILoggerProvider provider)
		{
		}

		public void Dispose()
		{
		}
	}
	public class NullLoggerProvider : ILoggerProvider, IDisposable
	{
		public static NullLoggerProvider Instance { get; } = new NullLoggerProvider();


		private NullLoggerProvider()
		{
		}

		public ILogger CreateLogger(string categoryName)
		{
			return NullLogger.Instance;
		}

		public void Dispose()
		{
		}
	}
	public class NullLogger<T> : ILogger<T>, ILogger
	{
		public static readonly NullLogger<T> Instance = new NullLogger<T>();

		public IDisposable BeginScope<TState>(TState state)
		{
			return NullScope.Instance;
		}

		public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
		{
		}

		public bool IsEnabled(LogLevel logLevel)
		{
			return false;
		}
	}
}

plugins/TwitchLib/Microsoft.Extensions.Logging.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using FxResources.Microsoft.Extensions.Logging;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyDefaultAlias("Microsoft.Extensions.Logging")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Logging infrastructure default implementation for Microsoft.Extensions.Logging.")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.Logging")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: AssemblyVersion("6.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
namespace FxResources.Microsoft.Extensions.Logging
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string InvalidActivityTrackingOptions => GetResourceString("InvalidActivityTrackingOptions");

		internal static string MoreThanOneWildcard => GetResourceString("MoreThanOneWildcard");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object p1, object p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object p1, object p2, object p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object[] args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2, object p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, params object[] args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace Microsoft.Extensions.DependencyInjection
{
	public static class LoggingServiceCollectionExtensions
	{
		public static IServiceCollection AddLogging(this IServiceCollection services)
		{
			return services.AddLogging(delegate
			{
			});
		}

		public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			OptionsServiceCollectionExtensions.AddOptions(services);
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));
			ServiceCollectionDescriptorExtensions.TryAddEnumerable(services, ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>((IConfigureOptions<LoggerFilterOptions>)(object)new DefaultLoggerLevelConfigureOptions((LogLevel)2)));
			configure(new LoggingBuilder(services));
			return services;
		}
	}
}
namespace Microsoft.Extensions.Logging
{
	[Flags]
	public enum ActivityTrackingOptions
	{
		None = 0,
		SpanId = 1,
		TraceId = 2,
		ParentId = 4,
		TraceState = 8,
		TraceFlags = 0x10,
		Tags = 0x20,
		Baggage = 0x40
	}
	internal sealed class DefaultLoggerLevelConfigureOptions : ConfigureOptions<LoggerFilterOptions>
	{
		public DefaultLoggerLevelConfigureOptions(LogLevel level)
			: base((Action<LoggerFilterOptions>)delegate(LoggerFilterOptions options)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				options.MinLevel = level;
			})
		{
		}//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)

	}
	public static class FilterLoggingBuilderExtensions
	{
		public static ILoggingBuilder AddFilter(this ILoggingBuilder builder, Func<string, string, LogLevel, bool> filter)
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter(filter);
			});
		}

		public static ILoggingBuilder AddFilter(this ILoggingBuilder builder, Func<string, LogLevel, bool> categoryLevelFilter)
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter(categoryLevelFilter);
			});
		}

		public static ILoggingBuilder AddFilter<T>(this ILoggingBuilder builder, Func<string, LogLevel, bool> categoryLevelFilter) where T : ILoggerProvider
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter<T>(categoryLevelFilter);
			});
		}

		public static ILoggingBuilder AddFilter(this ILoggingBuilder builder, Func<LogLevel, bool> levelFilter)
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter(levelFilter);
			});
		}

		public static ILoggingBuilder AddFilter<T>(this ILoggingBuilder builder, Func<LogLevel, bool> levelFilter) where T : ILoggerProvider
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter<T>(levelFilter);
			});
		}

		public static ILoggingBuilder AddFilter(this ILoggingBuilder builder, string category, LogLevel level)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				options.AddFilter(category, level);
			});
		}

		public static ILoggingBuilder AddFilter<T>(this ILoggingBuilder builder, string category, LogLevel level) where T : ILoggerProvider
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				options.AddFilter<T>(category, level);
			});
		}

		public static ILoggingBuilder AddFilter(this ILoggingBuilder builder, string category, Func<LogLevel, bool> levelFilter)
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter(category, levelFilter);
			});
		}

		public static ILoggingBuilder AddFilter<T>(this ILoggingBuilder builder, string category, Func<LogLevel, bool> levelFilter) where T : ILoggerProvider
		{
			return builder.ConfigureFilter(delegate(LoggerFilterOptions options)
			{
				options.AddFilter<T>(category, levelFilter);
			});
		}

		public static LoggerFilterOptions AddFilter(this LoggerFilterOptions builder, Func<string, string, LogLevel, bool> filter)
		{
			return AddRule(builder, null, null, null, filter);
		}

		public static LoggerFilterOptions AddFilter(this LoggerFilterOptions builder, Func<string, LogLevel, bool> categoryLevelFilter)
		{
			return AddRule(builder, null, null, null, (string type, string name, LogLevel level) => categoryLevelFilter(name, level));
		}

		public static LoggerFilterOptions AddFilter<T>(this LoggerFilterOptions builder, Func<string, LogLevel, bool> categoryLevelFilter) where T : ILoggerProvider
		{
			return AddRule(builder, typeof(T).FullName, null, null, (string type, string name, LogLevel level) => categoryLevelFilter(name, level));
		}

		public static LoggerFilterOptions AddFilter(this LoggerFilterOptions builder, Func<LogLevel, bool> levelFilter)
		{
			return AddRule(builder, null, null, null, (string type, string name, LogLevel level) => levelFilter(level));
		}

		public static LoggerFilterOptions AddFilter<T>(this LoggerFilterOptions builder, Func<LogLevel, bool> levelFilter) where T : ILoggerProvider
		{
			return AddRule(builder, typeof(T).FullName, null, null, (string type, string name, LogLevel level) => levelFilter(level));
		}

		public static LoggerFilterOptions AddFilter(this LoggerFilterOptions builder, string category, LogLevel level)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return AddRule(builder, null, category, level);
		}

		public static LoggerFilterOptions AddFilter<T>(this LoggerFilterOptions builder, string category, LogLevel level) where T : ILoggerProvider
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return AddRule(builder, typeof(T).FullName, category, level);
		}

		public static LoggerFilterOptions AddFilter(this LoggerFilterOptions builder, string category, Func<LogLevel, bool> levelFilter)
		{
			return AddRule(builder, null, category, null, (string type, string name, LogLevel level) => levelFilter(level));
		}

		public static LoggerFilterOptions AddFilter<T>(this LoggerFilterOptions builder, string category, Func<LogLevel, bool> levelFilter) where T : ILoggerProvider
		{
			return AddRule(builder, typeof(T).FullName, category, null, (string type, string name, LogLevel level) => levelFilter(level));
		}

		private static ILoggingBuilder ConfigureFilter(this ILoggingBuilder builder, Action<LoggerFilterOptions> configureOptions)
		{
			OptionsServiceCollectionExtensions.Configure<LoggerFilterOptions>(builder.Services, configureOptions);
			return builder;
		}

		private static LoggerFilterOptions AddRule(LoggerFilterOptions options, string type = null, string category = null, LogLevel? level = null, Func<string, string, LogLevel, bool> filter = null)
		{
			options.Rules.Add(new LoggerFilterRule(type, category, level, filter));
			return options;
		}
	}
	public interface ILoggingBuilder
	{
		IServiceCollection Services { get; }
	}
	internal sealed class Logger : ILogger
	{
		private sealed class Scope : IDisposable
		{
			private bool _isDisposed;

			private IDisposable _disposable0;

			private IDisposable _disposable1;

			private readonly IDisposable[] _disposable;

			public Scope(int count)
			{
				if (count > 2)
				{
					_disposable = new IDisposable[count - 2];
				}
			}

			public void SetDisposable(int index, IDisposable disposable)
			{
				switch (index)
				{
				case 0:
					_disposable0 = disposable;
					break;
				case 1:
					_disposable1 = disposable;
					break;
				default:
					_disposable[index - 2] = disposable;
					break;
				}
			}

			public void Dispose()
			{
				if (_isDisposed)
				{
					return;
				}
				_disposable0?.Dispose();
				_disposable1?.Dispose();
				if (_disposable != null)
				{
					int num = _disposable.Length;
					for (int i = 0; i != num; i++)
					{
						if (_disposable[i] != null)
						{
							_disposable[i].Dispose();
						}
					}
				}
				_isDisposed = true;
			}
		}

		public LoggerInformation[] Loggers { get; set; }

		public MessageLogger[] MessageLoggers { get; set; }

		public ScopeLogger[] ScopeLoggers { get; set; }

		public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			MessageLogger[] messageLoggers = MessageLoggers;
			if (messageLoggers == null)
			{
				return;
			}
			List<Exception> exceptions2 = null;
			for (int i = 0; i < messageLoggers.Length; i++)
			{
				ref MessageLogger reference = ref messageLoggers[i];
				if (reference.IsEnabled(logLevel))
				{
					LoggerLog(logLevel, eventId, reference.Logger, exception, formatter, ref exceptions2, in state);
				}
			}
			if (exceptions2 != null && exceptions2.Count > 0)
			{
				ThrowLoggingError(exceptions2);
			}
			static void LoggerLog(LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func<TState, Exception, string> formatter, ref List<Exception> exceptions, in TState state)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					logger.Log<TState>(logLevel, eventId, state, exception, formatter);
				}
				catch (Exception item)
				{
					if (exceptions == null)
					{
						exceptions = new List<Exception>();
					}
					exceptions.Add(item);
				}
			}
		}

		public bool IsEnabled(LogLevel logLevel)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			MessageLogger[] messageLoggers = MessageLoggers;
			if (messageLoggers == null)
			{
				return false;
			}
			List<Exception> exceptions2 = null;
			int i;
			for (i = 0; i < messageLoggers.Length; i++)
			{
				ref MessageLogger reference = ref messageLoggers[i];
				if (reference.IsEnabled(logLevel) && LoggerIsEnabled(logLevel, reference.Logger, ref exceptions2))
				{
					break;
				}
			}
			if (exceptions2 != null && exceptions2.Count > 0)
			{
				ThrowLoggingError(exceptions2);
			}
			if (i >= messageLoggers.Length)
			{
				return false;
			}
			return true;
			static bool LoggerIsEnabled(LogLevel logLevel, ILogger logger, ref List<Exception> exceptions)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (logger.IsEnabled(logLevel))
					{
						return true;
					}
				}
				catch (Exception item)
				{
					if (exceptions == null)
					{
						exceptions = new List<Exception>();
					}
					exceptions.Add(item);
				}
				return false;
			}
		}

		public IDisposable BeginScope<TState>(TState state)
		{
			ScopeLogger[] scopeLoggers = ScopeLoggers;
			if (scopeLoggers == null)
			{
				return NullScope.Instance;
			}
			if (scopeLoggers.Length == 1)
			{
				return scopeLoggers[0].CreateScope(state);
			}
			Scope scope = new Scope(scopeLoggers.Length);
			List<Exception> list = null;
			for (int i = 0; i < scopeLoggers.Length; i++)
			{
				ref ScopeLogger reference = ref scopeLoggers[i];
				try
				{
					scope.SetDisposable(i, reference.CreateScope(state));
				}
				catch (Exception item)
				{
					if (list == null)
					{
						list = new List<Exception>();
					}
					list.Add(item);
				}
			}
			if (list != null && list.Count > 0)
			{
				ThrowLoggingError(list);
			}
			return scope;
		}

		private static void ThrowLoggingError(List<Exception> exceptions)
		{
			throw new AggregateException("An error occurred while writing to logger(s).", exceptions);
		}
	}
	public class LoggerFactory : ILoggerFactory, IDisposable
	{
		private struct ProviderRegistration
		{
			public ILoggerProvider Provider;

			public bool ShouldDispose;
		}

		private sealed class DisposingLoggerFactory : ILoggerFactory, IDisposable
		{
			private readonly ILoggerFactory _loggerFactory;

			private readonly ServiceProvider _serviceProvider;

			public DisposingLoggerFactory(ILoggerFactory loggerFactory, ServiceProvider serviceProvider)
			{
				_loggerFactory = loggerFactory;
				_serviceProvider = serviceProvider;
			}

			public void Dispose()
			{
				_serviceProvider.Dispose();
			}

			public ILogger CreateLogger(string categoryName)
			{
				return _loggerFactory.CreateLogger(categoryName);
			}

			public void AddProvider(ILoggerProvider provider)
			{
				_loggerFactory.AddProvider(provider);
			}
		}

		private readonly Dictionary<string, Logger> _loggers = new Dictionary<string, Logger>(StringComparer.Ordinal);

		private readonly List<ProviderRegistration> _providerRegistrations = new List<ProviderRegistration>();

		private readonly object _sync = new object();

		private volatile bool _disposed;

		private IDisposable _changeTokenRegistration;

		private LoggerFilterOptions _filterOptions;

		private LoggerFactoryScopeProvider _scopeProvider;

		private LoggerFactoryOptions _factoryOptions;

		public LoggerFactory()
			: this(Array.Empty<ILoggerProvider>())
		{
		}

		public LoggerFactory(IEnumerable<ILoggerProvider> providers)
			: this(providers, new StaticFilterOptionsMonitor(new LoggerFilterOptions()))
		{
		}

		public LoggerFactory(IEnumerable<ILoggerProvider> providers, LoggerFilterOptions filterOptions)
			: this(providers, new StaticFilterOptionsMonitor(filterOptions))
		{
		}

		public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<LoggerFilterOptions> filterOption)
			: this(providers, filterOption, null)
		{
		}

		public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<LoggerFilterOptions> filterOption, IOptions<LoggerFactoryOptions> options = null)
		{
			_factoryOptions = ((options == null || options.Value == null) ? new LoggerFactoryOptions() : options.Value);
			if (((uint)_factoryOptions.ActivityTrackingOptions & 0xFFFFFF80u) != 0)
			{
				throw new ArgumentException(System.SR.Format(System.SR.InvalidActivityTrackingOptions, _factoryOptions.ActivityTrackingOptions), "options");
			}
			foreach (ILoggerProvider provider in providers)
			{
				AddProviderRegistration(provider, dispose: false);
			}
			_changeTokenRegistration = OptionsMonitorExtensions.OnChange<LoggerFilterOptions>(filterOption, (Action<LoggerFilterOptions>)RefreshFilters);
			RefreshFilters(filterOption.CurrentValue);
		}

		public static ILoggerFactory Create(Action<ILoggingBuilder> configure)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ServiceCollection val = new ServiceCollection();
			((IServiceCollection)(object)val).AddLogging(configure);
			ServiceProvider val2 = ServiceCollectionContainerBuilderExtensions.BuildServiceProvider((IServiceCollection)(object)val);
			ILoggerFactory service = ServiceProviderServiceExtensions.GetService<ILoggerFactory>((IServiceProvider)val2);
			return (ILoggerFactory)(object)new DisposingLoggerFactory(service, val2);
		}

		private void RefreshFilters(LoggerFilterOptions filterOptions)
		{
			lock (_sync)
			{
				_filterOptions = filterOptions;
				foreach (KeyValuePair<string, Logger> logger2 in _loggers)
				{
					Logger value = logger2.Value;
					(value.MessageLoggers, value.ScopeLoggers) = ApplyFilters(value.Loggers);
				}
			}
		}

		public ILogger CreateLogger(string categoryName)
		{
			if (CheckDisposed())
			{
				throw new ObjectDisposedException("LoggerFactory");
			}
			lock (_sync)
			{
				if (!_loggers.TryGetValue(categoryName, out var value))
				{
					value = new Logger
					{
						Loggers = CreateLoggers(categoryName)
					};
					(value.MessageLoggers, value.ScopeLoggers) = ApplyFilters(value.Loggers);
					_loggers[categoryName] = value;
				}
				return (ILogger)(object)value;
			}
		}

		public void AddProvider(ILoggerProvider provider)
		{
			if (CheckDisposed())
			{
				throw new ObjectDisposedException("LoggerFactory");
			}
			if (provider == null)
			{
				throw new ArgumentNullException("provider");
			}
			lock (_sync)
			{
				AddProviderRegistration(provider, dispose: true);
				foreach (KeyValuePair<string, Logger> logger2 in _loggers)
				{
					Logger value = logger2.Value;
					LoggerInformation[] array = value.Loggers;
					int num = array.Length;
					Array.Resize(ref array, array.Length + 1);
					array[num] = new LoggerInformation(provider, logger2.Key);
					value.Loggers = array;
					(value.MessageLoggers, value.ScopeLoggers) = ApplyFilters(value.Loggers);
				}
			}
		}

		private void AddProviderRegistration(ILoggerProvider provider, bool dispose)
		{
			_providerRegistrations.Add(new ProviderRegistration
			{
				Provider = provider,
				ShouldDispose = dispose
			});
			ISupportExternalScope val = (ISupportExternalScope)(object)((provider is ISupportExternalScope) ? provider : null);
			if (val != null)
			{
				if (_scopeProvider == null)
				{
					_scopeProvider = new LoggerFactoryScopeProvider(_factoryOptions.ActivityTrackingOptions);
				}
				val.SetScopeProvider((IExternalScopeProvider)(object)_scopeProvider);
			}
		}

		private LoggerInformation[] CreateLoggers(string categoryName)
		{
			LoggerInformation[] array = new LoggerInformation[_providerRegistrations.Count];
			for (int i = 0; i < _providerRegistrations.Count; i++)
			{
				array[i] = new LoggerInformation(_providerRegistrations[i].Provider, categoryName);
			}
			return array;
		}

		private (MessageLogger[] MessageLoggers, ScopeLogger[] ScopeLoggers) ApplyFilters(LoggerInformation[] loggers)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			List<MessageLogger> list = new List<MessageLogger>();
			List<ScopeLogger> list2 = (_filterOptions.CaptureScopes ? new List<ScopeLogger>() : null);
			for (int i = 0; i < loggers.Length; i++)
			{
				LoggerInformation loggerInformation = loggers[i];
				LoggerRuleSelector.Select(_filterOptions, loggerInformation.ProviderType, loggerInformation.Category, out var minLevel, out var filter);
				if (!minLevel.HasValue || !(minLevel > 5))
				{
					list.Add(new MessageLogger(loggerInformation.Logger, loggerInformation.Category, loggerInformation.ProviderType.FullName, minLevel, filter));
					if (!loggerInformation.ExternalScope)
					{
						list2?.Add(new ScopeLogger(loggerInformation.Logger, null));
					}
				}
			}
			if (_scopeProvider != null)
			{
				list2?.Add(new ScopeLogger(null, (IExternalScopeProvider)(object)_scopeProvider));
			}
			return (list.ToArray(), list2?.ToArray());
		}

		protected virtual bool CheckDisposed()
		{
			return _disposed;
		}

		public void Dispose()
		{
			if (_disposed)
			{
				return;
			}
			_disposed = true;
			_changeTokenRegistration?.Dispose();
			foreach (ProviderRegistration providerRegistration in _providerRegistrations)
			{
				try
				{
					if (providerRegistration.ShouldDispose)
					{
						((IDisposable)providerRegistration.Provider).Dispose();
					}
				}
				catch
				{
				}
			}
		}
	}
	public class LoggerFactoryOptions
	{
		public ActivityTrackingOptions ActivityTrackingOptions { get; set; }
	}
	internal sealed class LoggerFactoryScopeProvider : IExternalScopeProvider
	{
		private sealed class Scope : IDisposable
		{
			private readonly LoggerFactoryScopeProvider _provider;

			private bool _isDisposed;

			public Scope Parent { get; }

			public object State { get; }

			internal Scope(LoggerFactoryScopeProvider provider, object state, Scope parent)
			{
				_provider = provider;
				State = state;
				Parent = parent;
			}

			public override string ToString()
			{
				return State?.ToString();
			}

			public void Dispose()
			{
				if (!_isDisposed)
				{
					_provider._currentScope.Value = Parent;
					_isDisposed = true;
				}
			}
		}

		private sealed class ActivityLogScope : IReadOnlyList<KeyValuePair<string, object>>, IReadOnlyCollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
		{
			private string _cachedToString;

			private const int MaxItems = 5;

			private KeyValuePair<string, object>[] _items = new KeyValuePair<string, object>[5];

			public int Count { get; }

			public KeyValuePair<string, object> this[int index]
			{
				get
				{
					if (index >= Count)
					{
						throw new ArgumentOutOfRangeException("index");
					}
					return _items[index];
				}
			}

			public ActivityLogScope(Activity activity, ActivityTrackingOptions activityTrackingOption)
			{
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				int num = 0;
				if ((activityTrackingOption & ActivityTrackingOptions.SpanId) != 0)
				{
					_items[num++] = new KeyValuePair<string, object>("SpanId", activity.GetSpanId());
				}
				if ((activityTrackingOption & ActivityTrackingOptions.TraceId) != 0)
				{
					_items[num++] = new KeyValuePair<string, object>("TraceId", activity.GetTraceId());
				}
				if ((activityTrackingOption & ActivityTrackingOptions.ParentId) != 0)
				{
					_items[num++] = new KeyValuePair<string, object>("ParentId", activity.GetParentId());
				}
				if ((activityTrackingOption & ActivityTrackingOptions.TraceState) != 0)
				{
					_items[num++] = new KeyValuePair<string, object>("TraceState", activity.TraceStateString);
				}
				if ((activityTrackingOption & ActivityTrackingOptions.TraceFlags) != 0)
				{
					_items[num++] = new KeyValuePair<string, object>("TraceFlags", activity.ActivityTraceFlags);
				}
				Count = num;
			}

			public override string ToString()
			{
				if (_cachedToString == null)
				{
					StringBuilder stringBuilder = new StringBuilder();
					stringBuilder.Append(_items[0].Key);
					stringBuilder.Append(':');
					stringBuilder.Append(_items[0].Value);
					for (int i = 1; i < Count; i++)
					{
						stringBuilder.Append(", ");
						stringBuilder.Append(_items[i].Key);
						stringBuilder.Append(':');
						stringBuilder.Append(_items[i].Value);
					}
					_cachedToString = stringBuilder.ToString();
				}
				return _cachedToString;
			}

			public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
			{
				int i = 0;
				while (i < Count)
				{
					yield return this[i];
					int num = i + 1;
					i = num;
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}
		}

		private sealed class ActivityBaggageLogScopeWrapper : IEnumerable<KeyValuePair<string, string>>, IEnumerable
		{
			private readonly IEnumerable<KeyValuePair<string, string>> _items;

			private StringBuilder _stringBuilder;

			public ActivityBaggageLogScopeWrapper(IEnumerable<KeyValuePair<string, string>> items)
			{
				_items = items;
			}

			public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
			{
				return _items.GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return _items.GetEnumerator();
			}

			public override string ToString()
			{
				lock (this)
				{
					IEnumerator<KeyValuePair<string, string>> enumerator = _items.GetEnumerator();
					if (!enumerator.MoveNext())
					{
						return string.Empty;
					}
					if (_stringBuilder == null)
					{
						_stringBuilder = new StringBuilder();
					}
					_stringBuilder.Append(enumerator.Current.Key);
					_stringBuilder.Append(':');
					_stringBuilder.Append(enumerator.Current.Value);
					while (enumerator.MoveNext())
					{
						_stringBuilder.Append(", ");
						_stringBuilder.Append(enumerator.Current.Key);
						_stringBuilder.Append(':');
						_stringBuilder.Append(enumerator.Current.Value);
					}
					string result = _stringBuilder.ToString();
					_stringBuilder.Clear();
					return result;
				}
			}
		}

		private readonly AsyncLocal<Scope> _currentScope = new AsyncLocal<Scope>();

		private readonly ActivityTrackingOptions _activityTrackingOption;

		public LoggerFactoryScopeProvider(ActivityTrackingOptions activityTrackingOption)
		{
			_activityTrackingOption = activityTrackingOption;
		}

		public void ForEachScope<TState>(Action<object, TState> callback, TState state)
		{
			if (_activityTrackingOption != 0)
			{
				Activity current2 = Activity.Current;
				if (current2 != null)
				{
					ActivityLogScope activityLogScope = current2.GetCustomProperty("__ActivityLogScope__") as ActivityLogScope;
					if (activityLogScope == null)
					{
						activityLogScope = new ActivityLogScope(current2, _activityTrackingOption);
						current2.SetCustomProperty("__ActivityLogScope__", (object)activityLogScope);
					}
					callback(activityLogScope, state);
					if ((_activityTrackingOption & ActivityTrackingOptions.Tags) != 0 && current2.TagObjects.GetEnumerator().MoveNext())
					{
						callback(current2.TagObjects, state);
					}
					if ((_activityTrackingOption & ActivityTrackingOptions.Baggage) != 0)
					{
						IEnumerable<KeyValuePair<string, string>> baggage = current2.Baggage;
						if (baggage.GetEnumerator().MoveNext())
						{
							ActivityBaggageLogScopeWrapper orCreateActivityBaggageLogScopeWrapper = GetOrCreateActivityBaggageLogScopeWrapper(current2, baggage);
							callback(orCreateActivityBaggageLogScopeWrapper, state);
						}
					}
				}
			}
			Report(_currentScope.Value);
			void Report(Scope current)
			{
				if (current != null)
				{
					Report(current.Parent);
					callback(current.State, state);
				}
			}
		}

		private static ActivityBaggageLogScopeWrapper GetOrCreateActivityBaggageLogScopeWrapper(Activity activity, IEnumerable<KeyValuePair<string, string>> items)
		{
			ActivityBaggageLogScopeWrapper activityBaggageLogScopeWrapper = activity.GetCustomProperty("__ActivityBaggageItemsLogScope__") as ActivityBaggageLogScopeWrapper;
			if (activityBaggageLogScopeWrapper == null)
			{
				activityBaggageLogScopeWrapper = new ActivityBaggageLogScopeWrapper(items);
				activity.SetCustomProperty("__ActivityBaggageItemsLogScope__", (object)activityBaggageLogScopeWrapper);
			}
			return activityBaggageLogScopeWrapper;
		}

		public IDisposable Push(object state)
		{
			Scope value = _currentScope.Value;
			Scope scope = new Scope(this, state, value);
			_currentScope.Value = scope;
			return scope;
		}
	}
	internal static class ActivityExtensions
	{
		public static string GetSpanId(this Activity activity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			ActivityIdFormat idFormat = activity.IdFormat;
			string text;
			if ((int)idFormat != 1)
			{
				if ((int)idFormat == 2)
				{
					ActivitySpanId spanId = activity.SpanId;
					text = ((ActivitySpanId)(ref spanId)).ToHexString();
				}
				else
				{
					text = null;
				}
			}
			else
			{
				text = activity.Id;
			}
			return text ?? string.Empty;
		}

		public static string GetTraceId(this Activity activity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			ActivityIdFormat idFormat = activity.IdFormat;
			string text;
			if ((int)idFormat != 1)
			{
				if ((int)idFormat == 2)
				{
					ActivityTraceId traceId = activity.TraceId;
					text = ((ActivityTraceId)(ref traceId)).ToHexString();
				}
				else
				{
					text = null;
				}
			}
			else
			{
				text = activity.RootId;
			}
			return text ?? string.Empty;
		}

		public static string GetParentId(this Activity activity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			ActivityIdFormat idFormat = activity.IdFormat;
			string text;
			if ((int)idFormat != 1)
			{
				if ((int)idFormat == 2)
				{
					ActivitySpanId parentSpanId = activity.ParentSpanId;
					text = ((ActivitySpanId)(ref parentSpanId)).ToHexString();
				}
				else
				{
					text = null;
				}
			}
			else
			{
				text = activity.ParentId;
			}
			return text ?? string.Empty;
		}
	}
	public class LoggerFilterOptions
	{
		public bool CaptureScopes { get; set; } = true;


		public LogLevel MinLevel { get; set; }

		public IList<LoggerFilterRule> Rules => RulesInternal;

		internal List<LoggerFilterRule> RulesInternal { get; } = new List<LoggerFilterRule>();

	}
	public class LoggerFilterRule
	{
		public string ProviderName { get; }

		public string CategoryName { get; }

		public LogLevel? LogLevel { get; }

		public Func<string, string, LogLevel, bool> Filter { get; }

		public LoggerFilterRule(string providerName, string categoryName, LogLevel? logLevel, Func<string, string, LogLevel, bool> filter)
		{
			ProviderName = providerName;
			CategoryName = categoryName;
			LogLevel = logLevel;
			Filter = filter;
		}

		public override string ToString()
		{
			return string.Format("{0}: '{1}', {2}: '{3}', {4}: '{5}', {6}: '{7}'", "ProviderName", ProviderName, "CategoryName", CategoryName, "LogLevel", LogLevel, "Filter", Filter);
		}
	}
	internal readonly struct MessageLogger
	{
		public ILogger Logger { get; }

		public string Category { get; }

		private string ProviderTypeFullName { get; }

		public LogLevel? MinLevel { get; }

		public Func<string, string, LogLevel, bool> Filter { get; }

		public MessageLogger(ILogger logger, string category, string providerTypeFullName, LogLevel? minLevel, Func<string, string, LogLevel, bool> filter)
		{
			Logger = logger;
			Category = category;
			ProviderTypeFullName = providerTypeFullName;
			MinLevel = minLevel;
			Filter = filter;
		}

		public bool IsEnabled(LogLevel level)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (MinLevel.HasValue && level < MinLevel)
			{
				return false;
			}
			if (Filter != null)
			{
				return Filter(ProviderTypeFullName, Category, level);
			}
			return true;
		}
	}
	internal readonly struct ScopeLogger
	{
		public ILogger Logger { get; }

		public IExternalScopeProvider ExternalScopeProvider { get; }

		public ScopeLogger(ILogger logger, IExternalScopeProvider externalScopeProvider)
		{
			Logger = logger;
			ExternalScopeProvider = externalScopeProvider;
		}

		public IDisposable CreateScope<TState>(TState state)
		{
			if (ExternalScopeProvider != null)
			{
				return ExternalScopeProvider.Push((object)state);
			}
			return Logger.BeginScope<TState>(state);
		}
	}
	internal readonly struct LoggerInformation
	{
		public ILogger Logger { get; }

		public string Category { get; }

		public Type ProviderType { get; }

		public bool ExternalScope { get; }

		public LoggerInformation(ILoggerProvider provider, string category)
		{
			this = default(LoggerInformation);
			ProviderType = ((object)provider).GetType();
			Logger = provider.CreateLogger(category);
			Category = category;
			ExternalScope = provider is ISupportExternalScope;
		}
	}
	internal static class LoggerRuleSelector
	{
		public static void Select(LoggerFilterOptions options, Type providerType, string category, out LogLevel? minLevel, out Func<string, string, LogLevel, bool> filter)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			filter = null;
			minLevel = options.MinLevel;
			string alias = ProviderAliasUtilities.GetAlias(providerType);
			LoggerFilterRule loggerFilterRule = null;
			foreach (LoggerFilterRule item in options.RulesInternal)
			{
				if (IsBetter(item, loggerFilterRule, providerType.FullName, category) || (!string.IsNullOrEmpty(alias) && IsBetter(item, loggerFilterRule, alias, category)))
				{
					loggerFilterRule = item;
				}
			}
			if (loggerFilterRule != null)
			{
				filter = loggerFilterRule.Filter;
				minLevel = loggerFilterRule.LogLevel;
			}
		}

		private static bool IsBetter(LoggerFilterRule rule, LoggerFilterRule current, string logger, string category)
		{
			if (rule.ProviderName != null && rule.ProviderName != logger)
			{
				return false;
			}
			string categoryName = rule.CategoryName;
			if (categoryName != null)
			{
				int num = categoryName.IndexOf('*');
				if (num != -1 && categoryName.IndexOf('*', num + 1) != -1)
				{
					throw new InvalidOperationException(System.SR.MoreThanOneWildcard);
				}
				ReadOnlySpan<char> value;
				ReadOnlySpan<char> value2;
				if (num == -1)
				{
					value = categoryName.AsSpan();
					value2 = default(ReadOnlySpan<char>);
				}
				else
				{
					value = categoryName.AsSpan(0, num);
					value2 = categoryName.AsSpan(num + 1);
				}
				if (!category.AsSpan().StartsWith(value, StringComparison.OrdinalIgnoreCase) || !category.AsSpan().EndsWith(value2, StringComparison.OrdinalIgnoreCase))
				{
					return false;
				}
			}
			if (current != null && current.ProviderName != null)
			{
				if (rule.ProviderName == null)
				{
					return false;
				}
			}
			else if (rule.ProviderName != null)
			{
				return true;
			}
			if (current != null && current.CategoryName != null)
			{
				if (rule.CategoryName == null)
				{
					return false;
				}
				if (current.CategoryName.Length > rule.CategoryName.Length)
				{
					return false;
				}
			}
			return true;
		}
	}
	internal sealed class LoggingBuilder : ILoggingBuilder
	{
		public IServiceCollection Services { get; }

		public LoggingBuilder(IServiceCollection services)
		{
			Services = services;
		}
	}
	public static class LoggingBuilderExtensions
	{
		public static ILoggingBuilder SetMinimumLevel(this ILoggingBuilder builder, LogLevel level)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			((ICollection<ServiceDescriptor>)builder.Services).Add(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>((IConfigureOptions<LoggerFilterOptions>)(object)new DefaultLoggerLevelConfigureOptions(level)));
			return builder;
		}

		public static ILoggingBuilder AddProvider(this ILoggingBuilder builder, ILoggerProvider provider)
		{
			ServiceCollectionServiceExtensions.AddSingleton<ILoggerProvider>(builder.Services, provider);
			return builder;
		}

		public static ILoggingBuilder ClearProviders(this ILoggingBuilder builder)
		{
			ServiceCollectionDescriptorExtensions.RemoveAll<ILoggerProvider>(builder.Services);
			return builder;
		}

		public static ILoggingBuilder Configure(this ILoggingBuilder builder, Action<LoggerFactoryOptions> action)
		{
			OptionsServiceCollectionExtensions.Configure<LoggerFactoryOptions>(builder.Services, action);
			return builder;
		}
	}
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
	public class ProviderAliasAttribute : Attribute
	{
		public string Alias { get; }

		public ProviderAliasAttribute(string alias)
		{
			Alias = alias;
		}
	}
	internal sealed class StaticFilterOptionsMonitor : IOptionsMonitor<LoggerFilterOptions>
	{
		public LoggerFilterOptions CurrentValue { get; }

		public StaticFilterOptionsMonitor(LoggerFilterOptions currentValue)
		{
			CurrentValue = currentValue;
		}

		public IDisposable OnChange(Action<LoggerFilterOptions, string> listener)
		{
			return null;
		}

		public LoggerFilterOptions Get(string name)
		{
			return CurrentValue;
		}
	}
	internal static class ProviderAliasUtilities
	{
		private const string AliasAttibuteTypeFullName = "Microsoft.Extensions.Logging.ProviderAliasAttribute";

		internal static string GetAlias(Type providerType)
		{
			IList<CustomAttributeData> customAttributes = CustomAttributeData.GetCustomAttributes(providerType);
			for (int i = 0; i < customAttributes.Count; i++)
			{
				CustomAttributeData customAttributeData = customAttributes[i];
				if (customAttributeData.AttributeType.FullName == "Microsoft.Extensions.Logging.ProviderAliasAttribute" && customAttributeData.ConstructorArguments.Count > 0)
				{
					return customAttributeData.ConstructorArguments[0].Value?.ToString();
				}
			}
			return null;
		}
	}
	internal sealed class NullExternalScopeProvider : IExternalScopeProvider
	{
		public static IExternalScopeProvider Instance { get; } = (IExternalScopeProvider)(object)new NullExternalScopeProvider();


		private NullExternalScopeProvider()
		{
		}

		void IExternalScopeProvider.ForEachScope<TState>(Action<object, TState> callback, TState state)
		{
		}

		IDisposable IExternalScopeProvider.Push(object state)
		{
			return NullScope.Instance;
		}
	}
	internal sealed class NullScope : IDisposable
	{
		public static NullScope Instance { get; } = new NullScope();


		private NullScope()
		{
		}

		public void Dispose()
		{
		}
	}
}

plugins/TwitchLib/Microsoft.Extensions.Options.dll

Decompiled 6 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using FxResources.Microsoft.Extensions.Options;
using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Microsoft.Extensions.Options.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyDefaultAlias("Microsoft.Extensions.Options")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Provides a strongly typed way of specifying and accessing settings using dependency injection.")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.Options")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: AssemblyVersion("6.0.0.0")]
[module: System.Runtime.CompilerServices.NullablePublicOnly(true)]
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 NullablePublicOnlyAttribute : Attribute
	{
		public readonly bool IncludesInternals;

		public NullablePublicOnlyAttribute(bool P_0)
		{
			IncludesInternals = P_0;
		}
	}
}
namespace FxResources.Microsoft.Extensions.Options
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string Error_CannotActivateAbstractOrInterface => GetResourceString("Error_CannotActivateAbstractOrInterface");

		internal static string Error_FailedBinding => GetResourceString("Error_FailedBinding");

		internal static string Error_FailedToActivate => GetResourceString("Error_FailedToActivate");

		internal static string Error_MissingParameterlessConstructor => GetResourceString("Error_MissingParameterlessConstructor");

		internal static string Error_NoConfigurationServices => GetResourceString("Error_NoConfigurationServices");

		internal static string Error_NoConfigurationServicesAndAction => GetResourceString("Error_NoConfigurationServicesAndAction");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
	internal sealed class DynamicallyAccessedMembersAttribute : Attribute
	{
		public DynamicallyAccessedMemberTypes MemberTypes { get; }

		public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
		{
			MemberTypes = memberTypes;
		}
	}
	[Flags]
	internal enum DynamicallyAccessedMemberTypes
	{
		None = 0,
		PublicParameterlessConstructor = 1,
		PublicConstructors = 3,
		NonPublicConstructors = 4,
		PublicMethods = 8,
		NonPublicMethods = 0x10,
		PublicFields = 0x20,
		NonPublicFields = 0x40,
		PublicNestedTypes = 0x80,
		NonPublicNestedTypes = 0x100,
		PublicProperties = 0x200,
		NonPublicProperties = 0x400,
		PublicEvents = 0x800,
		NonPublicEvents = 0x1000,
		Interfaces = 0x2000,
		All = -1
	}
	[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
	internal sealed class UnconditionalSuppressMessageAttribute : Attribute
	{
		public string Category { get; }

		public string CheckId { get; }

		public string? Scope { get; set; }

		public string? Target { get; set; }

		public string? MessageId { get; set; }

		public string? Justification { get; set; }

		public UnconditionalSuppressMessageAttribute(string category, string checkId)
		{
			Category = category;
			CheckId = checkId;
		}
	}
}
namespace Microsoft.Extensions.DependencyInjection
{
	public static class OptionsServiceCollectionExtensions
	{
		public static IServiceCollection AddOptions(this IServiceCollection services)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(UnnamedOptionsManager<>)));
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsManager<>)));
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Singleton(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>)));
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Transient(typeof(IOptionsFactory<>), typeof(OptionsFactory<>)));
			ServiceCollectionDescriptorExtensions.TryAdd(services, ServiceDescriptor.Singleton(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>)));
			return services;
		}

		public static IServiceCollection Configure<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
		{
			return services.Configure(Microsoft.Extensions.Options.Options.DefaultName, configureOptions);
		}

		public static IServiceCollection Configure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions) where TOptions : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			services.AddOptions();
			ServiceCollectionServiceExtensions.AddSingleton<IConfigureOptions<TOptions>>(services, (IConfigureOptions<TOptions>)new ConfigureNamedOptions<TOptions>(name, configureOptions));
			return services;
		}

		public static IServiceCollection ConfigureAll<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
		{
			return services.Configure(null, configureOptions);
		}

		public static IServiceCollection PostConfigure<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
		{
			return services.PostConfigure(Microsoft.Extensions.Options.Options.DefaultName, configureOptions);
		}

		public static IServiceCollection PostConfigure<TOptions>(this IServiceCollection services, string name, Action<TOptions> configureOptions) where TOptions : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			services.AddOptions();
			ServiceCollectionServiceExtensions.AddSingleton<IPostConfigureOptions<TOptions>>(services, (IPostConfigureOptions<TOptions>)new PostConfigureOptions<TOptions>(name, configureOptions));
			return services;
		}

		public static IServiceCollection PostConfigureAll<TOptions>(this IServiceCollection services, Action<TOptions> configureOptions) where TOptions : class
		{
			return services.PostConfigure(null, configureOptions);
		}

		public static IServiceCollection ConfigureOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TConfigureOptions>(this IServiceCollection services) where TConfigureOptions : class
		{
			return services.ConfigureOptions(typeof(TConfigureOptions));
		}

		private static IEnumerable<Type> FindConfigurationServices(Type type)
		{
			Type[] array = GetInterfacesOnType(type);
			foreach (Type type2 in array)
			{
				if (type2.IsGenericType)
				{
					Type genericTypeDefinition = type2.GetGenericTypeDefinition();
					if (genericTypeDefinition == typeof(IConfigureOptions<>) || genericTypeDefinition == typeof(IPostConfigureOptions<>) || genericTypeDefinition == typeof(IValidateOptions<>))
					{
						yield return type2;
					}
				}
			}
			[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "This method only looks for interfaces referenced in its code. The trimmer will keep the interface and thus all of its implementations in that case. The call to GetInterfaces may return less results in trimmed apps, but it will include the interfaces this method looks for if they should be there.")]
			static Type[] GetInterfacesOnType(Type t)
			{
				return t.GetInterfaces();
			}
		}

		private static void ThrowNoConfigServices(Type type)
		{
			throw new InvalidOperationException((type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Action<>)) ? System.SR.Error_NoConfigurationServicesAndAction : System.SR.Error_NoConfigurationServices);
		}

		public static IServiceCollection ConfigureOptions(this IServiceCollection services, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type configureType)
		{
			services.AddOptions();
			bool flag = false;
			foreach (Type item in FindConfigurationServices(configureType))
			{
				ServiceCollectionServiceExtensions.AddTransient(services, item, configureType);
				flag = true;
			}
			if (!flag)
			{
				ThrowNoConfigServices(configureType);
			}
			return services;
		}

		public static IServiceCollection ConfigureOptions(this IServiceCollection services, object configureInstance)
		{
			services.AddOptions();
			Type type = configureInstance.GetType();
			bool flag = false;
			foreach (Type item in FindConfigurationServices(type))
			{
				ServiceCollectionServiceExtensions.AddSingleton(services, item, configureInstance);
				flag = true;
			}
			if (!flag)
			{
				ThrowNoConfigServices(type);
			}
			return services;
		}

		public static OptionsBuilder<TOptions> AddOptions<TOptions>(this IServiceCollection services) where TOptions : class
		{
			return services.AddOptions<TOptions>(Microsoft.Extensions.Options.Options.DefaultName);
		}

		public static OptionsBuilder<TOptions> AddOptions<TOptions>(this IServiceCollection services, string name) where TOptions : class
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			services.AddOptions();
			return new OptionsBuilder<TOptions>(services, name);
		}
	}
}
namespace Microsoft.Extensions.Options
{
	public class ConfigureNamedOptions<TOptions> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Action<TOptions> Action { get; }

		public ConfigureNamedOptions(string name, Action<TOptions> action)
		{
			Name = name;
			Action = action;
		}

		public virtual void Configure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options);
			}
		}

		public void Configure(TOptions options)
		{
			Configure(Options.DefaultName, options);
		}
	}
	public class ConfigureNamedOptions<TOptions, TDep> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class where TDep : class
	{
		public string Name { get; }

		public Action<TOptions, TDep> Action { get; }

		public TDep Dependency { get; }

		public ConfigureNamedOptions(string name, TDep dependency, Action<TOptions, TDep> action)
		{
			Name = name;
			Action = action;
			Dependency = dependency;
		}

		public virtual void Configure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency);
			}
		}

		public void Configure(TOptions options)
		{
			Configure(Options.DefaultName, options);
		}
	}
	public class ConfigureNamedOptions<TOptions, TDep1, TDep2> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public ConfigureNamedOptions(string name, TDep1 dependency, TDep2 dependency2, Action<TOptions, TDep1, TDep2> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency;
			Dependency2 = dependency2;
		}

		public virtual void Configure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2);
			}
		}

		public void Configure(TOptions options)
		{
			Configure(Options.DefaultName, options);
		}
	}
	public class ConfigureNamedOptions<TOptions, TDep1, TDep2, TDep3> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class where TDep3 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2, TDep3> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public ConfigureNamedOptions(string name, TDep1 dependency, TDep2 dependency2, TDep3 dependency3, Action<TOptions, TDep1, TDep2, TDep3> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
		}

		public virtual void Configure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2, Dependency3);
			}
		}

		public void Configure(TOptions options)
		{
			Configure(Options.DefaultName, options);
		}
	}
	public class ConfigureNamedOptions<TOptions, TDep1, TDep2, TDep3, TDep4> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2, TDep3, TDep4> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public TDep4 Dependency4 { get; }

		public ConfigureNamedOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, Action<TOptions, TDep1, TDep2, TDep3, TDep4> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
			Dependency4 = dependency4;
		}

		public virtual void Configure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2, Dependency3, Dependency4);
			}
		}

		public void Configure(TOptions options)
		{
			Configure(Options.DefaultName, options);
		}
	}
	public class ConfigureNamedOptions<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> : IConfigureNamedOptions<TOptions>, IConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TDep5 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public TDep4 Dependency4 { get; }

		public TDep5 Dependency5 { get; }

		public ConfigureNamedOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, TDep5 dependency5, Action<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
			Dependency4 = dependency4;
			Dependency5 = dependency5;
		}

		public virtual void Configure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2, Dependency3, Dependency4, Dependency5);
			}
		}

		public void Configure(TOptions options)
		{
			Configure(Options.DefaultName, options);
		}
	}
	public class ConfigureOptions<TOptions> : IConfigureOptions<TOptions> where TOptions : class
	{
		public Action<TOptions> Action { get; }

		public ConfigureOptions(Action<TOptions> action)
		{
			Action = action;
		}

		public virtual void Configure(TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			Action?.Invoke(options);
		}
	}
	public interface IConfigureNamedOptions<in TOptions> : IConfigureOptions<TOptions> where TOptions : class
	{
		void Configure(string name, TOptions options);
	}
	public interface IConfigureOptions<in TOptions> where TOptions : class
	{
		void Configure(TOptions options);
	}
	public interface IOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] out TOptions> where TOptions : class
	{
		TOptions Value { get; }
	}
	public interface IOptionsChangeTokenSource<out TOptions>
	{
		string Name { get; }

		IChangeToken GetChangeToken();
	}
	public interface IOptionsFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> where TOptions : class
	{
		TOptions Create(string name);
	}
	public interface IOptionsMonitor<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] out TOptions>
	{
		TOptions CurrentValue { get; }

		TOptions Get(string name);

		IDisposable OnChange(Action<TOptions, string> listener);
	}
	public interface IOptionsMonitorCache<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> where TOptions : class
	{
		TOptions GetOrAdd(string name, Func<TOptions> createOptions);

		bool TryAdd(string name, TOptions options);

		bool TryRemove(string name);

		void Clear();
	}
	public interface IOptionsSnapshot<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] out TOptions> : IOptions<TOptions> where TOptions : class
	{
		TOptions Get(string name);
	}
	public interface IPostConfigureOptions<in TOptions> where TOptions : class
	{
		void PostConfigure(string name, TOptions options);
	}
	public interface IValidateOptions<TOptions> where TOptions : class
	{
		ValidateOptionsResult Validate(string name, TOptions options);
	}
	public static class Options
	{
		internal const DynamicallyAccessedMemberTypes DynamicallyAccessedMembers = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor;

		public static readonly string DefaultName = string.Empty;

		public static IOptions<TOptions> Create<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions>(TOptions options) where TOptions : class
		{
			return new OptionsWrapper<TOptions>(options);
		}
	}
	public class OptionsBuilder<TOptions> where TOptions : class
	{
		private const string DefaultValidationFailureMessage = "A validation error has occurred.";

		public string Name { get; }

		public IServiceCollection Services { get; }

		public OptionsBuilder(IServiceCollection services, string name)
		{
			if (services == null)
			{
				throw new ArgumentNullException("services");
			}
			Services = services;
			Name = name ?? Options.DefaultName;
		}

		public virtual OptionsBuilder<TOptions> Configure(Action<TOptions> configureOptions)
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddSingleton<IConfigureOptions<TOptions>>(Services, (IConfigureOptions<TOptions>)new ConfigureNamedOptions<TOptions>(Name, configureOptions));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Configure<TDep>(Action<TOptions, TDep> configureOptions) where TDep : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IConfigureOptions<TOptions>>)((IServiceProvider sp) => new ConfigureNamedOptions<TOptions, TDep>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Configure<TDep1, TDep2>(Action<TOptions, TDep1, TDep2> configureOptions) where TDep1 : class where TDep2 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IConfigureOptions<TOptions>>)((IServiceProvider sp) => new ConfigureNamedOptions<TOptions, TDep1, TDep2>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Configure<TDep1, TDep2, TDep3>(Action<TOptions, TDep1, TDep2, TDep3> configureOptions) where TDep1 : class where TDep2 : class where TDep3 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IConfigureOptions<TOptions>>)((IServiceProvider sp) => new ConfigureNamedOptions<TOptions, TDep1, TDep2, TDep3>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Configure<TDep1, TDep2, TDep3, TDep4>(Action<TOptions, TDep1, TDep2, TDep3, TDep4> configureOptions) where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IConfigureOptions<TOptions>>)((IServiceProvider sp) => new ConfigureNamedOptions<TOptions, TDep1, TDep2, TDep3, TDep4>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep4>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Configure<TDep1, TDep2, TDep3, TDep4, TDep5>(Action<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> configureOptions) where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TDep5 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IConfigureOptions<TOptions>>)((IServiceProvider sp) => new ConfigureNamedOptions<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep4>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep5>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> PostConfigure(Action<TOptions> configureOptions)
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddSingleton<IPostConfigureOptions<TOptions>>(Services, (IPostConfigureOptions<TOptions>)new PostConfigureOptions<TOptions>(Name, configureOptions));
			return this;
		}

		public virtual OptionsBuilder<TOptions> PostConfigure<TDep>(Action<TOptions, TDep> configureOptions) where TDep : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IPostConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IPostConfigureOptions<TOptions>>)((IServiceProvider sp) => new PostConfigureOptions<TOptions, TDep>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> PostConfigure<TDep1, TDep2>(Action<TOptions, TDep1, TDep2> configureOptions) where TDep1 : class where TDep2 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IPostConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IPostConfigureOptions<TOptions>>)((IServiceProvider sp) => new PostConfigureOptions<TOptions, TDep1, TDep2>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> PostConfigure<TDep1, TDep2, TDep3>(Action<TOptions, TDep1, TDep2, TDep3> configureOptions) where TDep1 : class where TDep2 : class where TDep3 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IPostConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IPostConfigureOptions<TOptions>>)((IServiceProvider sp) => new PostConfigureOptions<TOptions, TDep1, TDep2, TDep3>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> PostConfigure<TDep1, TDep2, TDep3, TDep4>(Action<TOptions, TDep1, TDep2, TDep3, TDep4> configureOptions) where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IPostConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IPostConfigureOptions<TOptions>>)((IServiceProvider sp) => new PostConfigureOptions<TOptions, TDep1, TDep2, TDep3, TDep4>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep4>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> PostConfigure<TDep1, TDep2, TDep3, TDep4, TDep5>(Action<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> configureOptions) where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TDep5 : class
		{
			if (configureOptions == null)
			{
				throw new ArgumentNullException("configureOptions");
			}
			ServiceCollectionServiceExtensions.AddTransient<IPostConfigureOptions<TOptions>>(Services, (Func<IServiceProvider, IPostConfigureOptions<TOptions>>)((IServiceProvider sp) => new PostConfigureOptions<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep4>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep5>(sp), configureOptions)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Validate(Func<TOptions, bool> validation)
		{
			return Validate(validation, "A validation error has occurred.");
		}

		public virtual OptionsBuilder<TOptions> Validate(Func<TOptions, bool> validation, string failureMessage)
		{
			if (validation == null)
			{
				throw new ArgumentNullException("validation");
			}
			ServiceCollectionServiceExtensions.AddSingleton<IValidateOptions<TOptions>>(Services, (IValidateOptions<TOptions>)new ValidateOptions<TOptions>(Name, validation, failureMessage));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep>(Func<TOptions, TDep, bool> validation)
		{
			return Validate(validation, "A validation error has occurred.");
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep>(Func<TOptions, TDep, bool> validation, string failureMessage)
		{
			if (validation == null)
			{
				throw new ArgumentNullException("validation");
			}
			ServiceCollectionServiceExtensions.AddTransient<IValidateOptions<TOptions>>(Services, (Func<IServiceProvider, IValidateOptions<TOptions>>)((IServiceProvider sp) => new ValidateOptions<TOptions, TDep>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep>(sp), validation, failureMessage)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2>(Func<TOptions, TDep1, TDep2, bool> validation)
		{
			return Validate(validation, "A validation error has occurred.");
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2>(Func<TOptions, TDep1, TDep2, bool> validation, string failureMessage)
		{
			if (validation == null)
			{
				throw new ArgumentNullException("validation");
			}
			ServiceCollectionServiceExtensions.AddTransient<IValidateOptions<TOptions>>(Services, (Func<IServiceProvider, IValidateOptions<TOptions>>)((IServiceProvider sp) => new ValidateOptions<TOptions, TDep1, TDep2>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), validation, failureMessage)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2, TDep3>(Func<TOptions, TDep1, TDep2, TDep3, bool> validation)
		{
			return Validate(validation, "A validation error has occurred.");
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2, TDep3>(Func<TOptions, TDep1, TDep2, TDep3, bool> validation, string failureMessage)
		{
			if (validation == null)
			{
				throw new ArgumentNullException("validation");
			}
			ServiceCollectionServiceExtensions.AddTransient<IValidateOptions<TOptions>>(Services, (Func<IServiceProvider, IValidateOptions<TOptions>>)((IServiceProvider sp) => new ValidateOptions<TOptions, TDep1, TDep2, TDep3>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), validation, failureMessage)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2, TDep3, TDep4>(Func<TOptions, TDep1, TDep2, TDep3, TDep4, bool> validation)
		{
			return Validate(validation, "A validation error has occurred.");
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2, TDep3, TDep4>(Func<TOptions, TDep1, TDep2, TDep3, TDep4, bool> validation, string failureMessage)
		{
			if (validation == null)
			{
				throw new ArgumentNullException("validation");
			}
			ServiceCollectionServiceExtensions.AddTransient<IValidateOptions<TOptions>>(Services, (Func<IServiceProvider, IValidateOptions<TOptions>>)((IServiceProvider sp) => new ValidateOptions<TOptions, TDep1, TDep2, TDep3, TDep4>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep4>(sp), validation, failureMessage)));
			return this;
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2, TDep3, TDep4, TDep5>(Func<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5, bool> validation)
		{
			return Validate(validation, "A validation error has occurred.");
		}

		public virtual OptionsBuilder<TOptions> Validate<TDep1, TDep2, TDep3, TDep4, TDep5>(Func<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5, bool> validation, string failureMessage)
		{
			if (validation == null)
			{
				throw new ArgumentNullException("validation");
			}
			ServiceCollectionServiceExtensions.AddTransient<IValidateOptions<TOptions>>(Services, (Func<IServiceProvider, IValidateOptions<TOptions>>)((IServiceProvider sp) => new ValidateOptions<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5>(Name, ServiceProviderServiceExtensions.GetRequiredService<TDep1>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep2>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep3>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep4>(sp), ServiceProviderServiceExtensions.GetRequiredService<TDep5>(sp), validation, failureMessage)));
			return this;
		}
	}
	public class OptionsCache<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : IOptionsMonitorCache<TOptions> where TOptions : class
	{
		private readonly ConcurrentDictionary<string, Lazy<TOptions>> _cache = new ConcurrentDictionary<string, Lazy<TOptions>>(1, 31, StringComparer.Ordinal);

		public void Clear()
		{
			_cache.Clear();
		}

		public virtual TOptions GetOrAdd(string name, Func<TOptions> createOptions)
		{
			if (createOptions == null)
			{
				throw new ArgumentNullException("createOptions");
			}
			name = name ?? Options.DefaultName;
			if (!_cache.TryGetValue(name, out var value))
			{
				value = _cache.GetOrAdd(name, new Lazy<TOptions>(createOptions));
			}
			return value.Value;
		}

		internal bool TryGetValue(string name, out TOptions options)
		{
			if (_cache.TryGetValue(name ?? Options.DefaultName, out var value))
			{
				options = value.Value;
				return true;
			}
			options = null;
			return false;
		}

		public virtual bool TryAdd(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			return _cache.TryAdd(name ?? Options.DefaultName, new Lazy<TOptions>(() => options));
		}

		public virtual bool TryRemove(string name)
		{
			Lazy<TOptions> value;
			return _cache.TryRemove(name ?? Options.DefaultName, out value);
		}
	}
	public class OptionsFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : IOptionsFactory<TOptions> where TOptions : class
	{
		private readonly IConfigureOptions<TOptions>[] _setups;

		private readonly IPostConfigureOptions<TOptions>[] _postConfigures;

		private readonly IValidateOptions<TOptions>[] _validations;

		public OptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IPostConfigureOptions<TOptions>> postConfigures)
			: this(setups, postConfigures, (IEnumerable<IValidateOptions<TOptions>>)Array.Empty<IValidateOptions<TOptions>>())
		{
		}

		public OptionsFactory(IEnumerable<IConfigureOptions<TOptions>> setups, IEnumerable<IPostConfigureOptions<TOptions>> postConfigures, IEnumerable<IValidateOptions<TOptions>> validations)
		{
			_setups = (setups as IConfigureOptions<TOptions>[]) ?? new List<IConfigureOptions<TOptions>>(setups).ToArray();
			_postConfigures = (postConfigures as IPostConfigureOptions<TOptions>[]) ?? new List<IPostConfigureOptions<TOptions>>(postConfigures).ToArray();
			_validations = (validations as IValidateOptions<TOptions>[]) ?? new List<IValidateOptions<TOptions>>(validations).ToArray();
		}

		public TOptions Create(string name)
		{
			TOptions val = CreateInstance(name);
			IConfigureOptions<TOptions>[] setups = _setups;
			foreach (IConfigureOptions<TOptions> configureOptions in setups)
			{
				if (configureOptions is IConfigureNamedOptions<TOptions> configureNamedOptions)
				{
					configureNamedOptions.Configure(name, val);
				}
				else if (name == Options.DefaultName)
				{
					configureOptions.Configure(val);
				}
			}
			IPostConfigureOptions<TOptions>[] postConfigures = _postConfigures;
			foreach (IPostConfigureOptions<TOptions> postConfigureOptions in postConfigures)
			{
				postConfigureOptions.PostConfigure(name, val);
			}
			if (_validations != null)
			{
				List<string> list = new List<string>();
				IValidateOptions<TOptions>[] validations = _validations;
				foreach (IValidateOptions<TOptions> validateOptions in validations)
				{
					ValidateOptionsResult validateOptionsResult = validateOptions.Validate(name, val);
					if (validateOptionsResult != null && validateOptionsResult.Failed)
					{
						list.AddRange(validateOptionsResult.Failures);
					}
				}
				if (list.Count > 0)
				{
					throw new OptionsValidationException(name, typeof(TOptions), list);
				}
			}
			return val;
		}

		protected virtual TOptions CreateInstance(string name)
		{
			return Activator.CreateInstance<TOptions>();
		}
	}
	public class OptionsManager<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : IOptions<TOptions>, IOptionsSnapshot<TOptions> where TOptions : class
	{
		private readonly IOptionsFactory<TOptions> _factory;

		private readonly OptionsCache<TOptions> _cache = new OptionsCache<TOptions>();

		public TOptions Value => Get(Options.DefaultName);

		public OptionsManager(IOptionsFactory<TOptions> factory)
		{
			_factory = factory;
		}

		public virtual TOptions Get(string name)
		{
			name = name ?? Options.DefaultName;
			if (!_cache.TryGetValue(name, out var options))
			{
				IOptionsFactory<TOptions> localFactory = _factory;
				string localName = name;
				return _cache.GetOrAdd(name, () => localFactory.Create(localName));
			}
			return options;
		}
	}
	public class OptionsMonitor<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : IOptionsMonitor<TOptions>, IDisposable where TOptions : class
	{
		internal sealed class ChangeTrackerDisposable : IDisposable
		{
			private readonly Action<TOptions, string> _listener;

			private readonly OptionsMonitor<TOptions> _monitor;

			public ChangeTrackerDisposable(OptionsMonitor<TOptions> monitor, Action<TOptions, string> listener)
			{
				_listener = listener;
				_monitor = monitor;
			}

			public void OnChange(TOptions options, string name)
			{
				_listener(options, name);
			}

			public void Dispose()
			{
				_monitor._onChange -= OnChange;
			}
		}

		private readonly IOptionsMonitorCache<TOptions> _cache;

		private readonly IOptionsFactory<TOptions> _factory;

		private readonly List<IDisposable> _registrations = new List<IDisposable>();

		public TOptions CurrentValue => Get(Options.DefaultName);

		internal event Action<TOptions, string> _onChange;

		public OptionsMonitor(IOptionsFactory<TOptions> factory, IEnumerable<IOptionsChangeTokenSource<TOptions>> sources, IOptionsMonitorCache<TOptions> cache)
		{
			_factory = factory;
			_cache = cache;
			if (sources is IOptionsChangeTokenSource<TOptions>[] array)
			{
				IOptionsChangeTokenSource<TOptions>[] array2 = array;
				foreach (IOptionsChangeTokenSource<TOptions> source2 in array2)
				{
					RegisterSource(source2);
					void RegisterSource(IOptionsChangeTokenSource<TOptions> source)
					{
						IDisposable item = ChangeToken.OnChange<string>((Func<IChangeToken>)(() => source.GetChangeToken()), (Action<string>)delegate(string name)
						{
							InvokeChanged(name);
						}, source.Name);
						_registrations.Add(item);
					}
				}
				return;
			}
			foreach (IOptionsChangeTokenSource<TOptions> source3 in sources)
			{
				RegisterSource(source3);
			}
		}

		private void InvokeChanged(string name)
		{
			name = name ?? Options.DefaultName;
			_cache.TryRemove(name);
			TOptions arg = Get(name);
			if (this._onChange != null)
			{
				this._onChange(arg, name);
			}
		}

		public virtual TOptions Get(string name)
		{
			name = name ?? Options.DefaultName;
			return _cache.GetOrAdd(name, () => _factory.Create(name));
		}

		public IDisposable OnChange(Action<TOptions, string> listener)
		{
			ChangeTrackerDisposable changeTrackerDisposable = new ChangeTrackerDisposable(this, listener);
			_onChange += changeTrackerDisposable.OnChange;
			return changeTrackerDisposable;
		}

		public void Dispose()
		{
			foreach (IDisposable registration in _registrations)
			{
				registration.Dispose();
			}
			_registrations.Clear();
		}
	}
	public static class OptionsMonitorExtensions
	{
		public static IDisposable OnChange<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions>(this IOptionsMonitor<TOptions> monitor, Action<TOptions> listener)
		{
			return monitor.OnChange(delegate(TOptions o, string _)
			{
				listener(o);
			});
		}
	}
	public class OptionsValidationException : Exception
	{
		public string OptionsName { get; }

		public Type OptionsType { get; }

		public IEnumerable<string> Failures { get; }

		public override string Message => string.Join("; ", Failures);

		public OptionsValidationException(string optionsName, Type optionsType, IEnumerable<string> failureMessages)
		{
			Failures = failureMessages ?? new List<string>();
			OptionsType = optionsType ?? throw new ArgumentNullException("optionsType");
			OptionsName = optionsName ?? throw new ArgumentNullException("optionsName");
		}
	}
	public class OptionsWrapper<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : IOptions<TOptions> where TOptions : class
	{
		public TOptions Value { get; }

		public OptionsWrapper(TOptions options)
		{
			Value = options;
		}
	}
	public class PostConfigureOptions<TOptions> : IPostConfigureOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Action<TOptions> Action { get; }

		public PostConfigureOptions(string name, Action<TOptions> action)
		{
			Name = name;
			Action = action;
		}

		public virtual void PostConfigure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options);
			}
		}
	}
	public class PostConfigureOptions<TOptions, TDep> : IPostConfigureOptions<TOptions> where TOptions : class where TDep : class
	{
		public string Name { get; }

		public Action<TOptions, TDep> Action { get; }

		public TDep Dependency { get; }

		public PostConfigureOptions(string name, TDep dependency, Action<TOptions, TDep> action)
		{
			Name = name;
			Action = action;
			Dependency = dependency;
		}

		public virtual void PostConfigure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency);
			}
		}

		public void PostConfigure(TOptions options)
		{
			PostConfigure(Options.DefaultName, options);
		}
	}
	public class PostConfigureOptions<TOptions, TDep1, TDep2> : IPostConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public PostConfigureOptions(string name, TDep1 dependency, TDep2 dependency2, Action<TOptions, TDep1, TDep2> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency;
			Dependency2 = dependency2;
		}

		public virtual void PostConfigure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2);
			}
		}

		public void PostConfigure(TOptions options)
		{
			PostConfigure(Options.DefaultName, options);
		}
	}
	public class PostConfigureOptions<TOptions, TDep1, TDep2, TDep3> : IPostConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class where TDep3 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2, TDep3> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public PostConfigureOptions(string name, TDep1 dependency, TDep2 dependency2, TDep3 dependency3, Action<TOptions, TDep1, TDep2, TDep3> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
		}

		public virtual void PostConfigure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2, Dependency3);
			}
		}

		public void PostConfigure(TOptions options)
		{
			PostConfigure(Options.DefaultName, options);
		}
	}
	public class PostConfigureOptions<TOptions, TDep1, TDep2, TDep3, TDep4> : IPostConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2, TDep3, TDep4> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public TDep4 Dependency4 { get; }

		public PostConfigureOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, Action<TOptions, TDep1, TDep2, TDep3, TDep4> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
			Dependency4 = dependency4;
		}

		public virtual void PostConfigure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2, Dependency3, Dependency4);
			}
		}

		public void PostConfigure(TOptions options)
		{
			PostConfigure(Options.DefaultName, options);
		}
	}
	public class PostConfigureOptions<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> : IPostConfigureOptions<TOptions> where TOptions : class where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TDep5 : class
	{
		public string Name { get; }

		public Action<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> Action { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public TDep4 Dependency4 { get; }

		public TDep5 Dependency5 { get; }

		public PostConfigureOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, TDep5 dependency5, Action<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> action)
		{
			Name = name;
			Action = action;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
			Dependency4 = dependency4;
			Dependency5 = dependency5;
		}

		public virtual void PostConfigure(string name, TOptions options)
		{
			if (options == null)
			{
				throw new ArgumentNullException("options");
			}
			if (Name == null || name == Name)
			{
				Action?.Invoke(options, Dependency1, Dependency2, Dependency3, Dependency4, Dependency5);
			}
		}

		public void PostConfigure(TOptions options)
		{
			PostConfigure(Options.DefaultName, options);
		}
	}
	internal sealed class UnnamedOptionsManager<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TOptions> : IOptions<TOptions> where TOptions : class
	{
		private readonly IOptionsFactory<TOptions> _factory;

		private volatile object _syncObj;

		private volatile TOptions _value;

		public TOptions Value
		{
			get
			{
				TOptions value = _value;
				if (value != null)
				{
					return value;
				}
				lock (_syncObj ?? Interlocked.CompareExchange(ref _syncObj, new object(), null) ?? _syncObj)
				{
					return _value ?? (_value = _factory.Create(Options.DefaultName));
				}
			}
		}

		public UnnamedOptionsManager(IOptionsFactory<TOptions> factory)
		{
			_factory = factory;
		}
	}
	public class ValidateOptions<TOptions> : IValidateOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Func<TOptions, bool> Validation { get; }

		public string FailureMessage { get; }

		public ValidateOptions(string name, Func<TOptions, bool> validation, string failureMessage)
		{
			Name = name;
			Validation = validation;
			FailureMessage = failureMessage;
		}

		public ValidateOptionsResult Validate(string name, TOptions options)
		{
			if (Name == null || name == Name)
			{
				if ((Validation?.Invoke(options)).Value)
				{
					return ValidateOptionsResult.Success;
				}
				return ValidateOptionsResult.Fail(FailureMessage);
			}
			return ValidateOptionsResult.Skip;
		}
	}
	public class ValidateOptions<TOptions, TDep> : IValidateOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Func<TOptions, TDep, bool> Validation { get; }

		public string FailureMessage { get; }

		public TDep Dependency { get; }

		public ValidateOptions(string name, TDep dependency, Func<TOptions, TDep, bool> validation, string failureMessage)
		{
			Name = name;
			Validation = validation;
			FailureMessage = failureMessage;
			Dependency = dependency;
		}

		public ValidateOptionsResult Validate(string name, TOptions options)
		{
			if (Name == null || name == Name)
			{
				if ((Validation?.Invoke(options, Dependency)).Value)
				{
					return ValidateOptionsResult.Success;
				}
				return ValidateOptionsResult.Fail(FailureMessage);
			}
			return ValidateOptionsResult.Skip;
		}
	}
	public class ValidateOptions<TOptions, TDep1, TDep2> : IValidateOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Func<TOptions, TDep1, TDep2, bool> Validation { get; }

		public string FailureMessage { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public ValidateOptions(string name, TDep1 dependency1, TDep2 dependency2, Func<TOptions, TDep1, TDep2, bool> validation, string failureMessage)
		{
			Name = name;
			Validation = validation;
			FailureMessage = failureMessage;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
		}

		public ValidateOptionsResult Validate(string name, TOptions options)
		{
			if (Name == null || name == Name)
			{
				if ((Validation?.Invoke(options, Dependency1, Dependency2)).Value)
				{
					return ValidateOptionsResult.Success;
				}
				return ValidateOptionsResult.Fail(FailureMessage);
			}
			return ValidateOptionsResult.Skip;
		}
	}
	public class ValidateOptions<TOptions, TDep1, TDep2, TDep3> : IValidateOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Func<TOptions, TDep1, TDep2, TDep3, bool> Validation { get; }

		public string FailureMessage { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public ValidateOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, Func<TOptions, TDep1, TDep2, TDep3, bool> validation, string failureMessage)
		{
			Name = name;
			Validation = validation;
			FailureMessage = failureMessage;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
		}

		public ValidateOptionsResult Validate(string name, TOptions options)
		{
			if (Name == null || name == Name)
			{
				if ((Validation?.Invoke(options, Dependency1, Dependency2, Dependency3)).Value)
				{
					return ValidateOptionsResult.Success;
				}
				return ValidateOptionsResult.Fail(FailureMessage);
			}
			return ValidateOptionsResult.Skip;
		}
	}
	public class ValidateOptions<TOptions, TDep1, TDep2, TDep3, TDep4> : IValidateOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Func<TOptions, TDep1, TDep2, TDep3, TDep4, bool> Validation { get; }

		public string FailureMessage { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public TDep4 Dependency4 { get; }

		public ValidateOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, Func<TOptions, TDep1, TDep2, TDep3, TDep4, bool> validation, string failureMessage)
		{
			Name = name;
			Validation = validation;
			FailureMessage = failureMessage;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
			Dependency4 = dependency4;
		}

		public ValidateOptionsResult Validate(string name, TOptions options)
		{
			if (Name == null || name == Name)
			{
				if ((Validation?.Invoke(options, Dependency1, Dependency2, Dependency3, Dependency4)).Value)
				{
					return ValidateOptionsResult.Success;
				}
				return ValidateOptionsResult.Fail(FailureMessage);
			}
			return ValidateOptionsResult.Skip;
		}
	}
	public class ValidateOptions<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5> : IValidateOptions<TOptions> where TOptions : class
	{
		public string Name { get; }

		public Func<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5, bool> Validation { get; }

		public string FailureMessage { get; }

		public TDep1 Dependency1 { get; }

		public TDep2 Dependency2 { get; }

		public TDep3 Dependency3 { get; }

		public TDep4 Dependency4 { get; }

		public TDep5 Dependency5 { get; }

		public ValidateOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, TDep5 dependency5, Func<TOptions, TDep1, TDep2, TDep3, TDep4, TDep5, bool> validation, string failureMessage)
		{
			Name = name;
			Validation = validation;
			FailureMessage = failureMessage;
			Dependency1 = dependency1;
			Dependency2 = dependency2;
			Dependency3 = dependency3;
			Dependency4 = dependency4;
			Dependency5 = dependency5;
		}

		public ValidateOptionsResult Validate(string name, TOptions options)
		{
			if (Name == null || name == Name)
			{
				if ((Validation?.Invoke(options, Dependency1, Dependency2, Dependency3, Dependency4, Dependency5)).Value)
				{
					return ValidateOptionsResult.Success;
				}
				return ValidateOptionsResult.Fail(FailureMessage);
			}
			return ValidateOptionsResult.Skip;
		}
	}
	public class ValidateOptionsResult
	{
		public static readonly ValidateOptionsResult Skip = new ValidateOptionsResult
		{
			Skipped = true
		};

		public static readonly ValidateOptionsResult Success = new ValidateOptionsResult
		{
			Succeeded = true
		};

		public bool Succeeded { get; protected set; }

		public bool Skipped { get; protected set; }

		public bool Failed { get; protected set; }

		public string FailureMessage { get; protected set; }

		public IEnumerable<string> Failures { get; protected set; }

		public static ValidateOptionsResult Fail(string failureMessage)
		{
			ValidateOptionsResult validateOptionsResult = new ValidateOptionsResult();
			validateOptionsResult.Failed = true;
			validateOptionsResult.FailureMessage = failureMessage;
			validateOptionsResult.Failures = new string[1] { failureMessage };
			return validateOptionsResult;
		}

		public static ValidateOptionsResult Fail(IEnumerable<string> failures)
		{
			return new ValidateOptionsResult
			{
				Failed = true,
				FailureMessage = string.Join("; ", failures),
				Failures = failures
			};
		}
	}
}

plugins/TwitchLib/Microsoft.Extensions.Primitives.dll

Decompiled 6 months ago
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics.Hashing;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using FxResources.Microsoft.Extensions.Primitives;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: CLSCompliant(true)]
[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)]
[assembly: AssemblyDefaultAlias("Microsoft.Extensions.Primitives")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyMetadata(".NETFrameworkAssembly", "")]
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: AssemblyMetadata("PreferInbox", "True")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyDescription("Primitives shared by framework extensions. Commonly used types include:\r\n\r\nCommonly Used Types:\r\nMicrosoft.Extensions.Primitives.IChangeToken\r\nMicrosoft.Extensions.Primitives.StringValues\r\nMicrosoft.Extensions.Primitives.StringSegment")]
[assembly: AssemblyFileVersion("6.0.21.52210")]
[assembly: AssemblyInformationalVersion("6.0.0+4822e3c3aa77eb82b2fb33c9321f923cf11ddde6")]
[assembly: AssemblyProduct("Microsoft® .NET")]
[assembly: AssemblyTitle("Microsoft.Extensions.Primitives")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("6.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsByRefLikeAttribute : Attribute
	{
	}
}
namespace FxResources.Microsoft.Extensions.Primitives
{
	internal static class SR
	{
	}
}
namespace System
{
	internal static class SR
	{
		private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled) && isEnabled;

		private static ResourceManager s_resourceManager;

		internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR)));

		internal static string Argument_InvalidOffsetLength => GetResourceString("Argument_InvalidOffsetLength");

		internal static string Argument_InvalidOffsetLengthStringSegment => GetResourceString("Argument_InvalidOffsetLengthStringSegment");

		internal static string Capacity_CannotChangeAfterWriteStarted => GetResourceString("Capacity_CannotChangeAfterWriteStarted");

		internal static string Capacity_NotEnough => GetResourceString("Capacity_NotEnough");

		internal static string Capacity_NotUsedEntirely => GetResourceString("Capacity_NotUsedEntirely");

		private static bool UsingResourceKeys()
		{
			return s_usingResourceKeys;
		}

		internal static string GetResourceString(string resourceKey)
		{
			if (UsingResourceKeys())
			{
				return resourceKey;
			}
			string result = null;
			try
			{
				result = ResourceManager.GetString(resourceKey);
			}
			catch (MissingManifestResourceException)
			{
			}
			return result;
		}

		internal static string GetResourceString(string resourceKey, string defaultString)
		{
			string resourceString = GetResourceString(resourceKey);
			if (!(resourceKey == resourceString) && resourceString != null)
			{
				return resourceString;
			}
			return defaultString;
		}

		internal static string Format(string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(resourceFormat, p1);
		}

		internal static string Format(string resourceFormat, object p1, object p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(resourceFormat, p1, p2);
		}

		internal static string Format(string resourceFormat, object p1, object p2, object p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(resourceFormat, p1, p2, p3);
		}

		internal static string Format(string resourceFormat, params object[] args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(resourceFormat, args);
			}
			return resourceFormat;
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, object p1)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1);
			}
			return string.Format(provider, resourceFormat, p1);
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2);
			}
			return string.Format(provider, resourceFormat, p1, p2);
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, object p1, object p2, object p3)
		{
			if (UsingResourceKeys())
			{
				return string.Join(", ", resourceFormat, p1, p2, p3);
			}
			return string.Format(provider, resourceFormat, p1, p2, p3);
		}

		internal static string Format(IFormatProvider provider, string resourceFormat, params object[] args)
		{
			if (args != null)
			{
				if (UsingResourceKeys())
				{
					return resourceFormat + ", " + string.Join(", ", args);
				}
				return string.Format(provider, resourceFormat, args);
			}
			return resourceFormat;
		}
	}
}
namespace System.Text
{
	internal ref struct ValueStringBuilder
	{
		private char[] _arrayToReturnToPool;

		private Span<char> _chars;

		private int _pos;

		public int Length
		{
			get
			{
				return _pos;
			}
			set
			{
				_pos = value;
			}
		}

		public int Capacity => _chars.Length;

		public ref char this[int index] => ref _chars[index];

		public Span<char> RawChars => _chars;

		public ValueStringBuilder(Span<char> initialBuffer)
		{
			_arrayToReturnToPool = null;
			_chars = initialBuffer;
			_pos = 0;
		}

		public ValueStringBuilder(int initialCapacity)
		{
			_arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialCapacity);
			_chars = _arrayToReturnToPool;
			_pos = 0;
		}

		public void EnsureCapacity(int capacity)
		{
			if ((uint)capacity > (uint)_chars.Length)
			{
				Grow(capacity - _pos);
			}
		}

		public ref char GetPinnableReference()
		{
			return ref MemoryMarshal.GetReference(_chars);
		}

		public ref char GetPinnableReference(bool terminate)
		{
			if (terminate)
			{
				EnsureCapacity(Length + 1);
				_chars[Length] = '\0';
			}
			return ref MemoryMarshal.GetReference(_chars);
		}

		public override string ToString()
		{
			string result = _chars.Slice(0, _pos).ToString();
			Dispose();
			return result;
		}

		public ReadOnlySpan<char> AsSpan(bool terminate)
		{
			if (terminate)
			{
				EnsureCapacity(Length + 1);
				_chars[Length] = '\0';
			}
			return _chars.Slice(0, _pos);
		}

		public ReadOnlySpan<char> AsSpan()
		{
			return _chars.Slice(0, _pos);
		}

		public ReadOnlySpan<char> AsSpan(int start)
		{
			return _chars.Slice(start, _pos - start);
		}

		public ReadOnlySpan<char> AsSpan(int start, int length)
		{
			return _chars.Slice(start, length);
		}

		public bool TryCopyTo(Span<char> destination, out int charsWritten)
		{
			if (_chars.Slice(0, _pos).TryCopyTo(destination))
			{
				charsWritten = _pos;
				Dispose();
				return true;
			}
			charsWritten = 0;
			Dispose();
			return false;
		}

		public void Insert(int index, char value, int count)
		{
			if (_pos > _chars.Length - count)
			{
				Grow(count);
			}
			int length = _pos - index;
			_chars.Slice(index, length).CopyTo(_chars.Slice(index + count));
			_chars.Slice(index, count).Fill(value);
			_pos += count;
		}

		public void Insert(int index, string s)
		{
			if (s != null)
			{
				int length = s.Length;
				if (_pos > _chars.Length - length)
				{
					Grow(length);
				}
				int length2 = _pos - index;
				_chars.Slice(index, length2).CopyTo(_chars.Slice(index + length));
				s.AsSpan().CopyTo(_chars.Slice(index));
				_pos += length;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Append(char c)
		{
			int pos = _pos;
			if ((uint)pos < (uint)_chars.Length)
			{
				_chars[pos] = c;
				_pos = pos + 1;
			}
			else
			{
				GrowAndAppend(c);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Append(string s)
		{
			if (s != null)
			{
				int pos = _pos;
				if (s.Length == 1 && (uint)pos < (uint)_chars.Length)
				{
					_chars[pos] = s[0];
					_pos = pos + 1;
				}
				else
				{
					AppendSlow(s);
				}
			}
		}

		private void AppendSlow(string s)
		{
			int pos = _pos;
			if (pos > _chars.Length - s.Length)
			{
				Grow(s.Length);
			}
			s.AsSpan().CopyTo(_chars.Slice(pos));
			_pos += s.Length;
		}

		public void Append(char c, int count)
		{
			if (_pos > _chars.Length - count)
			{
				Grow(count);
			}
			Span<char> span = _chars.Slice(_pos, count);
			for (int i = 0; i < span.Length; i++)
			{
				span[i] = c;
			}
			_pos += count;
		}

		public unsafe void Append(char* value, int length)
		{
			int pos = _pos;
			if (pos > _chars.Length - length)
			{
				Grow(length);
			}
			Span<char> span = _chars.Slice(_pos, length);
			for (int i = 0; i < span.Length; i++)
			{
				span[i] = *(value++);
			}
			_pos += length;
		}

		public void Append(ReadOnlySpan<char> value)
		{
			int pos = _pos;
			if (pos > _chars.Length - value.Length)
			{
				Grow(value.Length);
			}
			value.CopyTo(_chars.Slice(_pos));
			_pos += value.Length;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Span<char> AppendSpan(int length)
		{
			int pos = _pos;
			if (pos > _chars.Length - length)
			{
				Grow(length);
			}
			_pos = pos + length;
			return _chars.Slice(pos, length);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void GrowAndAppend(char c)
		{
			Grow(1);
			Append(c);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private void Grow(int additionalCapacityBeyondPos)
		{
			char[] array = ArrayPool<char>.Shared.Rent((int)Math.Max((uint)(_pos + additionalCapacityBeyondPos), (uint)(_chars.Length * 2)));
			_chars.Slice(0, _pos).CopyTo(array);
			char[] arrayToReturnToPool = _arrayToReturnToPool;
			_chars = (_arrayToReturnToPool = array);
			if (arrayToReturnToPool != null)
			{
				ArrayPool<char>.Shared.Return(arrayToReturnToPool);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Dispose()
		{
			char[] arrayToReturnToPool = _arrayToReturnToPool;
			this = default(System.Text.ValueStringBuilder);
			if (arrayToReturnToPool != null)
			{
				ArrayPool<char>.Shared.Return(arrayToReturnToPool);
			}
		}
	}
}
namespace System.Numerics.Hashing
{
	internal static class HashHelpers
	{
		public static int Combine(int h1, int h2)
		{
			uint num = (uint)(h1 << 5) | ((uint)h1 >> 27);
			return ((int)num + h1) ^ h2;
		}
	}
}
namespace Microsoft.Extensions.Primitives
{
	public class CancellationChangeToken : IChangeToken
	{
		private sealed class NullDisposable : IDisposable
		{
			public static readonly NullDisposable Instance = new NullDisposable();

			public void Dispose()
			{
			}
		}

		public bool ActiveChangeCallbacks { get; private set; } = true;


		public bool HasChanged => Token.IsCancellationRequested;

		private CancellationToken Token { get; }

		public CancellationChangeToken(CancellationToken cancellationToken)
		{
			Token = cancellationToken;
		}

		public IDisposable RegisterChangeCallback(Action<object> callback, object state)
		{
			bool flag = false;
			if (!ExecutionContext.IsFlowSuppressed())
			{
				ExecutionContext.SuppressFlow();
				flag = true;
			}
			try
			{
				return Token.Register(callback, state);
			}
			catch (ObjectDisposedException)
			{
				ActiveChangeCallbacks = false;
			}
			finally
			{
				if (flag)
				{
					ExecutionContext.RestoreFlow();
				}
			}
			return NullDisposable.Instance;
		}
	}
	public static class ChangeToken
	{
		private sealed class ChangeTokenRegistration<TState> : IDisposable
		{
			private sealed class NoopDisposable : IDisposable
			{
				public void Dispose()
				{
				}
			}

			private readonly Func<IChangeToken> _changeTokenProducer;

			private readonly Action<TState> _changeTokenConsumer;

			private readonly TState _state;

			private IDisposable _disposable;

			private static readonly NoopDisposable _disposedSentinel = new NoopDisposable();

			public ChangeTokenRegistration(Func<IChangeToken> changeTokenProducer, Action<TState> changeTokenConsumer, TState state)
			{
				_changeTokenProducer = changeTokenProducer;
				_changeTokenConsumer = changeTokenConsumer;
				_state = state;
				IChangeToken token = changeTokenProducer();
				RegisterChangeTokenCallback(token);
			}

			private void OnChangeTokenFired()
			{
				IChangeToken token = _changeTokenProducer();
				try
				{
					_changeTokenConsumer(_state);
				}
				finally
				{
					RegisterChangeTokenCallback(token);
				}
			}

			private void RegisterChangeTokenCallback(IChangeToken token)
			{
				if (token != null)
				{
					IDisposable disposable = token.RegisterChangeCallback(delegate(object s)
					{
						((ChangeTokenRegistration<TState>)s).OnChangeTokenFired();
					}, this);
					SetDisposable(disposable);
				}
			}

			private void SetDisposable(IDisposable disposable)
			{
				IDisposable disposable2 = Volatile.Read(ref _disposable);
				if (disposable2 == _disposedSentinel)
				{
					disposable.Dispose();
					return;
				}
				IDisposable disposable3 = Interlocked.CompareExchange(ref _disposable, disposable, disposable2);
				if (disposable3 == _disposedSentinel)
				{
					disposable.Dispose();
				}
				else if (disposable3 != disposable2)
				{
					throw new InvalidOperationException("Somebody else set the _disposable field");
				}
			}

			public void Dispose()
			{
				Interlocked.Exchange(ref _disposable, _disposedSentinel).Dispose();
			}
		}

		public static IDisposable OnChange(Func<IChangeToken> changeTokenProducer, Action changeTokenConsumer)
		{
			if (changeTokenProducer == null)
			{
				throw new ArgumentNullException("changeTokenProducer");
			}
			if (changeTokenConsumer == null)
			{
				throw new ArgumentNullException("changeTokenConsumer");
			}
			return new ChangeTokenRegistration<Action>(changeTokenProducer, delegate(Action callback)
			{
				callback();
			}, changeTokenConsumer);
		}

		public static IDisposable OnChange<TState>(Func<IChangeToken> changeTokenProducer, Action<TState> changeTokenConsumer, TState state)
		{
			if (changeTokenProducer == null)
			{
				throw new ArgumentNullException("changeTokenProducer");
			}
			if (changeTokenConsumer == null)
			{
				throw new ArgumentNullException("changeTokenConsumer");
			}
			return new ChangeTokenRegistration<TState>(changeTokenProducer, changeTokenConsumer, state);
		}
	}
	public class CompositeChangeToken : IChangeToken
	{
		private static readonly Action<object> _onChangeDelegate = OnChange;

		private readonly object _callbackLock = new object();

		private CancellationTokenSource _cancellationTokenSource;

		private bool _registeredCallbackProxy;

		private List<IDisposable> _disposables;

		public IReadOnlyList<IChangeToken> ChangeTokens { get; }

		public bool HasChanged
		{
			get
			{
				if (_cancellationTokenSource != null && _cancellationTokenSource.Token.IsCancellationRequested)
				{
					return true;
				}
				for (int i = 0; i < ChangeTokens.Count; i++)
				{
					if (ChangeTokens[i].HasChanged)
					{
						OnChange(this);
						return true;
					}
				}
				return false;
			}
		}

		public bool ActiveChangeCallbacks { get; }

		public CompositeChangeToken(IReadOnlyList<IChangeToken> changeTokens)
		{
			ChangeTokens = changeTokens ?? throw new ArgumentNullException("changeTokens");
			for (int i = 0; i < ChangeTokens.Count; i++)
			{
				if (ChangeTokens[i].ActiveChangeCallbacks)
				{
					ActiveChangeCallbacks = true;
					break;
				}
			}
		}

		public IDisposable RegisterChangeCallback(Action<object> callback, object state)
		{
			EnsureCallbacksInitialized();
			return _cancellationTokenSource.Token.Register(callback, state);
		}

		private void EnsureCallbacksInitialized()
		{
			if (_registeredCallbackProxy)
			{
				return;
			}
			lock (_callbackLock)
			{
				if (_registeredCallbackProxy)
				{
					return;
				}
				_cancellationTokenSource = new CancellationTokenSource();
				_disposables = new List<IDisposable>();
				for (int i = 0; i < ChangeTokens.Count; i++)
				{
					if (ChangeTokens[i].ActiveChangeCallbacks)
					{
						IDisposable item = ChangeTokens[i].RegisterChangeCallback(_onChangeDelegate, this);
						_disposables.Add(item);
					}
				}
				_registeredCallbackProxy = true;
			}
		}

		private static void OnChange(object state)
		{
			CompositeChangeToken compositeChangeToken = (CompositeChangeToken)state;
			if (compositeChangeToken._cancellationTokenSource == null)
			{
				return;
			}
			lock (compositeChangeToken._callbackLock)
			{
				try
				{
					compositeChangeToken._cancellationTokenSource.Cancel();
				}
				catch
				{
				}
			}
			List<IDisposable> disposables = compositeChangeToken._disposables;
			for (int i = 0; i < disposables.Count; i++)
			{
				disposables[i].Dispose();
			}
		}
	}
	public static class Extensions
	{
		public static StringBuilder Append(this StringBuilder builder, StringSegment segment)
		{
			return builder.Append(segment.Buffer, segment.Offset, segment.Length);
		}
	}
	public interface IChangeToken
	{
		bool HasChanged { get; }

		bool ActiveChangeCallbacks { get; }

		IDisposable RegisterChangeCallback(Action<object> callback, object state);
	}
	public readonly struct StringSegment : IEquatable<StringSegment>, IEquatable<string>
	{
		public static readonly StringSegment Empty = string.Empty;

		public string Buffer { get; }

		public int Offset { get; }

		public int Length { get; }

		public string Value
		{
			get
			{
				if (!HasValue)
				{
					return null;
				}
				return Buffer.Substring(Offset, Length);
			}
		}

		public bool HasValue => Buffer != null;

		public char this[int index]
		{
			get
			{
				if ((uint)index >= (uint)Length)
				{
					ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
				}
				return Buffer[Offset + index];
			}
		}

		public StringSegment(string buffer)
		{
			Buffer = buffer;
			Offset = 0;
			Length = buffer?.Length ?? 0;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public StringSegment(string buffer, int offset, int length)
		{
			if (buffer == null || (uint)offset > (uint)buffer.Length || (uint)length > (uint)(buffer.Length - offset))
			{
				ThrowInvalidArguments(buffer, offset, length);
			}
			Buffer = buffer;
			Offset = offset;
			Length = length;
		}

		public ReadOnlySpan<char> AsSpan()
		{
			return Buffer.AsSpan(Offset, Length);
		}

		public ReadOnlySpan<char> AsSpan(int start)
		{
			if (!HasValue || start < 0)
			{
				ThrowInvalidArguments(start, Length - start, ExceptionArgument.start);
			}
			return Buffer.AsSpan(Offset + start, Length - start);
		}

		public ReadOnlySpan<char> AsSpan(int start, int length)
		{
			if (!HasValue || start < 0 || length < 0 || (uint)(start + length) > (uint)Length)
			{
				ThrowInvalidArguments(start, length, ExceptionArgument.start);
			}
			return Buffer.AsSpan(Offset + start, length);
		}

		public ReadOnlyMemory<char> AsMemory()
		{
			return Buffer.AsMemory(Offset, Length);
		}

		public static int Compare(StringSegment a, StringSegment b, StringComparison comparisonType)
		{
			if (a.HasValue && b.HasValue)
			{
				return a.AsSpan().CompareTo(b.AsSpan(), comparisonType);
			}
			CheckStringComparison(comparisonType);
			if (a.HasValue)
			{
				return 1;
			}
			if (!b.HasValue)
			{
				return 0;
			}
			return -1;
		}

		public override bool Equals(object obj)
		{
			if (obj is StringSegment other)
			{
				return Equals(other);
			}
			return false;
		}

		public bool Equals(StringSegment other)
		{
			return Equals(other, StringComparison.Ordinal);
		}

		public bool Equals(StringSegment other, StringComparison comparisonType)
		{
			if (HasValue && other.HasValue)
			{
				return MemoryExtensions.Equals(AsSpan(), other.AsSpan(), comparisonType);
			}
			CheckStringComparison(comparisonType);
			if (!HasValue)
			{
				return !other.HasValue;
			}
			return false;
		}

		public static bool Equals(StringSegment a, StringSegment b, StringComparison comparisonType)
		{
			return a.Equals(b, comparisonType);
		}

		public bool Equals(string text)
		{
			return Equals(text, StringComparison.Ordinal);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool Equals(string text, StringComparison comparisonType)
		{
			if (text == null)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text);
			}
			if (!HasValue)
			{
				CheckStringComparison(comparisonType);
				return false;
			}
			return MemoryExtensions.Equals(AsSpan(), text.AsSpan(), comparisonType);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override int GetHashCode()
		{
			return Value?.GetHashCode() ?? 0;
		}

		public static bool operator ==(StringSegment left, StringSegment right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(StringSegment left, StringSegment right)
		{
			return !left.Equals(right);
		}

		public static implicit operator StringSegment(string value)
		{
			return new StringSegment(value);
		}

		public static implicit operator ReadOnlySpan<char>(StringSegment segment)
		{
			return segment.AsSpan();
		}

		public static implicit operator ReadOnlyMemory<char>(StringSegment segment)
		{
			return segment.AsMemory();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool StartsWith(string text, StringComparison comparisonType)
		{
			if (text == null)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text);
			}
			if (!HasValue)
			{
				CheckStringComparison(comparisonType);
				return false;
			}
			return AsSpan().StartsWith(text.AsSpan(), comparisonType);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool EndsWith(string text, StringComparison comparisonType)
		{
			if (text == null)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text);
			}
			if (!HasValue)
			{
				CheckStringComparison(comparisonType);
				return false;
			}
			return AsSpan().EndsWith(text.AsSpan(), comparisonType);
		}

		public string Substring(int offset)
		{
			return Substring(offset, Length - offset);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public string Substring(int offset, int length)
		{
			if (!HasValue || offset < 0 || length < 0 || (uint)(offset + length) > (uint)Length)
			{
				ThrowInvalidArguments(offset, length, ExceptionArgument.offset);
			}
			return Buffer.Substring(Offset + offset, length);
		}

		public StringSegment Subsegment(int offset)
		{
			return Subsegment(offset, Length - offset);
		}

		public StringSegment Subsegment(int offset, int length)
		{
			if (!HasValue || offset < 0 || length < 0 || (uint)(offset + length) > (uint)Length)
			{
				ThrowInvalidArguments(offset, length, ExceptionArgument.offset);
			}
			return new StringSegment(Buffer, Offset + offset, length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public int IndexOf(char c, int start, int count)
		{
			int num = -1;
			if (HasValue)
			{
				if ((uint)start > (uint)Length)
				{
					ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
				}
				if ((uint)count > (uint)(Length - start))
				{
					ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count);
				}
				num = AsSpan(start, count).IndexOf(c);
				if (num >= 0)
				{
					num += start;
				}
			}
			return num;
		}

		public int IndexOf(char c, int start)
		{
			return IndexOf(c, start, Length - start);
		}

		public int IndexOf(char c)
		{
			return IndexOf(c, 0, Length);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public int IndexOfAny(char[] anyOf, int startIndex, int count)
		{
			int num = -1;
			if (HasValue)
			{
				if ((uint)startIndex > (uint)Length)
				{
					ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
				}
				if ((uint)count > (uint)(Length - startIndex))
				{
					ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count);
				}
				num = Buffer.IndexOfAny(anyOf, Offset + startIndex, count);
				if (num != -1)
				{
					num -= Offset;
				}
			}
			return num;
		}

		public int IndexOfAny(char[] anyOf, int startIndex)
		{
			return IndexOfAny(anyOf, startIndex, Length - startIndex);
		}

		public int IndexOfAny(char[] anyOf)
		{
			return IndexOfAny(anyOf, 0, Length);
		}

		public int LastIndexOf(char value)
		{
			return AsSpan().LastIndexOf(value);
		}

		public StringSegment Trim()
		{
			return TrimStart().TrimEnd();
		}

		public StringSegment TrimStart()
		{
			ReadOnlySpan<char> readOnlySpan = AsSpan();
			int i;
			for (i = 0; i < readOnlySpan.Length && char.IsWhiteSpace(readOnlySpan[i]); i++)
			{
			}
			return Subsegment(i);
		}

		public StringSegment TrimEnd()
		{
			ReadOnlySpan<char> readOnlySpan = AsSpan();
			int num = readOnlySpan.Length - 1;
			while (num >= 0 && char.IsWhiteSpace(readOnlySpan[num]))
			{
				num--;
			}
			return Subsegment(0, num + 1);
		}

		public StringTokenizer Split(char[] chars)
		{
			return new StringTokenizer(this, chars);
		}

		public static bool IsNullOrEmpty(StringSegment value)
		{
			bool result = false;
			if (!value.HasValue || value.Length == 0)
			{
				result = true;
			}
			return result;
		}

		public override string ToString()
		{
			return Value ?? string.Empty;
		}

		private static void CheckStringComparison(StringComparison comparisonType)
		{
			if ((uint)comparisonType > 5u)
			{
				ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.comparisonType);
			}
		}

		private static void ThrowInvalidArguments(string buffer, int offset, int length)
		{
			throw GetInvalidArgumentsException();
			Exception GetInvalidArgumentsException()
			{
				if (buffer == null)
				{
					return ThrowHelper.GetArgumentNullException(ExceptionArgument.buffer);
				}
				if (offset < 0)
				{
					return ThrowHelper.GetArgumentOutOfRangeException(ExceptionArgument.offset);
				}
				if (length < 0)
				{
					return ThrowHelper.GetArgumentOutOfRangeException(ExceptionArgument.length);
				}
				return ThrowHelper.GetArgumentException(ExceptionResource.Argument_InvalidOffsetLength);
			}
		}

		private void ThrowInvalidArguments(int offset, int length, ExceptionArgument offsetOrStart)
		{
			throw GetInvalidArgumentsException(HasValue);
			Exception GetInvalidArgumentsException(bool hasValue)
			{
				if (!hasValue)
				{
					return ThrowHelper.GetArgumentOutOfRangeException(offsetOrStart);
				}
				if (offset < 0)
				{
					return ThrowHelper.GetArgumentOutOfRangeException(offsetOrStart);
				}
				if (length < 0)
				{
					return ThrowHelper.GetArgumentOutOfRangeException(ExceptionArgument.length);
				}
				return ThrowHelper.GetArgumentException(ExceptionResource.Argument_InvalidOffsetLengthStringSegment);
			}
		}

		bool IEquatable<string>.Equals(string other)
		{
			if (other != null)
			{
				return Equals(other);
			}
			return false;
		}
	}
	public class StringSegmentComparer : IComparer<StringSegment>, IEqualityComparer<StringSegment>
	{
		public static StringSegmentComparer Ordinal { get; } = new StringSegmentComparer(StringComparison.Ordinal, StringComparer.Ordinal);


		public static StringSegmentComparer OrdinalIgnoreCase { get; } = new StringSegmentComparer(StringComparison.OrdinalIgnoreCase, StringComparer.OrdinalIgnoreCase);


		private StringComparison Comparison { get; }

		private StringComparer Comparer { get; }

		private StringSegmentComparer(StringComparison comparison, StringComparer comparer)
		{
			Comparison = comparison;
			Comparer = comparer;
		}

		public int Compare(StringSegment x, StringSegment y)
		{
			return StringSegment.Compare(x, y, Comparison);
		}

		public bool Equals(StringSegment x, StringSegment y)
		{
			return StringSegment.Equals(x, y, Comparison);
		}

		public int GetHashCode(StringSegment obj)
		{
			if (!obj.HasValue)
			{
				return 0;
			}
			return Comparer.GetHashCode(obj.Value);
		}
	}
	public readonly struct StringTokenizer : IEnumerable<StringSegment>, IEnumerable
	{
		public struct Enumerator : IEnumerator<StringSegment>, IDisposable, IEnumerator
		{
			private readonly StringSegment _value;

			private readonly char[] _separators;

			private int _index;

			public StringSegment Current { get; private set; }

			object IEnumerator.Current => Current;

			internal Enumerator(in StringSegment value, char[] separators)
			{
				_value = value;
				_separators = separators;
				Current = default(StringSegment);
				_index = 0;
			}

			public Enumerator(ref StringTokenizer tokenizer)
			{
				_value = tokenizer._value;
				_separators = tokenizer._separators;
				Current = default(StringSegment);
				_index = 0;
			}

			public void Dispose()
			{
			}

			public bool MoveNext()
			{
				if (!_value.HasValue || _index > _value.Length)
				{
					Current = default(StringSegment);
					return false;
				}
				int num = _value.IndexOfAny(_separators, _index);
				if (num == -1)
				{
					num = _value.Length;
				}
				Current = _value.Subsegment(_index, num - _index);
				_index = num + 1;
				return true;
			}

			public void Reset()
			{
				Current = default(StringSegment);
				_index = 0;
			}
		}

		private readonly StringSegment _value;

		private readonly char[] _separators;

		public StringTokenizer(string value, char[] separators)
		{
			if (value == null)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
			}
			if (separators == null)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.separators);
			}
			_value = value;
			_separators = separators;
		}

		public StringTokenizer(StringSegment value, char[] separators)
		{
			if (!value.HasValue)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
			}
			if (separators == null)
			{
				ThrowHelper.ThrowArgumentNullException(ExceptionArgument.separators);
			}
			_value = value;
			_separators = separators;
		}

		public Enumerator GetEnumerator()
		{
			return new Enumerator(in _value, _separators);
		}

		IEnumerator<StringSegment> IEnumerable<StringSegment>.GetEnumerator()
		{
			return GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public readonly struct StringValues : IList<string>, ICollection<string>, IEnumerable<string>, IEnumerable, IReadOnlyList<string>, IReadOnlyCollection<string>, IEquatable<StringValues>, IEquatable<string>, IEquatable<string[]>
	{
		public struct Enumerator : IEnumerator<string>, IDisposable, IEnumerator
		{
			private readonly string[] _values;

			private string _current;

			private int _index;

			public string Current => _current;

			object IEnumerator.Current => _current;

			internal Enumerator(object value)
			{
				if (value is string current)
				{
					_values = null;
					_current = current;
				}
				else
				{
					_current = null;
					_values = System.Runtime.CompilerServices.Unsafe.As<string[]>(value);
				}
				_index = 0;
			}

			public Enumerator(ref StringValues values)
				: this(values._values)
			{
			}

			public bool MoveNext()
			{
				int index = _index;
				if (index < 0)
				{
					return false;
				}
				string[] values = _values;
				if (values != null)
				{
					if ((uint)index < (uint)values.Length)
					{
						_index = index + 1;
						_current = values[index];
						return true;
					}
					_index = -1;
					return false;
				}
				_index = -1;
				return _current != null;
			}

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

			public void Dispose()
			{
			}
		}

		public static readonly StringValues Empty = new StringValues(Array.Empty<string>());

		private readonly object _values;

		public int Count
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				object values = _values;
				if (values == null)
				{
					return 0;
				}
				if (values is string)
				{
					return 1;
				}
				return System.Runtime.CompilerServices.Unsafe.As<string[]>(values).Length;
			}
		}

		bool ICollection<string>.IsReadOnly => true;

		string IList<string>.this[int index]
		{
			get
			{
				return this[index];
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		public string this[int index]
		{
			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			get
			{
				object values = _values;
				if (values is string result)
				{
					if (index == 0)
					{
						return result;
					}
				}
				else if (values != null)
				{
					return System.Runtime.CompilerServices.Unsafe.As<string[]>(values)[index];
				}
				return OutOfBounds();
			}
		}

		public StringValues(string value)
		{
			_values = value;
		}

		public StringValues(string[] values)
		{
			_values = values;
		}

		public static implicit operator StringValues(string value)
		{
			return new StringValues(value);
		}

		public static implicit operator StringValues(string[] values)
		{
			return new StringValues(values);
		}

		public static implicit operator string(StringValues values)
		{
			return values.GetStringValue();
		}

		public static implicit operator string[](StringValues value)
		{
			return value.GetArrayValue();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string OutOfBounds()
		{
			return Array.Empty<string>()[0];
		}

		public override string ToString()
		{
			return GetStringValue() ?? string.Empty;
		}

		private string GetStringValue()
		{
			object values2 = _values;
			if (values2 is string result)
			{
				return result;
			}
			return GetStringValueFromArray(values2);
			static string GetJoinedStringValueFromArray(string[] values)
			{
				int num = 0;
				foreach (string text in values)
				{
					if (text != null && text.Length > 0)
					{
						if (num > 0)
						{
							num++;
						}
						num += text.Length;
					}
				}
				System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(num);
				bool flag = false;
				foreach (string text2 in values)
				{
					if (text2 != null && text2.Length > 0)
					{
						if (flag)
						{
							valueStringBuilder.Append(',');
						}
						valueStringBuilder.Append(text2);
						flag = true;
					}
				}
				return valueStringBuilder.ToString();
			}
			static string GetStringValueFromArray(object value)
			{
				if (value == null)
				{
					return null;
				}
				string[] array = System.Runtime.CompilerServices.Unsafe.As<string[]>(value);
				return array.Length switch
				{
					0 => null, 
					1 => array[0], 
					_ => GetJoinedStringValueFromArray(array), 
				};
			}
		}

		public string[] ToArray()
		{
			return GetArrayValue() ?? Array.Empty<string>();
		}

		private string[] GetArrayValue()
		{
			object values = _values;
			if (values is string[] result)
			{
				return result;
			}
			if (values != null)
			{
				return new string[1] { System.Runtime.CompilerServices.Unsafe.As<string>(values) };
			}
			return null;
		}

		int IList<string>.IndexOf(string item)
		{
			return IndexOf(item);
		}

		private int IndexOf(string item)
		{
			object values = _values;
			if (values is string[] array)
			{
				for (int i = 0; i < array.Length; i++)
				{
					if (string.Equals(array[i], item, StringComparison.Ordinal))
					{
						return i;
					}
				}
				return -1;
			}
			if (values != null)
			{
				if (!string.Equals(System.Runtime.CompilerServices.Unsafe.As<string>(values), item, StringComparison.Ordinal))
				{
					return -1;
				}
				return 0;
			}
			return -1;
		}

		bool ICollection<string>.Contains(string item)
		{
			return IndexOf(item) >= 0;
		}

		void ICollection<string>.CopyTo(string[] array, int arrayIndex)
		{
			CopyTo(array, arrayIndex);
		}

		private void CopyTo(string[] array, int arrayIndex)
		{
			object values = _values;
			if (values is string[] array2)
			{
				Array.Copy(array2, 0, array, arrayIndex, array2.Length);
			}
			else if (values != null)
			{
				if (array == null)
				{
					throw new ArgumentNullException("array");
				}
				if (arrayIndex < 0)
				{
					throw new ArgumentOutOfRangeException("arrayIndex");
				}
				if (array.Length - arrayIndex < 1)
				{
					throw new ArgumentException("'array' is not long enough to copy all the items in the collection. Check 'arrayIndex' and 'array' length.");
				}
				array[arrayIndex] = System.Runtime.CompilerServices.Unsafe.As<string>(values);
			}
		}

		void ICollection<string>.Add(string item)
		{
			throw new NotSupportedException();
		}

		void IList<string>.Insert(int index, string item)
		{
			throw new NotSupportedException();
		}

		bool ICollection<string>.Remove(string item)
		{
			throw new NotSupportedException();
		}

		void IList<string>.RemoveAt(int index)
		{
			throw new NotSupportedException();
		}

		void ICollection<string>.Clear()
		{
			throw new NotSupportedException();
		}

		public Enumerator GetEnumerator()
		{
			return new Enumerator(_values);
		}

		IEnumerator<string> IEnumerable<string>.GetEnumerator()
		{
			return GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public static bool IsNullOrEmpty(StringValues value)
		{
			object values = value._values;
			if (values == null)
			{
				return true;
			}
			if (values is string[] array)
			{
				return array.Length switch
				{
					0 => true, 
					1 => string.IsNullOrEmpty(array[0]), 
					_ => false, 
				};
			}
			return string.IsNullOrEmpty(System.Runtime.CompilerServices.Unsafe.As<string>(values));
		}

		public static StringValues Concat(StringValues values1, StringValues values2)
		{
			int count = values1.Count;
			int count2 = values2.Count;
			if (count == 0)
			{
				return values2;
			}
			if (count2 == 0)
			{
				return values1;
			}
			string[] array = new string[count + count2];
			values1.CopyTo(array, 0);
			values2.CopyTo(array, count);
			return new StringValues(array);
		}

		public static StringValues Concat(in StringValues values, string value)
		{
			if (value == null)
			{
				return values;
			}
			int count = values.Count;
			if (count == 0)
			{
				return new StringValues(value);
			}
			string[] array = new string[count + 1];
			values.CopyTo(array, 0);
			array[count] = value;
			return new StringValues(array);
		}

		public static StringValues Concat(string value, in StringValues values)
		{
			if (value == null)
			{
				return values;
			}
			int count = values.Count;
			if (count == 0)
			{
				return new StringValues(value);
			}
			string[] array = new string[count + 1];
			array[0] = value;
			values.CopyTo(array, 1);
			return new StringValues(array);
		}

		public static bool Equals(StringValues left, StringValues right)
		{
			int count = left.Count;
			if (count != right.Count)
			{
				return false;
			}
			for (int i = 0; i < count; i++)
			{
				if (left[i] != right[i])
				{
					return false;
				}
			}
			return true;
		}

		public static bool operator ==(StringValues left, StringValues right)
		{
			return Equals(left, right);
		}

		public static bool operator !=(StringValues left, StringValues right)
		{
			return !Equals(left, right);
		}

		public bool Equals(StringValues other)
		{
			return Equals(this, other);
		}

		public static bool Equals(string left, StringValues right)
		{
			return Equals(new StringValues(left), right);
		}

		public static bool Equals(StringValues left, string right)
		{
			return Equals(left, new StringValues(right));
		}

		public bool Equals(string other)
		{
			return Equals(this, new StringValues(other));
		}

		public static bool Equals(string[] left, StringValues right)
		{
			return Equals(new StringValues(left), right);
		}

		public static bool Equals(StringValues left, string[] right)
		{
			return Equals(left, new StringValues(right));
		}

		public bool Equals(string[] other)
		{
			return Equals(this, new StringValues(other));
		}

		public static bool operator ==(StringValues left, string right)
		{
			return Equals(left, new StringValues(right));
		}

		public static bool operator !=(StringValues left, string right)
		{
			return !Equals(left, new StringValues(right));
		}

		public static bool operator ==(string left, StringValues right)
		{
			return Equals(new StringValues(left), right);
		}

		public static bool operator !=(string left, StringValues right)
		{
			return !Equals(new StringValues(left), right);
		}

		public static bool operator ==(StringValues left, string[] right)
		{
			return Equals(left, new StringValues(right));
		}

		public static bool operator !=(StringValues left, string[] right)
		{
			return !Equals(left, new StringValues(right));
		}

		public static bool operator ==(string[] left, StringValues right)
		{
			return Equals(new StringValues(left), right);
		}

		public static bool operator !=(string[] left, StringValues right)
		{
			return !Equals(new StringValues(left), right);
		}

		public static bool operator ==(StringValues left, object right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(StringValues left, object right)
		{
			return !left.Equals(right);
		}

		public static bool operator ==(object left, StringValues right)
		{
			return right.Equals(left);
		}

		public static bool operator !=(object left, StringValues right)
		{
			return !right.Equals(left);
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return Equals(this, Empty);
			}
			if (obj is string)
			{
				return Equals(this, (string)obj);
			}
			if (obj is string[])
			{
				return Equals(this, (string[])obj);
			}
			if (obj is StringValues)
			{
				return Equals(this, (StringValues)obj);
			}
			return false;
		}

		public override int GetHashCode()
		{
			object values = _values;
			if (values is string[] array)
			{
				if (Count == 1)
				{
					return System.Runtime.CompilerServices.Unsafe.As<string>((object)this[0])?.GetHashCode() ?? Count.GetHashCode();
				}
				int num = 0;
				for (int i = 0; i < array.Length; i++)
				{
					num = HashHelpers.Combine(num, array[i]?.GetHashCode() ?? 0);
				}
				return num;
			}
			return System.Runtime.CompilerServices.Unsafe.As<string>(values)?.GetHashCode() ?? Count.GetHashCode();
		}
	}
	internal static class ThrowHelper
	{
		internal static void ThrowArgumentNullException(ExceptionArgument argument)
		{
			throw new ArgumentNullException(GetArgumentName(argument));
		}

		internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument)
		{
			throw new ArgumentOutOfRangeException(GetArgumentName(argument));
		}

		internal static void ThrowArgumentException(ExceptionResource resource)
		{
			throw new ArgumentException(GetResourceText(resource));
		}

		internal static void ThrowInvalidOperationException(ExceptionResource resource)
		{
			throw new InvalidOperationException(GetResourceText(resource));
		}

		internal static void ThrowInvalidOperationException(ExceptionResource resource, params object[] args)
		{
			string message = string.Format(GetResourceText(resource), args);
			throw new InvalidOperationException(message);
		}

		internal static ArgumentNullException GetArgumentNullException(ExceptionArgument argument)
		{
			return new ArgumentNullException(GetArgumentName(argument));
		}

		internal static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument)
		{
			return new ArgumentOutOfRangeException(GetArgumentName(argument));
		}

		internal static ArgumentException GetArgumentException(ExceptionResource resource)
		{
			return new ArgumentException(GetResourceText(resource));
		}

		private static string GetResourceText(ExceptionResource resource)
		{
			return System.SR.GetResourceString(GetResourceName(resource));
		}

		private static string GetArgumentName(ExceptionArgument argument)
		{
			return argument.ToString();
		}

		private static string GetResourceName(ExceptionResource resource)
		{
			return resource.ToString();
		}
	}
	internal enum ExceptionArgument
	{
		buffer,
		offset,
		length,
		text,
		start,
		count,
		index,
		value,
		capacity,
		separators,
		comparisonType
	}
	internal enum ExceptionResource
	{
		Argument_InvalidOffsetLength,
		Argument_InvalidOffsetLengthStringSegment,
		Capacity_CannotChangeAfterWriteStarted,
		Capacity_NotEnough,
		Capacity_NotUsedEntirely
	}
}

plugins/TwitchLib/TwitchLib.Api.Core.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using TwitchLib.Api.Core.Common;
using TwitchLib.Api.Core.Enums;
using TwitchLib.Api.Core.Exceptions;
using TwitchLib.Api.Core.Extensions.RateLimiter;
using TwitchLib.Api.Core.Interfaces;
using TwitchLib.Api.Core.Internal;
using TwitchLib.Api.Core.Models;
using TwitchLib.Api.Core.Models.Undocumented.Chatters;
using TwitchLib.Api.Core.RateLimiter;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Project containing the core of TwitchLib.Api")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api.Core")]
[assembly: AssemblyTitle("TwitchLib.Api.Core")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api.Core
{
	public class ApiBase
	{
		private class TwitchLibJsonSerializer
		{
			private class LowercaseContractResolver : DefaultContractResolver
			{
				protected override string ResolvePropertyName(string propertyName)
				{
					return propertyName.ToLower();
				}
			}

			private readonly JsonSerializerSettings _settings = new JsonSerializerSettings
			{
				ContractResolver = (IContractResolver)(object)new LowercaseContractResolver(),
				NullValueHandling = (NullValueHandling)1
			};

			public string SerializeObject(object o)
			{
				return JsonConvert.SerializeObject(o, (Formatting)1, _settings);
			}
		}

		private readonly TwitchLibJsonSerializer _jsonSerializer;

		protected readonly IApiSettings Settings;

		private readonly IRateLimiter _rateLimiter;

		private readonly IHttpCallHandler _http;

		internal const string BaseHelix = "https://api.twitch.tv/helix";

		internal const string BaseAuth = "https://id.twitch.tv/oauth2";

		private DateTime? _serverBasedAccessTokenExpiry;

		private string _serverBasedAccessToken;

		private readonly JsonSerializerSettings _twitchLibJsonDeserializer = new JsonSerializerSettings
		{
			NullValueHandling = (NullValueHandling)1,
			MissingMemberHandling = (MissingMemberHandling)0
		};

		public ApiBase(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Settings = settings;
			_rateLimiter = rateLimiter;
			_http = http;
			_jsonSerializer = new TwitchLibJsonSerializer();
		}

		public async ValueTask<string> GetAccessTokenAsync(string accessToken = null)
		{
			if (!string.IsNullOrWhiteSpace(accessToken))
			{
				return accessToken;
			}
			if (!string.IsNullOrWhiteSpace(Settings.AccessToken))
			{
				return Settings.AccessToken;
			}
			if (!string.IsNullOrWhiteSpace(Settings.Secret) && !string.IsNullOrWhiteSpace(Settings.ClientId) && !Settings.SkipAutoServerTokenGeneration)
			{
				if (!_serverBasedAccessTokenExpiry.HasValue || _serverBasedAccessTokenExpiry - TimeSpan.FromMinutes(1.0) < DateTime.Now)
				{
					return await GenerateServerBasedAccessToken().ConfigureAwait(continueOnCapturedContext: false);
				}
				return _serverBasedAccessToken;
			}
			return null;
		}

		internal async Task<string> GenerateServerBasedAccessToken()
		{
			KeyValuePair<int, string> keyValuePair = await _http.GeneralRequestAsync("https://id.twitch.tv/oauth2/token?client_id=" + Settings.ClientId + "&client_secret=" + Settings.Secret + "&grant_type=client_credentials", "POST", (string)null, (ApiVersion)1, Settings.ClientId, (string)null).ConfigureAwait(continueOnCapturedContext: false);
			if (keyValuePair.Key == 200)
			{
				JObject val = JObject.Parse(keyValuePair.Value);
				int num = int.Parse(((object)((JToken)val).SelectToken("expires_in"))?.ToString() ?? string.Empty);
				_serverBasedAccessTokenExpiry = DateTime.Now + TimeSpan.FromSeconds(num);
				_serverBasedAccessToken = ((object)((JToken)val).SelectToken("access_token"))?.ToString();
				return _serverBasedAccessToken;
			}
			return null;
		}

		internal void ForceAccessTokenAndClientIdForHelix(string clientId, string accessToken, ApiVersion api)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)api != 6 || (!string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(accessToken)))
			{
				return;
			}
			throw new ClientIdAndOAuthTokenRequired("As of May 1, all calls to Twitch's Helix API require Client-ID and OAuth access token be set. Example: api.Settings.AccessToken = \"twitch-oauth-access-token-here\"; api.Settings.ClientId = \"twitch-client-id-here\";");
		}

		protected async Task<string> TwitchGetAsync(string resource, ApiVersion api, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<string>((Func<Task<string>>)(async () => (await _http.GeneralRequestAsync(url, "GET", (string)null, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value)).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<T> TwitchGetGenericAsync<T>(string resource, ApiVersion api, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "GET", (string)null, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<T> TwitchPatchGenericAsync<T>(string resource, ApiVersion api, string payload, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "PATCH", payload, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<string> TwitchPatchAsync(string resource, ApiVersion api, string payload, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<string>((Func<Task<string>>)(async () => (await _http.GeneralRequestAsync(url, "PATCH", payload, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value)).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<KeyValuePair<int, string>> TwitchDeleteAsync(string resource, ApiVersion api, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<KeyValuePair<int, string>>((Func<Task<KeyValuePair<int, string>>>)(async () => await _http.GeneralRequestAsync(url, "DELETE", (string)null, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<T> TwitchPostGenericAsync<T>(string resource, ApiVersion api, string payload, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "POST", payload, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<T> TwitchPostGenericModelAsync<T>(string resource, ApiVersion api, RequestModel model, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, null, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "POST", (model != null) ? _jsonSerializer.SerializeObject(model) : "", api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<T> TwitchDeleteGenericAsync<T>(string resource, ApiVersion api, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "DELETE", (string)null, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<T> TwitchPutGenericAsync<T>(string resource, ApiVersion api, string payload = null, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "PUT", payload, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<string> TwitchPutAsync(string resource, ApiVersion api, string payload, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<string>((Func<Task<string>>)(async () => (await _http.GeneralRequestAsync(url, "PUT", payload, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value)).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected async Task<KeyValuePair<int, string>> TwitchPostAsync(string resource, ApiVersion api, string payload, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, string clientId = null, string customBase = null)
		{
			//IL_001e: 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)
			string url = ConstructResourceUrl(resource, getParams, api, customBase);
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<KeyValuePair<int, string>>((Func<Task<KeyValuePair<int, string>>>)(async () => await _http.GeneralRequestAsync(url, "POST", payload, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false))).ConfigureAwait(continueOnCapturedContext: false);
		}

		protected Task PutBytesAsync(string url, byte[] payload)
		{
			return _http.PutBytesAsync(url, payload);
		}

		internal Task<int> RequestReturnResponseCode(string url, string method, List<KeyValuePair<string, string>> getParams = null)
		{
			return _http.RequestReturnResponseCodeAsync(url, method, getParams);
		}

		protected async Task<T> GetGenericAsync<T>(string url, List<KeyValuePair<string, string>> getParams = null, string accessToken = null, ApiVersion api = 6, string clientId = null)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (getParams != null)
			{
				for (int i = 0; i < getParams.Count; i++)
				{
					if (i == 0)
					{
						url = url + "?" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value);
					}
					else
					{
						url = url + "&" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value);
					}
				}
			}
			if (string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(Settings.ClientId))
			{
				clientId = Settings.ClientId;
			}
			accessToken = await GetAccessTokenAsync(accessToken).ConfigureAwait(continueOnCapturedContext: false);
			ForceAccessTokenAndClientIdForHelix(clientId, accessToken, api);
			return await _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>((await _http.GeneralRequestAsync(url, "GET", (string)null, api, clientId, accessToken).ConfigureAwait(continueOnCapturedContext: false)).Value, _twitchLibJsonDeserializer))).ConfigureAwait(continueOnCapturedContext: false);
		}

		internal Task<T> GetSimpleGenericAsync<T>(string url, List<KeyValuePair<string, string>> getParams = null)
		{
			if (getParams != null)
			{
				for (int i = 0; i < getParams.Count; i++)
				{
					if (i == 0)
					{
						url = url + "?" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value);
					}
					else
					{
						url = url + "&" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value);
					}
				}
			}
			return _rateLimiter.Perform<T>((Func<Task<T>>)(async () => JsonConvert.DeserializeObject<T>(await SimpleRequestAsync(url).ConfigureAwait(continueOnCapturedContext: false), _twitchLibJsonDeserializer)));
		}

		private Task<string> SimpleRequestAsync(string url)
		{
			TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
			WebClient client = new WebClient();
			client.DownloadStringCompleted += DownloadStringCompletedEventHandler;
			client.DownloadString(new Uri(url));
			return tcs.Task;
			void DownloadStringCompletedEventHandler(object sender, DownloadStringCompletedEventArgs args)
			{
				if (args.Cancelled)
				{
					tcs.SetCanceled();
				}
				else if (args.Error != null)
				{
					tcs.SetException(args.Error);
				}
				else
				{
					tcs.SetResult(args.Result);
				}
				client.DownloadStringCompleted -= DownloadStringCompletedEventHandler;
			}
		}

		private string ConstructResourceUrl(string resource = null, List<KeyValuePair<string, string>> getParams = null, ApiVersion api = 6, string overrideUrl = null)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			string text = "";
			if (overrideUrl == null)
			{
				if (resource == null)
				{
					throw new Exception("Cannot pass null resource with null override url");
				}
				if ((int)api != 1)
				{
					if ((int)api == 6)
					{
						text = "https://api.twitch.tv/helix" + resource;
					}
				}
				else
				{
					text = "https://id.twitch.tv/oauth2" + resource;
				}
			}
			else
			{
				text = ((resource == null) ? overrideUrl : (overrideUrl + resource));
			}
			if (getParams != null)
			{
				for (int i = 0; i < getParams.Count; i++)
				{
					text = ((i != 0) ? (text + "&" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value)) : (text + "?" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value)));
				}
			}
			return text;
		}
	}
	public class ApiSettings : IApiSettings, INotifyPropertyChanged
	{
		private string _clientId;

		private string _secret;

		private string _accessToken;

		private bool _skipDynamicScopeValidation;

		private bool _skipAutoServerTokenGeneration;

		private List<AuthScopes> _scopes;

		public string ClientId
		{
			get
			{
				return _clientId;
			}
			set
			{
				if (value != _clientId)
				{
					_clientId = value;
					NotifyPropertyChanged("ClientId");
				}
			}
		}

		public string Secret
		{
			get
			{
				return _secret;
			}
			set
			{
				if (value != _secret)
				{
					_secret = value;
					NotifyPropertyChanged("Secret");
				}
			}
		}

		public string AccessToken
		{
			get
			{
				return _accessToken;
			}
			set
			{
				if (value != _accessToken)
				{
					_accessToken = value;
					NotifyPropertyChanged("AccessToken");
				}
			}
		}

		public bool SkipDynamicScopeValidation
		{
			get
			{
				return _skipDynamicScopeValidation;
			}
			set
			{
				if (value != _skipDynamicScopeValidation)
				{
					_skipDynamicScopeValidation = value;
					NotifyPropertyChanged("SkipDynamicScopeValidation");
				}
			}
		}

		public bool SkipAutoServerTokenGeneration
		{
			get
			{
				return _skipAutoServerTokenGeneration;
			}
			set
			{
				if (value != _skipAutoServerTokenGeneration)
				{
					_skipAutoServerTokenGeneration = value;
					NotifyPropertyChanged("SkipAutoServerTokenGeneration");
				}
			}
		}

		public List<AuthScopes> Scopes
		{
			get
			{
				return _scopes;
			}
			set
			{
				if (value != _scopes)
				{
					_scopes = value;
					NotifyPropertyChanged("Scopes");
				}
			}
		}

		public event PropertyChangedEventHandler PropertyChanged;

		private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
		{
			this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
		}
	}
}
namespace TwitchLib.Api.Core.Undocumented
{
	public class Undocumented : ApiBase
	{
		public Undocumented(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
			: base(settings, rateLimiter, http)
		{
		}

		[Obsolete("Please use the new official Helix GetChatters Endpoint (api.Helix.Chat.GetChattersAsync) instead of this undocumented and unsupported endpoint.")]
		public async Task<List<ChatterFormatted>> GetChattersAsync(string channelName)
		{
			ChattersResponse val = await GetGenericAsync<ChattersResponse>("https://tmi.twitch.tv/group/user/" + channelName.ToLower() + "/chatters", null, null, (ApiVersion)6);
			List<ChatterFormatted> list = ((IEnumerable<string>)val.Chatters.Staff).Select((Func<string, ChatterFormatted>)((string chatter) => new ChatterFormatted(chatter, (UserType)6))).ToList();
			list.AddRange(((IEnumerable<string>)val.Chatters.Admins).Select((Func<string, ChatterFormatted>)((string chatter) => new ChatterFormatted(chatter, (UserType)5))));
			list.AddRange(((IEnumerable<string>)val.Chatters.GlobalMods).Select((Func<string, ChatterFormatted>)((string chatter) => new ChatterFormatted(chatter, (UserType)3))));
			list.AddRange(((IEnumerable<string>)val.Chatters.Moderators).Select((Func<string, ChatterFormatted>)((string chatter) => new ChatterFormatted(chatter, (UserType)2))));
			list.AddRange(((IEnumerable<string>)val.Chatters.Viewers).Select((Func<string, ChatterFormatted>)((string chatter) => new ChatterFormatted(chatter, (UserType)0))));
			list.AddRange(((IEnumerable<string>)val.Chatters.VIP).Select((Func<string, ChatterFormatted>)((string chatter) => new ChatterFormatted(chatter, (UserType)1))));
			foreach (ChatterFormatted item in list.Where((ChatterFormatted chatter) => string.Equals(chatter.Username, channelName, StringComparison.InvariantCultureIgnoreCase)))
			{
				item.UserType = (UserType)4;
			}
			return list;
		}

		public async Task<bool> IsUsernameAvailableAsync(string username)
		{
			List<KeyValuePair<string, string>> getParams = new List<KeyValuePair<string, string>>
			{
				new KeyValuePair<string, string>("users_service", "true")
			};
			int num = await RequestReturnResponseCode("https://passport.twitch.tv/usernames/" + username, "HEAD", getParams).ConfigureAwait(continueOnCapturedContext: false);
			return num switch
			{
				200 => false, 
				204 => true, 
				_ => throw new BadResourceException("Unexpected response from resource. Expecting response code 200 or 204, received: " + num), 
			};
		}
	}
}
namespace TwitchLib.Api.Core.RateLimiter
{
	public class BypassLimiter : IRateLimiter
	{
		public Task Perform(Func<Task> perform)
		{
			return Perform(perform, CancellationToken.None);
		}

		public Task<T> Perform<T>(Func<Task<T>> perform)
		{
			return Perform(perform, CancellationToken.None);
		}

		public Task Perform(Func<Task> perform, CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();
			return perform();
		}

		public Task<T> Perform<T>(Func<Task<T>> perform, CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();
			return perform();
		}

		private static Func<Task> Transform(Action act)
		{
			return delegate
			{
				act();
				return Task.FromResult(0);
			};
		}

		private static Func<Task<T>> Transform<T>(Func<T> compute)
		{
			return () => Task.FromResult(compute());
		}

		public Task Perform(Action perform, CancellationToken cancellationToken)
		{
			Func<Task> perform2 = Transform(perform);
			return Perform(perform2, cancellationToken);
		}

		public Task Perform(Action perform)
		{
			Func<Task> perform2 = Transform(perform);
			return Perform(perform2);
		}

		public Task<T> Perform<T>(Func<T> perform)
		{
			Func<Task<T>> perform2 = Transform(perform);
			return Perform(perform2);
		}

		public Task<T> Perform<T>(Func<T> perform, CancellationToken cancellationToken)
		{
			Func<Task<T>> perform2 = Transform(perform);
			return Perform(perform2, cancellationToken);
		}

		public static BypassLimiter CreateLimiterBypassInstance()
		{
			return new BypassLimiter();
		}
	}
	public class ComposedAwaitableConstraint : IAwaitableConstraint
	{
		private IAwaitableConstraint _ac1;

		private IAwaitableConstraint _ac2;

		private readonly SemaphoreSlim _semafore = new SemaphoreSlim(1, 1);

		internal ComposedAwaitableConstraint(IAwaitableConstraint ac1, IAwaitableConstraint ac2)
		{
			_ac1 = ac1;
			_ac2 = ac2;
		}

		public async Task<IDisposable> WaitForReadiness(CancellationToken cancellationToken)
		{
			await _semafore.WaitAsync(cancellationToken);
			IDisposable[] diposables;
			try
			{
				diposables = await Task.WhenAll<IDisposable>(_ac1.WaitForReadiness(cancellationToken), _ac2.WaitForReadiness(cancellationToken));
			}
			catch (Exception)
			{
				_semafore.Release();
				throw;
			}
			return new DisposeAction(delegate
			{
				IDisposable[] array = diposables;
				for (int i = 0; i < array.Length; i++)
				{
					array[i].Dispose();
				}
				_semafore.Release();
			});
		}
	}
	public class CountByIntervalAwaitableConstraint : IAwaitableConstraint
	{
		public IReadOnlyList<DateTime> TimeStamps => _timeStamps.ToList();

		protected LimitedSizeStack<DateTime> _timeStamps { get; }

		private int _count { get; }

		private TimeSpan _timeSpan { get; }

		private SemaphoreSlim _semafore { get; } = new SemaphoreSlim(1, 1);


		private ITime _time { get; }

		public CountByIntervalAwaitableConstraint(int count, TimeSpan timeSpan, ITime time = null)
		{
			if (count <= 0)
			{
				throw new ArgumentException("count should be strictly positive", "count");
			}
			if (timeSpan.TotalMilliseconds <= 0.0)
			{
				throw new ArgumentException("timeSpan should be strictly positive", "timeSpan");
			}
			_count = count;
			_timeSpan = timeSpan;
			_timeStamps = new LimitedSizeStack<DateTime>(_count);
			_time = time ?? TimeSystem.StandardTime;
		}

		public async Task<IDisposable> WaitForReadiness(CancellationToken cancellationToken)
		{
			await _semafore.WaitAsync(cancellationToken);
			int num = 0;
			DateTime timeNow = _time.GetTimeNow();
			DateTime dateTime = timeNow - _timeSpan;
			LinkedListNode<DateTime> linkedListNode = _timeStamps.First;
			LinkedListNode<DateTime> linkedListNode2 = null;
			while (linkedListNode != null && linkedListNode.Value > dateTime)
			{
				linkedListNode2 = linkedListNode;
				linkedListNode = linkedListNode.Next;
				num++;
			}
			if (num < _count)
			{
				return new DisposeAction(OnEnded);
			}
			TimeSpan timeSpan = linkedListNode2.Value.Add(_timeSpan) - timeNow;
			try
			{
				await _time.GetDelay(timeSpan, cancellationToken);
			}
			catch (Exception)
			{
				_semafore.Release();
				throw;
			}
			return new DisposeAction(OnEnded);
		}

		private void OnEnded()
		{
			DateTime timeNow = _time.GetTimeNow();
			_timeStamps.Push(timeNow);
			OnEnded(timeNow);
			_semafore.Release();
		}

		protected virtual void OnEnded(DateTime now)
		{
		}
	}
	public class DisposeAction : IDisposable
	{
		private Action _act;

		public DisposeAction(Action act)
		{
			_act = act;
		}

		public void Dispose()
		{
			_act?.Invoke();
			_act = null;
		}
	}
	public class LimitedSizeStack<T> : LinkedList<T>
	{
		private readonly int _maxSize;

		public LimitedSizeStack(int maxSize)
		{
			_maxSize = maxSize;
		}

		public void Push(T item)
		{
			AddFirst(item);
			if (base.Count > _maxSize)
			{
				RemoveLast();
			}
		}
	}
	public class PersistentCountByIntervalAwaitableConstraint : CountByIntervalAwaitableConstraint
	{
		private readonly Action<DateTime> _saveStateAction;

		public PersistentCountByIntervalAwaitableConstraint(int count, TimeSpan timeSpan, Action<DateTime> saveStateAction, IEnumerable<DateTime> initialTimeStamps, ITime time = null)
			: base(count, timeSpan, time)
		{
			_saveStateAction = saveStateAction;
			if (initialTimeStamps == null)
			{
				return;
			}
			foreach (DateTime initialTimeStamp in initialTimeStamps)
			{
				base._timeStamps.Push(initialTimeStamp);
			}
		}

		protected override void OnEnded(DateTime now)
		{
			_saveStateAction(now);
		}
	}
	public class TimeLimiter : IRateLimiter
	{
		private readonly IAwaitableConstraint _ac;

		internal TimeLimiter(IAwaitableConstraint ac)
		{
			_ac = ac;
		}

		public Task Perform(Func<Task> perform)
		{
			return Perform(perform, CancellationToken.None);
		}

		public Task<T> Perform<T>(Func<Task<T>> perform)
		{
			return Perform(perform, CancellationToken.None);
		}

		public async Task Perform(Func<Task> perform, CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();
			using (await _ac.WaitForReadiness(cancellationToken))
			{
				await perform();
			}
		}

		public async Task<T> Perform<T>(Func<Task<T>> perform, CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();
			using (await _ac.WaitForReadiness(cancellationToken))
			{
				return await perform();
			}
		}

		private static Func<Task> Transform(Action act)
		{
			return delegate
			{
				act();
				return Task.FromResult(0);
			};
		}

		private static Func<Task<T>> Transform<T>(Func<T> compute)
		{
			return () => Task.FromResult(compute());
		}

		public Task Perform(Action perform, CancellationToken cancellationToken)
		{
			Func<Task> perform2 = Transform(perform);
			return Perform(perform2, cancellationToken);
		}

		public Task Perform(Action perform)
		{
			Func<Task> perform2 = Transform(perform);
			return Perform(perform2);
		}

		public Task<T> Perform<T>(Func<T> perform)
		{
			Func<Task<T>> perform2 = Transform(perform);
			return Perform(perform2);
		}

		public Task<T> Perform<T>(Func<T> perform, CancellationToken cancellationToken)
		{
			Func<Task<T>> perform2 = Transform(perform);
			return Perform(perform2, cancellationToken);
		}

		public static TimeLimiter GetFromMaxCountByInterval(int maxCount, TimeSpan timeSpan)
		{
			return new TimeLimiter((IAwaitableConstraint)(object)new CountByIntervalAwaitableConstraint(maxCount, timeSpan));
		}

		public static TimeLimiter GetPersistentTimeLimiter(int maxCount, TimeSpan timeSpan, Action<DateTime> saveStateAction)
		{
			return GetPersistentTimeLimiter(maxCount, timeSpan, saveStateAction, null);
		}

		public static TimeLimiter GetPersistentTimeLimiter(int maxCount, TimeSpan timeSpan, Action<DateTime> saveStateAction, IEnumerable<DateTime> initialTimeStamps)
		{
			return new TimeLimiter((IAwaitableConstraint)(object)new PersistentCountByIntervalAwaitableConstraint(maxCount, timeSpan, saveStateAction, initialTimeStamps));
		}

		public static TimeLimiter Compose(params IAwaitableConstraint[] constraints)
		{
			IAwaitableConstraint val = null;
			foreach (IAwaitableConstraint val2 in constraints)
			{
				val = ((val == null) ? val2 : val.Compose(val2));
			}
			return new TimeLimiter(val);
		}
	}
	public class TimeSystem : ITime
	{
		public static ITime StandardTime { get; }

		static TimeSystem()
		{
			StandardTime = (ITime)(object)new TimeSystem();
		}

		private TimeSystem()
		{
		}

		DateTime ITime.GetTimeNow()
		{
			return DateTime.Now;
		}

		Task ITime.GetDelay(TimeSpan timespan, CancellationToken cancellationToken)
		{
			return Task.Delay(timespan, cancellationToken);
		}
	}
}
namespace TwitchLib.Api.Core.Internal
{
	public class TwitchHttpClientHandler : DelegatingHandler
	{
		private readonly ILogger<IHttpCallHandler> _logger;

		public TwitchHttpClientHandler(ILogger<IHttpCallHandler> logger)
			: base(new HttpClientHandler())
		{
			_logger = logger;
		}

		protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
		{
			if (request.Content != null)
			{
				ILogger<IHttpCallHandler> logger = _logger;
				if (logger != null)
				{
					ILogger logger2 = logger;
					object obj = DateTime.Now;
					object obj2 = "Request";
					object obj3 = request.Method.ToString();
					object obj4 = request.RequestUri.ToString();
					string text = await request.Content.ReadAsStringAsync();
					logger2.LogInformation("Timestamp: {timestamp} Type: {type} Method: {method} Resource: {url} Content: {content}", obj, obj2, obj3, obj4, text);
				}
			}
			else
			{
				_logger?.LogInformation("Timestamp: {timestamp} Type: {type} Method: {method} Resource: {url}", DateTime.Now, "Request", request.Method.ToString(), request.RequestUri.ToString());
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
			stopwatch.Stop();
			if (response.IsSuccessStatusCode)
			{
				if (response.Content != null)
				{
					ILogger<IHttpCallHandler> logger = _logger;
					if (logger != null)
					{
						ILogger logger2 = logger;
						object obj4 = DateTime.Now;
						object obj3 = "Response";
						object obj2 = response.RequestMessage.RequestUri;
						object obj = (int)response.StatusCode;
						object obj5 = stopwatch.ElapsedMilliseconds;
						string text = await response.Content.ReadAsStringAsync();
						logger2.LogInformation("Timestamp: {timestamp} Type: {type} Resource: {url} Statuscode: {statuscode} Elapsed: {elapsed} ms Content: {content}", obj4, obj3, obj2, obj, obj5, text);
					}
				}
				else
				{
					_logger?.LogInformation("Timestamp: {timestamp} Type: {type} Resource: {url} Statuscode: {statuscode} Elapsed: {elapsed} ms", DateTime.Now, "Response", response.RequestMessage.RequestUri, (int)response.StatusCode, stopwatch.ElapsedMilliseconds);
				}
			}
			else if (response.Content != null)
			{
				ILogger<IHttpCallHandler> logger = _logger;
				if (logger != null)
				{
					ILogger logger2 = logger;
					object obj5 = DateTime.Now;
					object obj = "Response";
					object obj2 = response.RequestMessage.RequestUri;
					object obj3 = (int)response.StatusCode;
					object obj4 = stopwatch.ElapsedMilliseconds;
					string text = await response.Content.ReadAsStringAsync();
					logger2.LogError("Timestamp: {timestamp} Type: {type} Resource: {url} Statuscode: {statuscode} Elapsed: {elapsed} ms Content: {content}", obj5, obj, obj2, obj3, obj4, text);
				}
			}
			else
			{
				_logger?.LogError("Timestamp: {timestamp} Type: {type} Resource: {url} Statuscode: {statuscode} Elapsed: {elapsed} ms", DateTime.Now, "Response", response.RequestMessage.RequestUri, (int)response.StatusCode, stopwatch.ElapsedMilliseconds);
			}
			return response;
		}
	}
}
namespace TwitchLib.Api.Core.HttpCallHandlers
{
	public class TwitchHttpClient : IHttpCallHandler
	{
		private readonly ILogger<TwitchHttpClient> _logger;

		private readonly HttpClient _http;

		public TwitchHttpClient(ILogger<TwitchHttpClient> logger = null)
		{
			_logger = logger;
			_http = new HttpClient(new TwitchHttpClientHandler((ILogger<IHttpCallHandler>)_logger));
		}

		public async Task PutBytesAsync(string url, byte[] payload)
		{
			HttpResponseMessage httpResponseMessage = await _http.PutAsync(new Uri(url), new ByteArrayContent(payload)).ConfigureAwait(continueOnCapturedContext: false);
			if (!httpResponseMessage.IsSuccessStatusCode)
			{
				HandleWebException(httpResponseMessage);
			}
		}

		public async Task<KeyValuePair<int, string>> GeneralRequestAsync(string url, string method, string payload = null, ApiVersion api = 6, string clientId = null, string accessToken = null)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			HttpRequestMessage httpRequestMessage = new HttpRequestMessage
			{
				RequestUri = new Uri(url),
				Method = new HttpMethod(method)
			};
			if ((int)api == 6)
			{
				if (string.IsNullOrWhiteSpace(clientId) || string.IsNullOrWhiteSpace(accessToken))
				{
					throw new InvalidCredentialException("A Client-Id and OAuth token is required to use the Twitch API.");
				}
				httpRequestMessage.Headers.Add("Client-ID", clientId);
			}
			string text = "OAuth";
			if ((int)api == 6 || (int)api == 1)
			{
				httpRequestMessage.Headers.Add(HttpRequestHeader.Accept.ToString(), "application/json");
				text = "Bearer";
			}
			if (!string.IsNullOrWhiteSpace(accessToken))
			{
				httpRequestMessage.Headers.Add(HttpRequestHeader.Authorization.ToString(), text + " " + Helpers.FormatOAuth(accessToken));
			}
			if (payload != null)
			{
				httpRequestMessage.Content = new StringContent(payload, Encoding.UTF8, "application/json");
			}
			HttpResponseMessage response = await _http.SendAsync(httpRequestMessage).ConfigureAwait(continueOnCapturedContext: false);
			if (response.IsSuccessStatusCode)
			{
				string value = await response.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false);
				return new KeyValuePair<int, string>((int)response.StatusCode, value);
			}
			HandleWebException(response);
			return new KeyValuePair<int, string>(0, null);
		}

		public async Task<int> RequestReturnResponseCodeAsync(string url, string method, List<KeyValuePair<string, string>> getParams = null)
		{
			if (getParams != null)
			{
				for (int i = 0; i < getParams.Count; i++)
				{
					url = ((i != 0) ? (url + "&" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value)) : (url + "?" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value)));
				}
			}
			HttpRequestMessage request = new HttpRequestMessage
			{
				RequestUri = new Uri(url),
				Method = new HttpMethod(method)
			};
			return (int)(await _http.SendAsync(request).ConfigureAwait(continueOnCapturedContext: false)).StatusCode;
		}

		private void HandleWebException(HttpResponseMessage errorResp)
		{
			switch (errorResp.StatusCode)
			{
			case HttpStatusCode.BadRequest:
				throw new BadRequestException("Your request failed because either: \n 1. Your ClientID was invalid/not set. \n 2. Your refresh token was invalid. \n 3. You requested a username when the server was expecting a user ID.");
			case HttpStatusCode.Unauthorized:
			{
				HttpHeaderValueCollection<AuthenticationHeaderValue> wwwAuthenticate = errorResp.Headers.WwwAuthenticate;
				if (wwwAuthenticate == null || wwwAuthenticate.Count <= 0)
				{
					throw new BadScopeException("Your request was blocked due to bad credentials (Do you have the right scope for your access token?).");
				}
				throw new TokenExpiredException("Your request was blocked due to an expired Token. Please refresh your token and update your API instance settings.");
			}
			case HttpStatusCode.NotFound:
				throw new BadResourceException("The resource you tried to access was not valid.");
			case HttpStatusCode.TooManyRequests:
			{
				errorResp.Headers.TryGetValues("Ratelimit-Reset", out IEnumerable<string> values);
				throw new TooManyRequestsException("You have reached your rate limit. Too many requests were made", values.FirstOrDefault());
			}
			case HttpStatusCode.BadGateway:
				throw new BadGatewayException("The API answered with a 502 Bad Gateway. Please retry your request");
			case HttpStatusCode.GatewayTimeout:
				throw new GatewayTimeoutException("The API answered with a 504 Gateway Timeout. Please retry your request");
			case HttpStatusCode.InternalServerError:
				throw new InternalServerErrorException("The API answered with a 500 Internal Server Error. Please retry your request");
			case HttpStatusCode.Forbidden:
				throw new BadTokenException("The token provided in the request did not match the associated user. Make sure the token you're using is from the resource owner (streamer? viewer?)");
			default:
				throw new HttpRequestException("Something went wrong during the request! Please try again later");
			}
		}
	}
	[Obsolete("The WebRequest handler is deprecated and is not updated to be working with Helix correctly")]
	public class TwitchWebRequest : IHttpCallHandler
	{
		private readonly ILogger<TwitchWebRequest> _logger;

		public TwitchWebRequest(ILogger<TwitchWebRequest> logger = null)
		{
			_logger = logger;
		}

		public Task PutBytesAsync(string url, byte[] payload)
		{
			return Task.Factory.StartNew(delegate
			{
				try
				{
					using WebClient webClient = new WebClient();
					webClient.UploadData(new Uri(url), "PUT", payload);
				}
				catch (WebException e)
				{
					HandleWebException(e);
				}
			});
		}

		public async Task<KeyValuePair<int, string>> GeneralRequestAsync(string url, string method, string payload = null, ApiVersion api = 6, string clientId = null, string accessToken = null)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			HttpWebRequest request = WebRequest.CreateHttp(url);
			if (string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(accessToken))
			{
				throw new InvalidCredentialException("A Client-Id or OAuth token is required to use the Twitch API. If you previously set them in InitializeAsync, please be sure to await the method.");
			}
			if (!string.IsNullOrEmpty(clientId))
			{
				request.Headers["Client-ID"] = clientId;
			}
			request.Method = method;
			request.ContentType = "application/json";
			string text = "OAuth";
			if ((int)api == 6)
			{
				request.Accept = "application/json";
				text = "Bearer";
			}
			else if ((int)api != 0)
			{
				request.Accept = $"application/vnd.twitchtv.v{(int)api}+json";
			}
			if (!string.IsNullOrEmpty(accessToken))
			{
				request.Headers["Authorization"] = text + " " + Helpers.FormatOAuth(accessToken);
			}
			if (payload != null)
			{
				using StreamWriter writer = new StreamWriter(await request.GetRequestStreamAsync().ConfigureAwait(continueOnCapturedContext: false));
				await writer.WriteAsync(payload).ConfigureAwait(continueOnCapturedContext: false);
			}
			try
			{
				HttpWebResponse response = (HttpWebResponse)request.GetResponse();
				using StreamReader reader = new StreamReader(response.GetResponseStream() ?? throw new InvalidOperationException());
				string value = await reader.ReadToEndAsync().ConfigureAwait(continueOnCapturedContext: false);
				return new KeyValuePair<int, string>((int)response.StatusCode, value);
			}
			catch (WebException e)
			{
				HandleWebException(e);
			}
			return new KeyValuePair<int, string>(0, null);
		}

		public Task<int> RequestReturnResponseCodeAsync(string url, string method, List<KeyValuePair<string, string>> getParams = null)
		{
			return Task.Factory.StartNew(delegate
			{
				if (getParams != null)
				{
					for (int i = 0; i < getParams.Count; i++)
					{
						if (i == 0)
						{
							url = url + "?" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value);
						}
						else
						{
							url = url + "&" + getParams[i].Key + "=" + Uri.EscapeDataString(getParams[i].Value);
						}
					}
				}
				HttpWebRequest obj = (HttpWebRequest)WebRequest.Create(url);
				obj.Method = method;
				return (int)((HttpWebResponse)obj.GetResponse()).StatusCode;
			});
		}

		private void HandleWebException(WebException e)
		{
			if (!(e.Response is HttpWebResponse httpWebResponse))
			{
				throw e;
			}
			switch (httpWebResponse.StatusCode)
			{
			case HttpStatusCode.BadRequest:
				throw new BadRequestException("Your request failed because either: \n 1. Your ClientID was invalid/not set. \n 2. Your refresh token was invalid. \n 3. You requested a username when the server was expecting a user ID.");
			case HttpStatusCode.Unauthorized:
			{
				string[] values = httpWebResponse.Headers.GetValues("WWW-Authenticate");
				if ((values != null && values.Length == 0) || string.IsNullOrEmpty((values != null) ? values[0] : null))
				{
					throw new BadScopeException("Your request was blocked due to bad credentials (do you have the right scope for your access token?).");
				}
				if (values[0].Contains("error='invalid_token'"))
				{
					throw new TokenExpiredException("Your request was blocked du to an expired Token. Please refresh your token and update your API instance settings.");
				}
				break;
			}
			case HttpStatusCode.NotFound:
				throw new BadResourceException("The resource you tried to access was not valid.");
			case HttpStatusCode.TooManyRequests:
			{
				string resetTime = httpWebResponse.Headers.Get("Ratelimit-Reset");
				throw new TooManyRequestsException("You have reached your rate limit. Too many requests were made", resetTime);
			}
			default:
				throw e;
			}
		}
	}
}
namespace TwitchLib.Api.Core.Extensions.System
{
	public static class DateTimeExtensions
	{
		public static string ToRfc3339String(this DateTime dateTime)
		{
			return dateTime.ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo);
		}
	}
	public static class IEnumerableExtensions
	{
		public static void AddTo<T>(this IEnumerable<T> source, List<T> destination)
		{
			if (source != null)
			{
				destination.AddRange(source);
			}
		}
	}
}
namespace TwitchLib.Api.Core.Extensions.RateLimiter
{
	public static class IAwaitableConstraintExtension
	{
		public static IAwaitableConstraint Compose(this IAwaitableConstraint ac1, IAwaitableConstraint ac2)
		{
			if (ac1 != ac2)
			{
				return (IAwaitableConstraint)(object)new ComposedAwaitableConstraint(ac1, ac2);
			}
			return ac1;
		}
	}
}
namespace TwitchLib.Api.Core.Exceptions
{
	public class BadGatewayException : Exception
	{
		public BadGatewayException(string data)
			: base(data)
		{
		}
	}
	public class BadParameterException : Exception
	{
		public BadParameterException(string badParamData)
			: base(badParamData)
		{
		}
	}
	public class BadRequestException : Exception
	{
		public BadRequestException(string apiData)
			: base(apiData)
		{
		}
	}
	public class BadResourceException : Exception
	{
		public BadResourceException(string apiData)
			: base(apiData)
		{
		}
	}
	public class BadScopeException : Exception
	{
		public BadScopeException(string data)
			: base(data)
		{
		}
	}
	public class BadTokenException : Exception
	{
		public BadTokenException(string data)
			: base(data)
		{
		}
	}
	public class ClientIdAndOAuthTokenRequired : Exception
	{
		public ClientIdAndOAuthTokenRequired(string explanation)
			: base(explanation)
		{
		}
	}
	public class GatewayTimeoutException : Exception
	{
		public GatewayTimeoutException(string data)
			: base(data)
		{
		}
	}
	public class InternalServerErrorException : Exception
	{
		public InternalServerErrorException(string data)
			: base(data)
		{
		}
	}
	public class InvalidCredentialException : Exception
	{
		public InvalidCredentialException(string data)
			: base(data)
		{
		}
	}
	public class TokenExpiredException : Exception
	{
		public TokenExpiredException(string data)
			: base(data)
		{
		}
	}
	public sealed class TooManyRequestsException : Exception
	{
		public TooManyRequestsException(string data, string resetTime)
			: base(data)
		{
			if (double.TryParse(resetTime, out var result))
			{
				Data.Add("Ratelimit-Reset", result);
			}
		}
	}
	public class UnexpectedResponseException : Exception
	{
		public UnexpectedResponseException(string data)
			: base(data)
		{
		}
	}
}
namespace TwitchLib.Api.Core.Common
{
	public static class Helpers
	{
		public static string FormatOAuth(string token)
		{
			if (!token.Contains(" "))
			{
				return token;
			}
			return token.Split(new char[1] { ' ' })[1];
		}

		public static string AuthScopesToString(AuthScopes scope)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected I4, but got Unknown
			return (int)scope switch
			{
				1 => "channel_check_subscription", 
				2 => "channel_commercial", 
				3 => "channel_editor", 
				4 => "channel_feed_edit", 
				5 => "channel_feed_read", 
				9 => "chat:read", 
				11 => "chat:moderate", 
				10 => "chat:edit", 
				6 => "channel_read", 
				7 => "channel_stream", 
				8 => "channel_subscriptions", 
				12 => "collections_edit", 
				13 => "communities_edit", 
				14 => "communities_moderate", 
				21 => "openid", 
				15 => "user_blocks_edit", 
				16 => "user_blocks_read", 
				17 => "user_follows_edit", 
				18 => "user_read", 
				19 => "user_subscriptions", 
				20 => "viewing_activity_read", 
				22 => "analytics:read:extensions", 
				23 => "analytics:read:games", 
				24 => "bits:read", 
				25 => "channel:edit:commercial", 
				26 => "channel:manage:broadcast", 
				27 => "channel:manage:extensions", 
				28 => "channel:manage:moderators", 
				31 => "channel:manage:redemptions", 
				29 => "channel:manage:polls", 
				30 => "channel:manage:predictions", 
				32 => "channel:manage:schedule", 
				33 => "channel:manage:videos", 
				34 => "channel:manage:vips", 
				35 => "channel:read:charity", 
				36 => "channel:read:editors", 
				37 => "channel:read:goals", 
				38 => "channel:read:hype_train", 
				39 => "channel:read:polls", 
				40 => "channel:read:predictions", 
				41 => "channel:read:redemptions", 
				42 => "channel:read:stream_key", 
				43 => "channel:read:subscriptions", 
				44 => "channel:read:vips", 
				45 => "clips:edit", 
				46 => "moderation:read", 
				58 => "user:edit", 
				59 => "user:edit:broadcast", 
				60 => "user:edit:follows", 
				64 => "user:read:blocked_users", 
				65 => "user:read:broadcast", 
				66 => "user:read:email", 
				67 => "user:read:follows", 
				68 => "user:read:subscriptions", 
				61 => "user:manage:blocked_users", 
				62 => "user:manage:chat_color", 
				63 => "user:manage:whispers", 
				49 => "moderator:manage:announcements", 
				50 => "moderator:manage:automod", 
				51 => "moderator:manage:automod_settings", 
				47 => "moderator:manage:banned_users", 
				48 => "moderator:manage:blocked_terms", 
				52 => "moderator:manage:chat_messages", 
				53 => "moderator:manage:chat_settings", 
				55 => "moderator:read:automod_settings", 
				54 => "moderator:read:blocked_terms", 
				56 => "moderator:read:chat_settings", 
				57 => "moderator:read:chatters", 
				_ => "", 
			};
		}

		public static string Base64Encode(string plainText)
		{
			return Convert.ToBase64String(Encoding.UTF8.GetBytes(plainText));
		}
	}
}

plugins/TwitchLib/TwitchLib.Api.Core.Enums.dll

Decompiled 6 months ago
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Project containing the enums of TwitchLib.Api")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api.Core.Enums")]
[assembly: AssemblyTitle("TwitchLib.Api.Core.Enums")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api.Core.Enums;

public enum ApiVersion
{
	Auth = 1,
	Helix = 6,
	Void = 0
}
public enum AuthScopes
{
	Any,
	Channel_Check_Subscription,
	Channel_Commercial,
	Channel_Editor,
	Channel_Feed_Edit,
	Channel_Feed_Read,
	Channel_Read,
	Channel_Stream,
	Channel_Subscriptions,
	Chat_Read,
	Chat_Edit,
	Chat_Moderate,
	Collections_Edit,
	Communities_Edit,
	Communities_Moderate,
	User_Blocks_Edit,
	User_Blocks_Read,
	User_Follows_Edit,
	User_Read,
	User_Subscriptions,
	Viewing_Activity_Read,
	OpenId,
	Helix_Analytics_Read_Extensions,
	Helix_Analytics_Read_Games,
	Helix_Bits_Read,
	Helix_Channel_Edit_Commercial,
	Helix_Channel_Manage_Broadcast,
	Helix_Channel_Manage_Extensions,
	Helix_Channel_Manage_Moderators,
	Helix_Channel_Manage_Polls,
	Helix_Channel_Manage_Predictions,
	Helix_Channel_Manage_Redemptions,
	Helix_Channel_Manage_Schedule,
	Helix_Channel_Manage_Videos,
	Helix_Channel_Manage_VIPs,
	Helix_Channel_Read_Charity,
	Helix_Channel_Read_Editors,
	Helix_Channel_Read_Goals,
	Helix_Channel_Read_Hype_Train,
	Helix_Channel_Read_Polls,
	Helix_Channel_Read_Predictions,
	Helix_Channel_Read_Redemptions,
	Helix_Channel_Read_Stream_Key,
	Helix_Channel_Read_Subscriptions,
	Helix_Channel_Read_VIPs,
	Helix_Clips_Edit,
	Helix_Moderation_Read,
	Helix_Moderator_Manage_Banned_Users,
	Helix_Moderator_Manage_Blocked_Terms,
	Helix_Moderator_Manage_Announcements,
	Helix_Moderator_Manage_Automod,
	Helix_Moderator_Manage_Automod_Settings,
	Helix_moderator_Manage_Chat_Messages,
	Helix_Moderator_Manage_Chat_Settings,
	Helix_Moderator_Read_Blocked_Terms,
	Helix_Moderator_Read_Automod_Settings,
	Helix_Moderator_Read_Chat_Settings,
	Helix_Moderator_Read_Chatters,
	Helix_User_Edit,
	Helix_User_Edit_Broadcast,
	Helix_User_Edit_Follows,
	Helix_User_Manage_BlockedUsers,
	Helix_User_Manage_Chat_Color,
	Helix_User_Manage_Whispers,
	Helix_User_Read_BlockedUsers,
	Helix_User_Read_Broadcast,
	Helix_User_Read_Email,
	Helix_User_Read_Follows,
	Helix_User_Read_Subscriptions,
	None
}
public enum BadgeColor
{
	Red = 10000,
	Blue = 5000,
	Green = 1000,
	Purple = 100,
	Gray = 1
}
public enum BitsLeaderboardPeriodEnum
{
	Day,
	Week,
	Month,
	Year,
	All
}
public enum BlockUserReasonEnum
{
	Spam,
	Harassment,
	Other
}
public enum BlockUserSourceContextEnum
{
	Chat,
	Whisper
}
public enum CodeStatusEnum
{
	SUCCESSFULLY_REDEEMED,
	ALREADY_CLAIMED,
	EXPIRED,
	USER_NOT_ELIGIBLE,
	NOT_FOUND,
	INACTIVE,
	UNUSED,
	INCORRECT_FORMAT,
	INTERNAL_ERROR
}
public enum CustomRewardRedemptionStatus
{
	UNFULFILLED,
	FULFILLED,
	CANCELED
}
public enum DropEntitlementUpdateStatus
{
	SUCCESS,
	UNAUTHORIZED,
	UPDATE_FAILED,
	INVALID_ID,
	NOT_FOUND
}
public enum EventSubTransportMethod
{
	Webhook,
	Websocket
}
public enum ExtensionState
{
	InTest,
	InReview,
	Rejected,
	Approved,
	Released,
	Deprecated,
	PendingAction,
	AssetsUploaded,
	Deleted
}
public enum ExtensionType
{
	Panel,
	Overlay,
	Component
}
public enum FulfillmentStatus
{
	CLAIMED,
	FULFILLED
}
public enum LogType
{
	Normal,
	Failure,
	Success
}
public enum ManageHeldAutoModMessageActionEnum
{
	ALLOW,
	DENY
}
public enum Period
{
	Day,
	Week,
	Month,
	All
}
public enum PollStatusEnum
{
	TERMINATED,
	ARCHIVED
}
public enum PredictionEndStatus
{
	RESOLVED,
	CANCELED,
	LOCKED
}
public enum PredictionStatus
{
	ACTIVE,
	RESOLVED,
	CANCELED,
	LOCKED
}
public abstract class StringEnum
{
	public string Value { get; }

	protected StringEnum(string value)
	{
		Value = value;
	}

	public override string ToString()
	{
		return Value;
	}
}
public enum UserType : byte
{
	Viewer,
	VIP,
	Moderator,
	GlobalModerator,
	Broadcaster,
	Admin,
	Staff
}
public enum VideoSort
{
	Time,
	Trending,
	Views
}
public enum VideoType
{
	All,
	Upload,
	Archive,
	Highlight
}

plugins/TwitchLib/TwitchLib.Api.Core.Interfaces.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using TwitchLib.Api.Core.Enums;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Project containing all of the interfaces used in TwitchLib.Api")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api.Core.Interfaces")]
[assembly: AssemblyTitle("TwitchLib.Api.Core.Interfaces")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api.Core.Interfaces;

public interface IApiSettings
{
	string AccessToken { get; set; }

	string Secret { get; set; }

	string ClientId { get; set; }

	bool SkipDynamicScopeValidation { get; set; }

	bool SkipAutoServerTokenGeneration { get; set; }

	List<AuthScopes> Scopes { get; set; }

	event PropertyChangedEventHandler PropertyChanged;
}
public interface IAwaitableConstraint
{
	Task<IDisposable> WaitForReadiness(CancellationToken cancellationToken);
}
public interface IFollow
{
	DateTime CreatedAt { get; }

	bool Notifications { get; }

	IUser User { get; }
}
public interface IFollows
{
	int Total { get; }

	string Cursor { get; }

	IFollow[] Follows { get; }
}
public interface IHttpCallHandler
{
	Task<KeyValuePair<int, string>> GeneralRequestAsync(string url, string method, string payload = null, ApiVersion api = 6, string clientId = null, string accessToken = null);

	Task PutBytesAsync(string url, byte[] payload);

	Task<int> RequestReturnResponseCodeAsync(string url, string method, List<KeyValuePair<string, string>> getParams = null);
}
public interface IRateLimiter
{
	Task Perform(Func<Task> perform, CancellationToken cancellationToken);

	Task Perform(Func<Task> perform);

	Task<T> Perform<T>(Func<Task<T>> perform);

	Task<T> Perform<T>(Func<Task<T>> perform, CancellationToken cancellationToken);

	Task Perform(Action perform, CancellationToken cancellationToken);

	Task Perform(Action perform);

	Task<T> Perform<T>(Func<T> perform);

	Task<T> Perform<T>(Func<T> perform, CancellationToken cancellationToken);
}
public interface ITime
{
	DateTime GetTimeNow();

	Task GetDelay(TimeSpan timespan, CancellationToken cancellationToken);
}
public interface IUser
{
	string Id { get; }

	string Bio { get; }

	DateTime CreatedAt { get; }

	string DisplayName { get; }

	string Logo { get; }

	string Name { get; }

	string Type { get; }

	DateTime UpdatedAt { get; }
}

plugins/TwitchLib/TwitchLib.Api.Core.Models.dll

Decompiled 6 months ago
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Newtonsoft.Json;
using TwitchLib.Api.Core.Enums;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Project containing the core models used in TwitchLib.Api")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api.Core.Models")]
[assembly: AssemblyTitle("TwitchLib.Api.Core.Models")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api.Core.Models
{
	public abstract class RequestModel
	{
	}
}
namespace TwitchLib.Api.Core.Models.Undocumented.Chatters
{
	public class ChatterFormatted
	{
		public string Username { get; protected set; }

		public UserType UserType { get; set; }

		public ChatterFormatted(string username, UserType userType)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Username = username;
			UserType = userType;
		}
	}
	public class Chatters
	{
		[JsonProperty(PropertyName = "moderators")]
		public string[] Moderators { get; protected set; }

		[JsonProperty(PropertyName = "staff")]
		public string[] Staff { get; protected set; }

		[JsonProperty(PropertyName = "admins")]
		public string[] Admins { get; protected set; }

		[JsonProperty(PropertyName = "global_mods")]
		public string[] GlobalMods { get; protected set; }

		[JsonProperty(PropertyName = "vips")]
		public string[] VIP { get; protected set; }

		[JsonProperty(PropertyName = "viewers")]
		public string[] Viewers { get; protected set; }
	}
	public class ChattersResponse
	{
		[JsonProperty(PropertyName = "chatter_count")]
		public int ChatterCount { get; protected set; }

		[JsonProperty(PropertyName = "chatters")]
		public Chatters Chatters { get; protected set; }
	}
}

plugins/TwitchLib/TwitchLib.Api.dll

Decompiled 6 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using System.Timers;
using System.Web;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TwitchLib.Api.Auth;
using TwitchLib.Api.Core;
using TwitchLib.Api.Core.Common;
using TwitchLib.Api.Core.Enums;
using TwitchLib.Api.Core.Exceptions;
using TwitchLib.Api.Core.HttpCallHandlers;
using TwitchLib.Api.Core.Interfaces;
using TwitchLib.Api.Core.RateLimiter;
using TwitchLib.Api.Core.Undocumented;
using TwitchLib.Api.Events;
using TwitchLib.Api.Helix;
using TwitchLib.Api.Helix.Models.Helpers;
using TwitchLib.Api.Helix.Models.Streams.GetStreams;
using TwitchLib.Api.Helix.Models.Users.GetUserFollows;
using TwitchLib.Api.Helix.Models.Users.GetUsers;
using TwitchLib.Api.Interfaces;
using TwitchLib.Api.Services.Core;
using TwitchLib.Api.Services.Core.FollowerService;
using TwitchLib.Api.Services.Core.LiveStreamMonitor;
using TwitchLib.Api.Services.Events;
using TwitchLib.Api.Services.Events.FollowerService;
using TwitchLib.Api.Services.Events.LiveStreamMonitor;
using TwitchLib.Api.ThirdParty;
using TwitchLib.Api.ThirdParty.AuthorizationFlow;
using TwitchLib.Api.ThirdParty.ModLookup;
using TwitchLib.Api.ThirdParty.UsernameChange;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Api component of TwitchLib. This component allows you to access the Twitch API, as well as undocumented and third party APIs.")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api")]
[assembly: AssemblyTitle("TwitchLib.Api")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api
{
	public class TwitchAPI : ITwitchAPI
	{
		private readonly ILogger<TwitchAPI> _logger;

		public IApiSettings Settings { get; }

		public TwitchLib.Api.Auth.Auth Auth { get; }

		public Helix Helix { get; }

		public TwitchLib.Api.ThirdParty.ThirdParty ThirdParty { get; }

		public Undocumented Undocumented { get; }

		public TwitchAPI(ILoggerFactory loggerFactory = null, IRateLimiter rateLimiter = null, IApiSettings settings = null, IHttpCallHandler http = null)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			_logger = loggerFactory?.CreateLogger<TwitchAPI>();
			rateLimiter = (IRateLimiter)(((object)rateLimiter) ?? ((object)BypassLimiter.CreateLimiterBypassInstance()));
			http = (IHttpCallHandler)(((object)http) ?? ((object)new TwitchHttpClient(loggerFactory?.CreateLogger<TwitchHttpClient>())));
			Settings = (IApiSettings)(((object)settings) ?? ((object)new ApiSettings()));
			Auth = new TwitchLib.Api.Auth.Auth(Settings, rateLimiter, http);
			Helix = new Helix(loggerFactory, rateLimiter, Settings, http);
			ThirdParty = new TwitchLib.Api.ThirdParty.ThirdParty(Settings, rateLimiter, http);
			Undocumented = new Undocumented(Settings, rateLimiter, http);
			Settings.PropertyChanged += SettingsPropertyChanged;
		}

		private void SettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			switch (e.PropertyName)
			{
			case "AccessToken":
				Helix.Settings.AccessToken = Settings.AccessToken;
				break;
			case "Secret":
				Helix.Settings.Secret = Settings.Secret;
				break;
			case "ClientId":
				Helix.Settings.ClientId = Settings.ClientId;
				break;
			case "SkipDynamicScopeValidation":
				Helix.Settings.SkipDynamicScopeValidation = Settings.SkipDynamicScopeValidation;
				break;
			case "SkipAutoServerTokenGeneration":
				Helix.Settings.SkipAutoServerTokenGeneration = Settings.SkipAutoServerTokenGeneration;
				break;
			case "Scopes":
				Helix.Settings.Scopes = Settings.Scopes;
				break;
			}
		}
	}
}
namespace TwitchLib.Api.ThirdParty
{
	public class ThirdParty
	{
		public class UsernameChangeApi : ApiBase
		{
			public UsernameChangeApi(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
				: base(settings, rateLimiter, http)
			{
			}

			public Task<List<UsernameChangeListing>> GetUsernameChangesAsync(string username)
			{
				List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
				{
					new KeyValuePair<string, string>("q", username),
					new KeyValuePair<string, string>("format", "json")
				};
				return ((ApiBase)this).GetGenericAsync<List<UsernameChangeListing>>("https://twitch-tools.rootonline.de/username_changelogs_search.php", list, (string)null, (ApiVersion)0, (string)null);
			}
		}

		public class ModLookupApi : ApiBase
		{
			public ModLookupApi(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
				: base(settings, rateLimiter, http)
			{
			}

			public Task<ModLookupResponse> GetChannelsModdedForByNameAsync(string username, int offset = 0, int limit = 100, bool useTls12 = true)
			{
				if (useTls12)
				{
					ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
				}
				List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
				{
					new KeyValuePair<string, string>("offset", offset.ToString()),
					new KeyValuePair<string, string>("limit", limit.ToString())
				};
				return ((ApiBase)this).GetGenericAsync<ModLookupResponse>("https://twitchstuff.3v.fi/modlookup/api/user/" + username, list, (string)null, (ApiVersion)0, (string)null);
			}

			public Task<TopResponse> GetChannelsModdedForByTopAsync(bool useTls12 = true)
			{
				if (useTls12)
				{
					ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
				}
				return ((ApiBase)this).GetGenericAsync<TopResponse>("https://twitchstuff.3v.fi/modlookup/api/top", (List<KeyValuePair<string, string>>)null, (string)null, (ApiVersion)6, (string)null);
			}

			public Task<StatsResponse> GetChannelsModdedForStatsAsync(bool useTls12 = true)
			{
				if (useTls12)
				{
					ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
				}
				return ((ApiBase)this).GetGenericAsync<StatsResponse>("https://twitchstuff.3v.fi/modlookup/api/stats", (List<KeyValuePair<string, string>>)null, (string)null, (ApiVersion)6, (string)null);
			}
		}

		public class AuthorizationFlowApi : ApiBase
		{
			private const string BaseUrl = "https://twitchtokengenerator.com/api";

			private string _apiId;

			private Timer _pingTimer;

			public event EventHandler<OnUserAuthorizationDetectedArgs> OnUserAuthorizationDetected;

			public event EventHandler<OnAuthorizationFlowErrorArgs> OnError;

			public AuthorizationFlowApi(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
				: base(settings, rateLimiter, http)
			{
			}

			public CreatedFlow CreateFlow(string applicationTitle, IEnumerable<AuthScopes> scopes)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				string text = null;
				foreach (AuthScopes scope in scopes)
				{
					text = ((text != null) ? (text + "+" + Helpers.AuthScopesToString(scope)) : Helpers.AuthScopesToString(scope));
				}
				string address = "https://twitchtokengenerator.com/api/create/" + Helpers.Base64Encode(applicationTitle) + "/" + text;
				return JsonConvert.DeserializeObject<CreatedFlow>(new WebClient().DownloadString(address));
			}

			public RefreshTokenResponse RefreshToken(string refreshToken)
			{
				string address = "https://twitchtokengenerator.com/api/refresh/" + refreshToken;
				return JsonConvert.DeserializeObject<RefreshTokenResponse>(new WebClient().DownloadString(address));
			}

			public void BeginPingingStatus(string id, int intervalMs = 5000)
			{
				_apiId = id;
				_pingTimer = new Timer(intervalMs);
				_pingTimer.Elapsed += OnPingTimerElapsed;
				_pingTimer.Start();
			}

			public PingResponse PingStatus(string id = null)
			{
				if (id != null)
				{
					_apiId = id;
				}
				return new PingResponse(new WebClient().DownloadString("https://twitchtokengenerator.com/api/status/" + _apiId));
			}

			private void OnPingTimerElapsed(object sender, ElapsedEventArgs e)
			{
				PingResponse pingResponse = PingStatus();
				if (pingResponse.Success)
				{
					_pingTimer.Stop();
					this.OnUserAuthorizationDetected?.Invoke(null, new OnUserAuthorizationDetectedArgs
					{
						Id = pingResponse.Id,
						Scopes = pingResponse.Scopes,
						Token = pingResponse.Token,
						Username = pingResponse.Username,
						Refresh = pingResponse.Refresh,
						ClientId = pingResponse.ClientId
					});
				}
				else if (pingResponse.Error != 3)
				{
					_pingTimer.Stop();
					this.OnError?.Invoke(null, new OnAuthorizationFlowErrorArgs
					{
						Error = pingResponse.Error,
						Message = pingResponse.Message
					});
				}
			}
		}

		public UsernameChangeApi UsernameChange { get; }

		public ModLookupApi ModLookup { get; }

		public AuthorizationFlowApi AuthorizationFlow { get; }

		public ThirdParty(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		{
			UsernameChange = new UsernameChangeApi(settings, rateLimiter, http);
			ModLookup = new ModLookupApi(settings, rateLimiter, http);
			AuthorizationFlow = new AuthorizationFlowApi(settings, rateLimiter, http);
		}
	}
}
namespace TwitchLib.Api.ThirdParty.UsernameChange
{
	public class UsernameChangeListing
	{
		[JsonProperty(PropertyName = "userid")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "username_old")]
		public string UsernameOld { get; protected set; }

		[JsonProperty(PropertyName = "username_new")]
		public string UsernameNew { get; protected set; }

		[JsonProperty(PropertyName = "found_at")]
		public DateTime FoundAt { get; protected set; }
	}
	public class UsernameChangeResponse
	{
		public UsernameChangeListing[] UsernameChangeListings { get; protected set; }
	}
}
namespace TwitchLib.Api.ThirdParty.ModLookup
{
	public class ModLookupListing
	{
		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "followers")]
		public int Followers { get; protected set; }

		[JsonProperty(PropertyName = "views")]
		public int Views { get; protected set; }

		[JsonProperty(PropertyName = "partnered")]
		public bool Partnered { get; protected set; }
	}
	public class ModLookupResponse
	{
		[JsonProperty(PropertyName = "status")]
		public int Status { get; protected set; }

		[JsonProperty(PropertyName = "user")]
		public string User { get; protected set; }

		[JsonProperty(PropertyName = "count")]
		public int Count { get; protected set; }

		[JsonProperty(PropertyName = "channels")]
		public ModLookupListing[] Channels { get; protected set; }
	}
	public class Stats
	{
		[JsonProperty(PropertyName = "relations")]
		public int Relations { get; protected set; }

		[JsonProperty(PropertyName = "channels_total")]
		public int ChannelsTotal { get; protected set; }

		[JsonProperty(PropertyName = "users")]
		public int Users { get; protected set; }

		[JsonProperty(PropertyName = "channels_no_mods")]
		public int ChannelsNoMods { get; protected set; }

		[JsonProperty(PropertyName = "channels_only_broadcaster")]
		public int ChannelsOnlyBroadcaster { get; protected set; }
	}
	public class StatsResponse
	{
		[JsonProperty(PropertyName = "status")]
		public int Status { get; protected set; }

		[JsonProperty(PropertyName = "stats")]
		public Stats Stats { get; protected set; }
	}
	public class Top
	{
		[JsonProperty(PropertyName = "modcount")]
		public ModLookupListing[] ModCount { get; protected set; }

		[JsonProperty(PropertyName = "views")]
		public ModLookupListing[] Views { get; protected set; }

		[JsonProperty(PropertyName = "followers")]
		public ModLookupListing[] Followers { get; protected set; }
	}
	public class TopResponse
	{
		[JsonProperty(PropertyName = "status")]
		public int Status { get; protected set; }

		[JsonProperty(PropertyName = "top")]
		public Top Top { get; protected set; }
	}
}
namespace TwitchLib.Api.ThirdParty.AuthorizationFlow
{
	public class CreatedFlow
	{
		[JsonProperty(PropertyName = "message")]
		public string Url { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }
	}
	public class PingResponse
	{
		public bool Success { get; protected set; }

		public string Id { get; protected set; }

		public int Error { get; protected set; }

		public string Message { get; protected set; }

		public List<AuthScopes> Scopes { get; protected set; }

		public string Token { get; protected set; }

		public string Refresh { get; protected set; }

		public string Username { get; protected set; }

		public string ClientId { get; protected set; }

		public PingResponse(string jsonStr)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			JObject val = JObject.Parse(jsonStr);
			Success = bool.Parse(((object)((JToken)val).SelectToken("success")).ToString());
			if (!Success)
			{
				Error = int.Parse(((object)((JToken)val).SelectToken("error")).ToString());
				Message = ((object)((JToken)val).SelectToken("message")).ToString();
				return;
			}
			Scopes = new List<AuthScopes>();
			foreach (JToken item in (IEnumerable<JToken>)((JToken)val).SelectToken("scopes"))
			{
				Scopes.Add(StringToScope(((object)item).ToString()));
			}
			Token = ((object)((JToken)val).SelectToken("token")).ToString();
			Refresh = ((object)((JToken)val).SelectToken("refresh")).ToString();
			Username = ((object)((JToken)val).SelectToken("username")).ToString();
			ClientId = ((object)((JToken)val).SelectToken("client_id")).ToString();
		}

		private AuthScopes StringToScope(string scope)
		{
			return (AuthScopes)(scope switch
			{
				"user_read" => 18, 
				"user_blocks_edit" => 15, 
				"user_blocks_read" => 16, 
				"user_follows_edit" => 17, 
				"channel_read" => 6, 
				"channel_commercial" => 2, 
				"channel_stream" => 8, 
				"channel_subscriptions" => 8, 
				"user_subscriptions" => 19, 
				"channel_check_subscription" => 1, 
				"chat:read" => 9, 
				"chat:edit" => 10, 
				"chat:moderate" => 11, 
				"channel_editor" => 3, 
				"channel_feed_read" => 5, 
				"channel_feed_edit" => 4, 
				"collections_edit" => 12, 
				"communities_edit" => 13, 
				"communities_moderate" => 14, 
				"viewing_activity_read" => 20, 
				"user:edit" => 58, 
				"user:read:email" => 66, 
				"clips:edit" => 45, 
				"analytics:read:games" => 23, 
				"bits:read" => 24, 
				"channel:read:subscriptions" => 43, 
				"channel:read:hype_train" => 38, 
				"channel:manage:redemptions" => 31, 
				"channel:edit:commercial" => 25, 
				"channel:read:stream_key" => 42, 
				"channel:read:editors" => 36, 
				"channel:manage:videos" => 33, 
				"user:read:blocked_users" => 64, 
				"user:manage:blocked_users" => 61, 
				"user:read:subscriptions" => 68, 
				"channel:manage:polls" => 29, 
				"channel:manage:predictions" => 30, 
				"channel:read:polls" => 39, 
				"channel:read:predictions" => 40, 
				"moderator:manage:automod" => 50, 
				"moderator:read:chatters" => 57, 
				"" => 69, 
				_ => throw new Exception("Unknown scope"), 
			});
		}
	}
	public class RefreshTokenResponse
	{
		[JsonProperty(PropertyName = "token")]
		public string Token { get; protected set; }

		[JsonProperty(PropertyName = "refresh")]
		public string Refresh { get; protected set; }

		[JsonProperty(PropertyName = "client_id")]
		public string ClientId { get; protected set; }
	}
}
namespace TwitchLib.Api.Services
{
	public class ApiService
	{
		protected readonly ITwitchAPI _api;

		private readonly ServiceTimer _serviceTimer;

		public List<string> ChannelsToMonitor { get; private set; }

		public int IntervalInSeconds => _serviceTimer.IntervalInSeconds;

		public bool Enabled => _serviceTimer.Enabled;

		public event EventHandler<OnServiceStartedArgs> OnServiceStarted;

		public event EventHandler<OnServiceStoppedArgs> OnServiceStopped;

		public event EventHandler<OnServiceTickArgs> OnServiceTick;

		public event EventHandler<OnChannelsSetArgs> OnChannelsSet;

		protected ApiService(ITwitchAPI api, int checkIntervalInSeconds)
		{
			if (checkIntervalInSeconds < 1)
			{
				throw new ArgumentException("The interval must be 1 second or more.", "checkIntervalInSeconds");
			}
			_api = api ?? throw new ArgumentNullException("api");
			_serviceTimer = new ServiceTimer(OnServiceTimerTick, checkIntervalInSeconds);
		}

		public virtual void Start()
		{
			if (ChannelsToMonitor == null)
			{
				throw new InvalidOperationException("You must atleast add 1 channel to service before starting it.");
			}
			if (_serviceTimer.Enabled)
			{
				throw new InvalidOperationException("The service has already been started.");
			}
			_serviceTimer.Start();
			this.OnServiceStarted?.Invoke(this, new OnServiceStartedArgs());
		}

		public virtual void Stop()
		{
			if (!_serviceTimer.Enabled)
			{
				throw new InvalidOperationException("The service hasn't started yet, or has already been stopped.");
			}
			_serviceTimer.Stop();
			this.OnServiceStopped?.Invoke(this, new OnServiceStoppedArgs());
		}

		protected virtual void SetChannels(List<string> channelsToMonitor)
		{
			if (channelsToMonitor == null)
			{
				throw new ArgumentNullException("channelsToMonitor");
			}
			if (channelsToMonitor.Count == 0)
			{
				throw new ArgumentException("The provided list is empty.", "channelsToMonitor");
			}
			ChannelsToMonitor = channelsToMonitor;
			this.OnChannelsSet?.Invoke(this, new OnChannelsSetArgs
			{
				Channels = channelsToMonitor
			});
		}

		protected virtual Task OnServiceTimerTick()
		{
			this.OnServiceTick?.Invoke(this, new OnServiceTickArgs());
			return Task.CompletedTask;
		}
	}
	public class FollowerService : ApiService
	{
		private readonly Dictionary<string, DateTime> _lastFollowerDates = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase);

		private readonly bool _invokeEventsOnStartup;

		private TwitchLib.Api.Services.Core.FollowerService.CoreMonitor _monitor;

		private TwitchLib.Api.Services.Core.FollowerService.IdBasedMonitor _idBasedMonitor;

		private TwitchLib.Api.Services.Core.FollowerService.NameBasedMonitor _nameBasedMonitor;

		public Dictionary<string, List<Follow>> KnownFollowers { get; } = new Dictionary<string, List<Follow>>(StringComparer.OrdinalIgnoreCase);


		public int QueryCountPerRequest { get; }

		public int CacheSize { get; }

		private TwitchLib.Api.Services.Core.FollowerService.IdBasedMonitor IdBasedMonitor => _idBasedMonitor ?? (_idBasedMonitor = new TwitchLib.Api.Services.Core.FollowerService.IdBasedMonitor(_api));

		private TwitchLib.Api.Services.Core.FollowerService.NameBasedMonitor NameBasedMonitor => _nameBasedMonitor ?? (_nameBasedMonitor = new TwitchLib.Api.Services.Core.FollowerService.NameBasedMonitor(_api));

		public event EventHandler<OnNewFollowersDetectedArgs> OnNewFollowersDetected;

		public FollowerService(ITwitchAPI api, int checkIntervalInSeconds = 60, int queryCountPerRequest = 100, int cacheSize = 1000, bool invokeEventsOnStartup = false)
			: base(api, checkIntervalInSeconds)
		{
			if (queryCountPerRequest < 1 || queryCountPerRequest > 100)
			{
				throw new ArgumentException("Twitch doesn't support less than 1 or more than 100 followers per request.", "queryCountPerRequest");
			}
			if (cacheSize < queryCountPerRequest)
			{
				throw new ArgumentException("The cache size must be at least the size of the queryCountPerRequest parameter.", "cacheSize");
			}
			QueryCountPerRequest = queryCountPerRequest;
			CacheSize = cacheSize;
			_invokeEventsOnStartup = invokeEventsOnStartup;
		}

		public void ClearCache()
		{
			KnownFollowers.Clear();
			_lastFollowerDates.Clear();
			_nameBasedMonitor?.ClearCache();
			_nameBasedMonitor = null;
			_idBasedMonitor = null;
		}

		public void SetChannelsById(List<string> channelsToMonitor)
		{
			SetChannels(channelsToMonitor);
			_monitor = IdBasedMonitor;
		}

		public void SetChannelsByName(List<string> channelsToMonitor)
		{
			SetChannels(channelsToMonitor);
			_monitor = NameBasedMonitor;
		}

		public async Task UpdateLatestFollowersAsync(bool callEvents = true)
		{
			if (base.ChannelsToMonitor == null)
			{
				return;
			}
			foreach (string channel in base.ChannelsToMonitor)
			{
				List<Follow> list = await GetLatestFollowersAsync(channel);
				if (list.Count == 0)
				{
					return;
				}
				List<Follow> list2;
				if (!KnownFollowers.TryGetValue(channel, out var value))
				{
					list2 = list;
					KnownFollowers[channel] = list.Take(CacheSize).ToList();
					_lastFollowerDates[channel] = list.Last().FollowedAt;
					if (!_invokeEventsOnStartup)
					{
						return;
					}
				}
				else
				{
					HashSet<string> hashSet = new HashSet<string>(value.Select((Follow f) => f.FromUserId));
					DateTime dateTime = _lastFollowerDates[channel];
					list2 = new List<Follow>();
					foreach (Follow item in list)
					{
						if (hashSet.Add(item.FromUserId) && !(item.FollowedAt < dateTime))
						{
							list2.Add(item);
							dateTime = item.FollowedAt;
							value.Add(item);
						}
					}
					hashSet.Clear();
					hashSet.TrimExcess();
					if (value.Count > CacheSize)
					{
						value.RemoveRange(0, value.Count - CacheSize);
					}
					if (list2.Count <= 0)
					{
						return;
					}
					_lastFollowerDates[channel] = dateTime;
				}
				if (!callEvents)
				{
					return;
				}
				this.OnNewFollowersDetected?.Invoke(this, new OnNewFollowersDetectedArgs
				{
					Channel = channel,
					NewFollowers = list2
				});
			}
		}

		protected override async Task OnServiceTimerTick()
		{
			await base.OnServiceTimerTick();
			await UpdateLatestFollowersAsync();
		}

		private async Task<List<Follow>> GetLatestFollowersAsync(string channel)
		{
			return (await _monitor.GetUsersFollowsAsync(channel, QueryCountPerRequest)).Follows.Reverse().ToList();
		}
	}
	public class LiveStreamMonitorService : ApiService
	{
		private TwitchLib.Api.Services.Core.LiveStreamMonitor.CoreMonitor _monitor;

		private TwitchLib.Api.Services.Core.LiveStreamMonitor.IdBasedMonitor _idBasedMonitor;

		private TwitchLib.Api.Services.Core.LiveStreamMonitor.NameBasedMonitor _nameBasedMonitor;

		public Dictionary<string, Stream> LiveStreams { get; } = new Dictionary<string, Stream>(StringComparer.OrdinalIgnoreCase);


		public int MaxStreamRequestCountPerRequest { get; }

		private TwitchLib.Api.Services.Core.LiveStreamMonitor.IdBasedMonitor IdBasedMonitor => _idBasedMonitor ?? (_idBasedMonitor = new TwitchLib.Api.Services.Core.LiveStreamMonitor.IdBasedMonitor(_api));

		private TwitchLib.Api.Services.Core.LiveStreamMonitor.NameBasedMonitor NameBasedMonitor => _nameBasedMonitor ?? (_nameBasedMonitor = new TwitchLib.Api.Services.Core.LiveStreamMonitor.NameBasedMonitor(_api));

		public event EventHandler<OnStreamOnlineArgs> OnStreamOnline;

		public event EventHandler<OnStreamOfflineArgs> OnStreamOffline;

		public event EventHandler<OnStreamUpdateArgs> OnStreamUpdate;

		public LiveStreamMonitorService(ITwitchAPI api, int checkIntervalInSeconds = 60, int maxStreamRequestCountPerRequest = 100)
			: base(api, checkIntervalInSeconds)
		{
			if (maxStreamRequestCountPerRequest < 1 || maxStreamRequestCountPerRequest > 100)
			{
				throw new ArgumentException("Twitch doesn't support less than 1 or more than 100 streams per request.", "maxStreamRequestCountPerRequest");
			}
			MaxStreamRequestCountPerRequest = maxStreamRequestCountPerRequest;
		}

		public void ClearCache()
		{
			LiveStreams.Clear();
			_nameBasedMonitor?.ClearCache();
			_nameBasedMonitor = null;
			_idBasedMonitor = null;
		}

		public void SetChannelsById(List<string> channelsToMonitor)
		{
			SetChannels(channelsToMonitor);
			_monitor = IdBasedMonitor;
		}

		public void SetChannelsByName(List<string> channelsToMonitor)
		{
			SetChannels(channelsToMonitor);
			_monitor = NameBasedMonitor;
		}

		public async Task UpdateLiveStreamersAsync(bool callEvents = true)
		{
			List<Stream> result = await GetLiveStreamersAsync();
			foreach (string channel in base.ChannelsToMonitor)
			{
				IEnumerable<Stream> source = result;
				Stream val = source.FirstOrDefault(await _monitor.CompareStream(channel));
				if (val != null)
				{
					HandleLiveStreamUpdate(channel, val, callEvents);
				}
				else
				{
					HandleOfflineStreamUpdate(channel, callEvents);
				}
			}
		}

		protected override async Task OnServiceTimerTick()
		{
			_ = 1;
			try
			{
				await base.OnServiceTimerTick();
				await UpdateLiveStreamersAsync();
			}
			catch
			{
			}
		}

		private void HandleLiveStreamUpdate(string channel, Stream liveStream, bool callEvents)
		{
			bool flag = LiveStreams.ContainsKey(channel);
			LiveStreams[channel] = liveStream;
			if (callEvents)
			{
				if (!flag)
				{
					this.OnStreamOnline?.Invoke(this, new OnStreamOnlineArgs
					{
						Channel = channel,
						Stream = liveStream
					});
				}
				else
				{
					this.OnStreamUpdate?.Invoke(this, new OnStreamUpdateArgs
					{
						Channel = channel,
						Stream = liveStream
					});
				}
			}
		}

		private void HandleOfflineStreamUpdate(string channel, bool callEvents)
		{
			if (LiveStreams.TryGetValue(channel, out var value))
			{
				LiveStreams.Remove(channel);
				if (callEvents)
				{
					this.OnStreamOffline?.Invoke(this, new OnStreamOfflineArgs
					{
						Channel = channel,
						Stream = value
					});
				}
			}
		}

		private async Task<List<Stream>> GetLiveStreamersAsync()
		{
			List<Stream> livestreamers = new List<Stream>();
			double pages = Math.Ceiling((double)base.ChannelsToMonitor.Count / (double)MaxStreamRequestCountPerRequest);
			for (int i = 0; (double)i < pages; i++)
			{
				List<string> channels = base.ChannelsToMonitor.Skip(i * MaxStreamRequestCountPerRequest).Take(MaxStreamRequestCountPerRequest).ToList();
				GetStreamsResponse val = await _monitor.GetStreamsAsync(channels);
				if (val.Streams != null)
				{
					livestreamers.AddRange(val.Streams);
				}
			}
			return livestreamers;
		}
	}
}
namespace TwitchLib.Api.Services.Events
{
	public class OnChannelsSetArgs : EventArgs
	{
		public List<string> Channels;
	}
	public class OnServiceStartedArgs : EventArgs
	{
	}
	public class OnServiceStoppedArgs : EventArgs
	{
	}
	public class OnServiceTickArgs : EventArgs
	{
	}
}
namespace TwitchLib.Api.Services.Events.LiveStreamMonitor
{
	public class OnStreamOfflineArgs : EventArgs
	{
		public string Channel;

		public Stream Stream;
	}
	public class OnStreamOnlineArgs : EventArgs
	{
		public string Channel;

		public Stream Stream;
	}
	public class OnStreamUpdateArgs : EventArgs
	{
		public string Channel;

		public Stream Stream;
	}
}
namespace TwitchLib.Api.Services.Events.FollowerService
{
	public class OnNewFollowersDetectedArgs : EventArgs
	{
		public string Channel;

		public List<Follow> NewFollowers;
	}
}
namespace TwitchLib.Api.Services.Core
{
	internal class ServiceTimer : Timer
	{
		public delegate Task ServiceTimerTick();

		private readonly ServiceTimerTick _serviceTimerTickAsyncCallback;

		public int IntervalInSeconds { get; }

		public ServiceTimer(ServiceTimerTick serviceTimerTickAsyncCallback, int intervalInSeconds = 60)
		{
			_serviceTimerTickAsyncCallback = serviceTimerTickAsyncCallback;
			base.Interval = intervalInSeconds * 1000;
			IntervalInSeconds = intervalInSeconds;
			base.Elapsed += async delegate(object sender, ElapsedEventArgs e)
			{
				await TimerElapsedAsync(sender, e);
			};
		}

		private async Task TimerElapsedAsync(object sender, ElapsedEventArgs e)
		{
			await _serviceTimerTickAsyncCallback();
		}
	}
}
namespace TwitchLib.Api.Services.Core.LiveStreamMonitor
{
	internal abstract class CoreMonitor
	{
		protected readonly ITwitchAPI _api;

		public abstract Task<GetStreamsResponse> GetStreamsAsync(List<string> channels, string accessToken = null);

		public abstract Task<Func<Stream, bool>> CompareStream(string channel, string accessToken = null);

		protected CoreMonitor(ITwitchAPI api)
		{
			_api = api;
		}
	}
	internal class IdBasedMonitor : CoreMonitor
	{
		public IdBasedMonitor(ITwitchAPI api)
			: base(api)
		{
		}

		public override Task<Func<Stream, bool>> CompareStream(string channel, string accessToken = null)
		{
			return Task.FromResult<Func<Stream, bool>>((Stream stream) => stream.UserId == channel);
		}

		public override Task<GetStreamsResponse> GetStreamsAsync(List<string> channels, string accessToken = null)
		{
			return _api.Helix.Streams.GetStreamsAsync((string)null, channels.Count, (List<string>)null, (List<string>)null, channels, (List<string>)null, accessToken);
		}
	}
	internal class NameBasedMonitor : CoreMonitor
	{
		private readonly ConcurrentDictionary<string, string> _channelToId = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		public NameBasedMonitor(ITwitchAPI api)
			: base(api)
		{
		}

		public override async Task<Func<Stream, bool>> CompareStream(string channel, string accessToken = null)
		{
			if (!_channelToId.TryGetValue(channel, out var channelId))
			{
				User? obj = (await _api.Helix.Users.GetUsersAsync((List<string>)null, new List<string> { channel }, accessToken)).Users.FirstOrDefault();
				channelId = ((obj != null) ? obj.Id : null);
				_channelToId[channel] = channelId ?? throw new InvalidOperationException("No channel with the name \"" + channel + "\" could be found.");
			}
			return (Stream stream) => stream.UserId == channelId;
		}

		public override Task<GetStreamsResponse> GetStreamsAsync(List<string> channels, string accessToken = null)
		{
			return _api.Helix.Streams.GetStreamsAsync((string)null, channels.Count, (List<string>)null, (List<string>)null, (List<string>)null, channels, accessToken);
		}

		public void ClearCache()
		{
			_channelToId.Clear();
		}
	}
}
namespace TwitchLib.Api.Services.Core.FollowerService
{
	internal abstract class CoreMonitor
	{
		protected readonly ITwitchAPI _api;

		public abstract Task<GetUsersFollowsResponse> GetUsersFollowsAsync(string channel, int queryCount);

		protected CoreMonitor(ITwitchAPI api)
		{
			_api = api;
		}
	}
	internal class IdBasedMonitor : CoreMonitor
	{
		public IdBasedMonitor(ITwitchAPI api)
			: base(api)
		{
		}

		public override Task<GetUsersFollowsResponse> GetUsersFollowsAsync(string channel, int queryCount)
		{
			return _api.Helix.Users.GetUsersFollowsAsync((string)null, (string)null, queryCount, (string)null, channel, (string)null);
		}
	}
	internal class NameBasedMonitor : CoreMonitor
	{
		private readonly ConcurrentDictionary<string, string> _channelToId = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		public NameBasedMonitor(ITwitchAPI api)
			: base(api)
		{
		}

		public override async Task<GetUsersFollowsResponse> GetUsersFollowsAsync(string channel, int queryCount)
		{
			if (!_channelToId.TryGetValue(channel, out var value))
			{
				User? obj = (await _api.Helix.Users.GetUsersAsync((List<string>)null, new List<string> { channel }, (string)null)).Users.FirstOrDefault();
				value = ((obj != null) ? obj.Id : null);
				_channelToId[channel] = value ?? throw new InvalidOperationException("No channel with the name \"" + channel + "\" could be found.");
			}
			return await _api.Helix.Users.GetUsersFollowsAsync((string)null, (string)null, queryCount, (string)null, value, (string)null);
		}

		public void ClearCache()
		{
			_channelToId.Clear();
		}
	}
}
namespace TwitchLib.Api.Interfaces
{
	public interface ITwitchAPI
	{
		IApiSettings Settings { get; }

		Helix Helix { get; }

		TwitchLib.Api.ThirdParty.ThirdParty ThirdParty { get; }

		Undocumented Undocumented { get; }
	}
}
namespace TwitchLib.Api.Helpers
{
	public static class ExtensionAnalyticsHelper
	{
		public static async Task<List<ExtensionAnalytics>> HandleUrlAsync(string url)
		{
			return ExtractData(await GetContentsAsync(url)).Select((Func<string, ExtensionAnalytics>)((string line) => new ExtensionAnalytics(line))).ToList();
		}

		private static IEnumerable<string> ExtractData(IEnumerable<string> cnts)
		{
			return cnts.Where((string line) => line.Any(char.IsDigit)).ToList();
		}

		private static async Task<string[]> GetContentsAsync(string url)
		{
			return (await new HttpClient().GetStringAsync(url)).Split(new string[1] { Environment.NewLine }, StringSplitOptions.None);
		}
	}
}
namespace TwitchLib.Api.Events
{
	public class OnAuthorizationFlowErrorArgs
	{
		public int Error { get; set; }

		public string Message { get; set; }
	}
	public class OnUserAuthorizationDetectedArgs
	{
		public string Id { get; set; }

		public List<AuthScopes> Scopes { get; set; }

		public string Username { get; set; }

		public string Token { get; set; }

		public string Refresh { get; set; }

		public string ClientId { get; set; }
	}
}
namespace TwitchLib.Api.Auth
{
	public class Auth : ApiBase
	{
		public Auth(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
			: base(settings, rateLimiter, http)
		{
		}

		public Task<RefreshResponse> RefreshAuthTokenAsync(string refreshToken, string clientSecret, string clientId = null)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			string text = clientId ?? base.Settings.ClientId;
			if (string.IsNullOrWhiteSpace(refreshToken))
			{
				throw new BadParameterException("The refresh token is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			if (string.IsNullOrWhiteSpace(clientSecret))
			{
				throw new BadParameterException("The client secret is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				throw new BadParameterException("The clientId is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
			{
				new KeyValuePair<string, string>("grant_type", "refresh_token"),
				new KeyValuePair<string, string>("refresh_token", refreshToken),
				new KeyValuePair<string, string>("client_id", text),
				new KeyValuePair<string, string>("client_secret", clientSecret)
			};
			return ((ApiBase)this).TwitchPostGenericAsync<RefreshResponse>("/token", (ApiVersion)1, (string)null, list, (string)null, text, (string)null);
		}

		public string GetAuthorizationCodeUrl(string redirectUri, IEnumerable<AuthScopes> scopes, bool forceVerify = false, string state = null, string clientId = null)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			string text = clientId ?? base.Settings.ClientId;
			string text2 = null;
			foreach (AuthScopes scope in scopes)
			{
				text2 = ((text2 != null) ? (text2 + "+" + Helpers.AuthScopesToString(scope)) : Helpers.AuthScopesToString(scope));
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				throw new BadParameterException("The clientId is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			return "https://id.twitch.tv/oauth2/authorize?client_id=" + text + "&redirect_uri=" + HttpUtility.UrlEncode(redirectUri) + "&response_type=code&scope=" + text2 + "&state=" + state + "&" + $"force_verify={forceVerify}";
		}

		public Task<AuthCodeResponse> GetAccessTokenFromCodeAsync(string code, string clientSecret, string redirectUri, string clientId = null)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			string text = clientId ?? base.Settings.ClientId;
			if (string.IsNullOrWhiteSpace(code))
			{
				throw new BadParameterException("The code is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			if (string.IsNullOrWhiteSpace(clientSecret))
			{
				throw new BadParameterException("The client secret is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			if (string.IsNullOrWhiteSpace(redirectUri))
			{
				throw new BadParameterException("The redirectUri is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				throw new BadParameterException("The clientId is not valid. It is not allowed to be null, empty or filled with whitespaces.");
			}
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
			{
				new KeyValuePair<string, string>("grant_type", "authorization_code"),
				new KeyValuePair<string, string>("code", code),
				new KeyValuePair<string, string>("client_id", text),
				new KeyValuePair<string, string>("client_secret", clientSecret),
				new KeyValuePair<string, string>("redirect_uri", redirectUri)
			};
			return ((ApiBase)this).TwitchPostGenericAsync<AuthCodeResponse>("/token", (ApiVersion)1, (string)null, list, (string)null, text, (string)null);
		}

		public async Task<ValidateAccessTokenResponse> ValidateAccessTokenAsync(string accessToken = null)
		{
			try
			{
				return await ((ApiBase)this).TwitchGetGenericAsync<ValidateAccessTokenResponse>("/validate", (ApiVersion)1, (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
			}
			catch (BadScopeException)
			{
				return null;
			}
		}
	}
	public class AuthCodeResponse
	{
		[JsonProperty(PropertyName = "access_token")]
		public string AccessToken { get; protected set; }

		[JsonProperty(PropertyName = "refresh_token")]
		public string RefreshToken { get; protected set; }

		[JsonProperty(PropertyName = "expires_in")]
		public int ExpiresIn { get; protected set; }

		[JsonProperty(PropertyName = "scope")]
		public string[] Scopes { get; protected set; }

		[JsonProperty(PropertyName = "token_type")]
		public string TokenType { get; set; }
	}
	public class RefreshResponse
	{
		[JsonProperty(PropertyName = "access_token")]
		public string AccessToken { get; protected set; }

		[JsonProperty(PropertyName = "refresh_token")]
		public string RefreshToken { get; protected set; }

		[JsonProperty(PropertyName = "expires_in")]
		public int ExpiresIn { get; protected set; }

		[JsonProperty(PropertyName = "scope")]
		public string[] Scopes { get; protected set; }
	}
	public class ValidateAccessTokenResponse
	{
		[JsonProperty(PropertyName = "client_id")]
		public string ClientId { get; protected set; }

		[JsonProperty(PropertyName = "login")]
		public string Login { get; protected set; }

		[JsonProperty(PropertyName = "scopes")]
		public List<string> Scopes { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "expires_in")]
		public int ExpiresIn { get; protected set; }
	}
}

plugins/TwitchLib/TwitchLib.Api.Helix.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TwitchLib.Api.Core;
using TwitchLib.Api.Core.Enums;
using TwitchLib.Api.Core.Exceptions;
using TwitchLib.Api.Core.Extensions.System;
using TwitchLib.Api.Core.HttpCallHandlers;
using TwitchLib.Api.Core.Interfaces;
using TwitchLib.Api.Core.RateLimiter;
using TwitchLib.Api.Helix.Models.Ads;
using TwitchLib.Api.Helix.Models.Analytics;
using TwitchLib.Api.Helix.Models.Bits;
using TwitchLib.Api.Helix.Models.Bits.ExtensionBitsProducts;
using TwitchLib.Api.Helix.Models.ChannelPoints.CreateCustomReward;
using TwitchLib.Api.Helix.Models.ChannelPoints.GetCustomReward;
using TwitchLib.Api.Helix.Models.ChannelPoints.GetCustomRewardRedemption;
using TwitchLib.Api.Helix.Models.ChannelPoints.UpdateCustomReward;
using TwitchLib.Api.Helix.Models.ChannelPoints.UpdateCustomRewardRedemptionStatus;
using TwitchLib.Api.Helix.Models.ChannelPoints.UpdateRedemptionStatus;
using TwitchLib.Api.Helix.Models.Channels.GetChannelEditors;
using TwitchLib.Api.Helix.Models.Channels.GetChannelInformation;
using TwitchLib.Api.Helix.Models.Channels.GetChannelVIPs;
using TwitchLib.Api.Helix.Models.Channels.ModifyChannelInformation;
using TwitchLib.Api.Helix.Models.Charity.GetCharityCampaign;
using TwitchLib.Api.Helix.Models.Chat;
using TwitchLib.Api.Helix.Models.Chat.Badges.GetChannelChatBadges;
using TwitchLib.Api.Helix.Models.Chat.Badges.GetGlobalChatBadges;
using TwitchLib.Api.Helix.Models.Chat.ChatSettings;
using TwitchLib.Api.Helix.Models.Chat.Emotes.GetChannelEmotes;
using TwitchLib.Api.Helix.Models.Chat.Emotes.GetEmoteSets;
using TwitchLib.Api.Helix.Models.Chat.Emotes.GetGlobalEmotes;
using TwitchLib.Api.Helix.Models.Chat.GetChatters;
using TwitchLib.Api.Helix.Models.Chat.GetUserChatColor;
using TwitchLib.Api.Helix.Models.Clips.CreateClip;
using TwitchLib.Api.Helix.Models.Clips.GetClips;
using TwitchLib.Api.Helix.Models.Entitlements.GetCodeStatus;
using TwitchLib.Api.Helix.Models.Entitlements.GetDropsEntitlements;
using TwitchLib.Api.Helix.Models.Entitlements.RedeemCode;
using TwitchLib.Api.Helix.Models.Entitlements.UpdateDropsEntitlements;
using TwitchLib.Api.Helix.Models.EventSub;
using TwitchLib.Api.Helix.Models.Extensions.LiveChannels;
using TwitchLib.Api.Helix.Models.Extensions.ReleasedExtensions;
using TwitchLib.Api.Helix.Models.Extensions.Transactions;
using TwitchLib.Api.Helix.Models.Games;
using TwitchLib.Api.Helix.Models.Goals;
using TwitchLib.Api.Helix.Models.HypeTrain;
using TwitchLib.Api.Helix.Models.Moderation.AutomodSettings;
using TwitchLib.Api.Helix.Models.Moderation.BanUser;
using TwitchLib.Api.Helix.Models.Moderation.BlockedTerms;
using TwitchLib.Api.Helix.Models.Moderation.CheckAutoModStatus;
using TwitchLib.Api.Helix.Models.Moderation.CheckAutoModStatus.Request;
using TwitchLib.Api.Helix.Models.Moderation.GetBannedEvents;
using TwitchLib.Api.Helix.Models.Moderation.GetBannedUsers;
using TwitchLib.Api.Helix.Models.Moderation.GetModeratorEvents;
using TwitchLib.Api.Helix.Models.Moderation.GetModerators;
using TwitchLib.Api.Helix.Models.Polls.CreatePoll;
using TwitchLib.Api.Helix.Models.Polls.EndPoll;
using TwitchLib.Api.Helix.Models.Polls.GetPolls;
using TwitchLib.Api.Helix.Models.Predictions.CreatePrediction;
using TwitchLib.Api.Helix.Models.Predictions.EndPrediction;
using TwitchLib.Api.Helix.Models.Predictions.GetPredictions;
using TwitchLib.Api.Helix.Models.Raids.StartRaid;
using TwitchLib.Api.Helix.Models.Schedule.CreateChannelStreamSegment;
using TwitchLib.Api.Helix.Models.Schedule.GetChannelStreamSchedule;
using TwitchLib.Api.Helix.Models.Schedule.UpdateChannelStreamSegment;
using TwitchLib.Api.Helix.Models.Search;
using TwitchLib.Api.Helix.Models.Soundtrack.GetCurrentTrack;
using TwitchLib.Api.Helix.Models.Soundtrack.GetPlaylist;
using TwitchLib.Api.Helix.Models.Soundtrack.GetPlaylists;
using TwitchLib.Api.Helix.Models.Streams.CreateStreamMarker;
using TwitchLib.Api.Helix.Models.Streams.GetFollowedStreams;
using TwitchLib.Api.Helix.Models.Streams.GetStreamKey;
using TwitchLib.Api.Helix.Models.Streams.GetStreamMarkers;
using TwitchLib.Api.Helix.Models.Streams.GetStreamTags;
using TwitchLib.Api.Helix.Models.Streams.GetStreams;
using TwitchLib.Api.Helix.Models.Subscriptions;
using TwitchLib.Api.Helix.Models.Tags;
using TwitchLib.Api.Helix.Models.Teams;
using TwitchLib.Api.Helix.Models.Users.GetUserActiveExtensions;
using TwitchLib.Api.Helix.Models.Users.GetUserBlockList;
using TwitchLib.Api.Helix.Models.Users.GetUserExtensions;
using TwitchLib.Api.Helix.Models.Users.GetUserFollows;
using TwitchLib.Api.Helix.Models.Users.GetUsers;
using TwitchLib.Api.Helix.Models.Users.Internal;
using TwitchLib.Api.Helix.Models.Users.UpdateUserExtensions;
using TwitchLib.Api.Helix.Models.Videos.DeleteVideos;
using TwitchLib.Api.Helix.Models.Videos.GetVideos;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Project containing the Helix section of TwitchLib.Api")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api.Helix")]
[assembly: AssemblyTitle("TwitchLib.Api.Helix")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api.Helix;

public class Ads : ApiBase
{
	public Ads(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<StartCommercialResponse> StartCommercialAsync(StartCommercialRequest request, string accessToken = null)
	{
		return ((ApiBase)this).TwitchPostGenericAsync<StartCommercialResponse>("/channels/commercial", (ApiVersion)6, JsonConvert.SerializeObject((object)request), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}
}
public class Analytics : ApiBase
{
	public Analytics(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetGameAnalyticsResponse> GetGameAnalyticsAsync(string gameId = null, DateTime? startedAt = null, DateTime? endedAt = null, int first = 20, string after = null, string type = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(gameId))
		{
			list.Add(new KeyValuePair<string, string>("game_id", gameId));
		}
		if (startedAt.HasValue && endedAt.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("started_at", DateTimeExtensions.ToRfc3339String(startedAt.Value)));
			list.Add(new KeyValuePair<string, string>("ended_at", DateTimeExtensions.ToRfc3339String(endedAt.Value)));
		}
		if (!string.IsNullOrWhiteSpace(type))
		{
			list.Add(new KeyValuePair<string, string>("type", type));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetGameAnalyticsResponse>("/analytics/games", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetExtensionAnalyticsResponse> GetExtensionAnalyticsAsync(string extensionId, DateTime? startedAt = null, DateTime? endedAt = null, int first = 20, string after = null, string type = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(extensionId))
		{
			list.Add(new KeyValuePair<string, string>("extension_id", extensionId));
		}
		if (startedAt.HasValue && endedAt.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("started_at", DateTimeExtensions.ToRfc3339String(startedAt.Value)));
			list.Add(new KeyValuePair<string, string>("ended_at", DateTimeExtensions.ToRfc3339String(endedAt.Value)));
		}
		if (!string.IsNullOrWhiteSpace(type))
		{
			list.Add(new KeyValuePair<string, string>("type", type));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetExtensionAnalyticsResponse>("/analytics/extensions", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Bits : ApiBase
{
	public Bits(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetCheermotesResponse> GetCheermotesAsync(string broadcasterId = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (!string.IsNullOrWhiteSpace(broadcasterId))
		{
			list.Add(new KeyValuePair<string, string>("broadcaster_id", broadcasterId));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetCheermotesResponse>("/bits/cheermotes", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetBitsLeaderboardResponse> GetBitsLeaderboardAsync(int count = 10, BitsLeaderboardPeriodEnum period = 4, DateTime? startedAt = null, string userid = null, string accessToken = null)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected I4, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("count", count.ToString())
		};
		switch ((int)period)
		{
		case 0:
			list.Add(new KeyValuePair<string, string>("period", "day"));
			break;
		case 1:
			list.Add(new KeyValuePair<string, string>("period", "week"));
			break;
		case 2:
			list.Add(new KeyValuePair<string, string>("period", "month"));
			break;
		case 3:
			list.Add(new KeyValuePair<string, string>("period", "year"));
			break;
		case 4:
			list.Add(new KeyValuePair<string, string>("period", "all"));
			break;
		default:
			throw new ArgumentOutOfRangeException("period", period, null);
		}
		if (startedAt.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("started_at", DateTimeExtensions.ToRfc3339String(startedAt.Value)));
		}
		if (!string.IsNullOrWhiteSpace(userid))
		{
			list.Add(new KeyValuePair<string, string>("user_id", userid));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetBitsLeaderboardResponse>("/bits/leaderboard", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetExtensionBitsProductsResponse> GetExtensionBitsProductsAsync(bool shouldIncludeAll = false, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("should_include_all", shouldIncludeAll.ToString().ToLower())
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetExtensionBitsProductsResponse>("/bits/extensions", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateExtensionBitsProductResponse> UpdateExtensionBitsProductAsync(ExtensionBitsProduct extensionBitsProduct, string accessToken = null)
	{
		return ((ApiBase)this).TwitchPutGenericAsync<UpdateExtensionBitsProductResponse>("/bits/extensions", (ApiVersion)6, ((object)extensionBitsProduct).ToString(), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}
}
public class ChannelPoints : ApiBase
{
	public ChannelPoints(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<CreateCustomRewardsResponse> CreateCustomRewardsAsync(string broadcasterId, CreateCustomRewardsRequest request, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchPostGenericAsync<CreateCustomRewardsResponse>("/channel_points/custom_rewards", (ApiVersion)6, JsonConvert.SerializeObject((object)request), list, accessToken, (string)null, (string)null);
	}

	public Task DeleteCustomRewardAsync(string broadcasterId, string rewardId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("id", rewardId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/channel_points/custom_rewards", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetCustomRewardsResponse> GetCustomRewardAsync(string broadcasterId, List<string> rewardIds = null, bool onlyManageableRewards = false, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("only_manageable_rewards", onlyManageableRewards.ToString().ToLower())
		};
		if (rewardIds != null && rewardIds.Count > 0)
		{
			list.AddRange(rewardIds.Select((string rewardId) => new KeyValuePair<string, string>("id", rewardId)));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetCustomRewardsResponse>("/channel_points/custom_rewards", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateCustomRewardResponse> UpdateCustomRewardAsync(string broadcasterId, string rewardId, UpdateCustomRewardRequest request, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("id", rewardId)
		};
		return ((ApiBase)this).TwitchPatchGenericAsync<UpdateCustomRewardResponse>("/channel_points/custom_rewards", (ApiVersion)6, JsonConvert.SerializeObject((object)request), list, accessToken, (string)null, (string)null);
	}

	public Task<GetCustomRewardRedemptionResponse> GetCustomRewardRedemptionAsync(string broadcasterId, string rewardId, List<string> redemptionIds = null, string status = null, string sort = null, string after = null, string first = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("reward_id", rewardId)
		};
		if (redemptionIds != null && redemptionIds.Count > 0)
		{
			list.AddRange(redemptionIds.Select((string redemptionId) => new KeyValuePair<string, string>("id", redemptionId)));
		}
		if (!string.IsNullOrWhiteSpace(status))
		{
			list.Add(new KeyValuePair<string, string>("status", status));
		}
		if (!string.IsNullOrWhiteSpace(sort))
		{
			list.Add(new KeyValuePair<string, string>("sort", sort));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		if (!string.IsNullOrWhiteSpace(first))
		{
			list.Add(new KeyValuePair<string, string>("first", first));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetCustomRewardRedemptionResponse>("/channel_points/custom_rewards/redemptions", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateRedemptionStatusResponse> UpdateRedemptionStatusAsync(string broadcasterId, string rewardId, List<string> redemptionIds, UpdateCustomRewardRedemptionStatusRequest request, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("reward_id", rewardId)
		};
		list.AddRange(redemptionIds.Select((string redemptionId) => new KeyValuePair<string, string>("id", redemptionId)));
		return ((ApiBase)this).TwitchPatchGenericAsync<UpdateRedemptionStatusResponse>("/channel_points/custom_rewards/redemptions", (ApiVersion)6, JsonConvert.SerializeObject((object)request), list, accessToken, (string)null, (string)null);
	}
}
public class Channels : ApiBase
{
	public Channels(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetChannelInformationResponse> GetChannelInformationAsync(string broadcasterId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelInformationResponse>("/channels", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task ModifyChannelInformationAsync(string broadcasterId, ModifyChannelInformationRequest request, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchPatchAsync("/channels", (ApiVersion)6, JsonConvert.SerializeObject((object)request), list, accessToken, (string)null, (string)null);
	}

	public Task<GetChannelEditorsResponse> GetChannelEditorsAsync(string broadcasterId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelEditorsResponse>("/channels/editors", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetChannelVIPsResponse> GetVIPsAsync(string broadcasterId, List<string> userIds = null, int first = 20, string after = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (first > 100 && first <= 0)
		{
			throw new BadParameterException("first must be greater than 0 and less then 101");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (userIds != null)
		{
			if (userIds.Count == 0)
			{
				throw new BadParameterException("userIds must contain at least 1 userId if a list is included in the call");
			}
			list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("userId", userId)));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelVIPsResponse>("/channels/vips", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task AddChannelVIPAsync(string broadcasterId, string userId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrEmpty(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("user_id", userId)
		};
		return ((ApiBase)this).TwitchPostAsync("/channels/vips", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}

	public Task RemoveChannelVIPAsync(string broadcasterId, string userId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrEmpty(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("user_id", userId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/channels/vips", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Charity : ApiBase
{
	public Charity(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetCharityCampaignResponse> GetCharityCampaignAsync(string broadcasterId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetCharityCampaignResponse>("/charity/campaigns", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Chat : ApiBase
{
	public Chat(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetChannelChatBadgesResponse> GetChannelChatBadgesAsync(string broadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelChatBadgesResponse>("/chat/badges", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetGlobalChatBadgesResponse> GetGlobalChatBadgesAsync(string accessToken = null)
	{
		return ((ApiBase)this).TwitchGetGenericAsync<GetGlobalChatBadgesResponse>("/chat/badges/global", (ApiVersion)6, (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<GetChattersResponse> GetChattersAsync(string broadcasterId, string moderatorId, int first = 100, string after = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null/empty/whitespace");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId cannot be null/empty/whitespace");
		}
		if (first < 1 || first > 1000)
		{
			throw new BadParameterException("first cannot be less than 1 or greater than 1000");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetChattersResponse>("/chat/chatters", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetChannelEmotesResponse> GetChannelEmotesAsync(string broadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelEmotesResponse>("/chat/emotes", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetEmoteSetsResponse> GetEmoteSetsAsync(List<string> emoteSetIds, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		list.AddRange(emoteSetIds.Select((string emoteSetId) => new KeyValuePair<string, string>("emote_set_id", emoteSetId)));
		return ((ApiBase)this).TwitchGetGenericAsync<GetEmoteSetsResponse>("/chat/emotes/set", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetGlobalEmotesResponse> GetGlobalEmotesAsync(string accessToken = null)
	{
		return ((ApiBase)this).TwitchGetGenericAsync<GetGlobalEmotesResponse>("/chat/emotes/global", (ApiVersion)6, (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<GetChatSettingsResponse> GetChatSettingsAsync(string broadcasterId, string moderatorId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrEmpty(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetChatSettingsResponse>("/chat/settings", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateChatSettingsResponse> UpdateChatSettingsAsync(string broadcasterId, string moderatorId, ChatSettings settings, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrEmpty(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (settings == null)
		{
			throw new BadParameterException("settings must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		return ((ApiBase)this).TwitchPatchGenericAsync<UpdateChatSettingsResponse>("/chat/settings", (ApiVersion)6, JsonConvert.SerializeObject((object)settings), list, accessToken, (string)null, (string)null);
	}

	public Task SendChatAnnouncementAsync(string broadcasterId, string moderatorId, string message, AnnouncementColors color = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Expected O, but got Unknown
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrEmpty(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (message == null)
		{
			throw new BadParameterException("message must be set");
		}
		if (message.Length > 500)
		{
			throw new BadParameterException("message length must be less than or equal to 500 characters");
		}
		if (color == null)
		{
			color = AnnouncementColors.Primary;
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		JObject val = new JObject
		{
			["message"] = JToken.op_Implicit(message),
			["color"] = JToken.op_Implicit(color.Value)
		};
		return ((ApiBase)this).TwitchPostAsync("/chat/announcements", (ApiVersion)6, ((object)val).ToString(), list, accessToken, (string)null, (string)null);
	}

	public Task UpdateUserChatColorAsync(string userId, UserColors color, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		if (string.IsNullOrEmpty(color.Value))
		{
			throw new BadParameterException("color must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("user_id", userId),
			new KeyValuePair<string, string>("color", color.Value)
		};
		return ((ApiBase)this).TwitchPostAsync("/chat/color", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}

	public Task UpdateUserChatColorAsync(string userId, string colorHex, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		if (string.IsNullOrEmpty(colorHex))
		{
			throw new BadParameterException("colorHex must be set");
		}
		if (colorHex.Length != 6)
		{
			throw new BadParameterException("colorHex length must be equal to 6 characters \"######\"");
		}
		string value = HttpUtility.UrlEncode("#" + colorHex);
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("user_id", userId),
			new KeyValuePair<string, string>("color", value)
		};
		return ((ApiBase)this).TwitchPostAsync("/chat/color", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}

	public Task<GetUserChatColorResponse> GetUserChatColorAsync(List<string> userIds, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		if (userIds.Count == 0)
		{
			throw new BadParameterException("userIds must contain at least 1 userId");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		foreach (string userId in userIds)
		{
			if (string.IsNullOrEmpty(userId))
			{
				throw new BadParameterException("userId must be set");
			}
			list.Add(new KeyValuePair<string, string>("user_id", userId));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetUserChatColorResponse>("/chat/color", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Clips : ApiBase
{
	public Clips(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetClipsResponse> GetClipsAsync(List<string> clipIds = null, string gameId = null, string broadcasterId = null, string before = null, string after = null, DateTime? startedAt = null, DateTime? endedAt = null, int first = 20, string accessToken = null)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		if (first < 0 || first > 100)
		{
			throw new BadParameterException("'first' must between 0 (inclusive) and 100 (inclusive).");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (clipIds != null)
		{
			list.AddRange(clipIds.Select((string clipId) => new KeyValuePair<string, string>("id", clipId)));
		}
		if (!string.IsNullOrWhiteSpace(gameId))
		{
			list.Add(new KeyValuePair<string, string>("game_id", gameId));
		}
		if (!string.IsNullOrWhiteSpace(broadcasterId))
		{
			list.Add(new KeyValuePair<string, string>("broadcaster_id", broadcasterId));
		}
		if (list.Count == 0 || (list.Count > 1 && gameId != null && broadcasterId != null))
		{
			throw new BadParameterException("One of the following parameters must be set: clipId, gameId, broadcasterId. Only one is allowed to be set.");
		}
		if (!startedAt.HasValue && endedAt.HasValue)
		{
			throw new BadParameterException("The ended_at parameter cannot be used without the started_at parameter. Please include both parameters!");
		}
		if (startedAt.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("started_at", DateTimeExtensions.ToRfc3339String(startedAt.Value)));
		}
		if (endedAt.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("ended_at", DateTimeExtensions.ToRfc3339String(endedAt.Value)));
		}
		if (!string.IsNullOrWhiteSpace(before))
		{
			list.Add(new KeyValuePair<string, string>("before", before));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		list.Add(new KeyValuePair<string, string>("first", first.ToString()));
		return ((ApiBase)this).TwitchGetGenericAsync<GetClipsResponse>("/clips", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<CreatedClipResponse> CreateClipAsync(string broadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchPostGenericAsync<CreatedClipResponse>("/clips", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}
}
public class Entitlements : ApiBase
{
	public Entitlements(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetCodeStatusResponse> GetCodeStatusAsync(List<string> codes, string userId, string accessToken = null)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (codes == null || codes.Count == 0 || codes.Count > 20)
		{
			throw new BadParameterException("codes cannot be null and must have between 1 and 20 items");
		}
		if (userId == null)
		{
			throw new BadParameterException("userId cannot be null");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("user_id", userId)
		};
		list.AddRange(codes.Select((string code) => new KeyValuePair<string, string>("code", code)));
		return ((ApiBase)this).TwitchPostGenericAsync<GetCodeStatusResponse>("/entitlements/codes", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}

	public Task<GetDropsEntitlementsResponse> GetDropsEntitlementsAsync(string id = null, string userId = null, string gameId = null, string after = null, int first = 20, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(id))
		{
			list.Add(new KeyValuePair<string, string>("id", id));
		}
		if (!string.IsNullOrWhiteSpace(userId))
		{
			list.Add(new KeyValuePair<string, string>("user_id", userId));
		}
		if (!string.IsNullOrWhiteSpace(gameId))
		{
			list.Add(new KeyValuePair<string, string>("game_id", gameId));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetDropsEntitlementsResponse>("/entitlements/drops", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateDropsEntitlementsResponse> UpdateDropsEntitlementsAsync(string[] entitlementIds, FulfillmentStatus fulfillmentStatus, string accessToken)
	{
		var anon = new
		{
			entitlement_ids = entitlementIds,
			fulfillment_status = ((object)(FulfillmentStatus)(ref fulfillmentStatus)).ToString()
		};
		return ((ApiBase)this).TwitchPatchGenericAsync<UpdateDropsEntitlementsResponse>("/entitlements/drops", (ApiVersion)6, JsonConvert.SerializeObject((object)anon), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<RedeemCodeResponse> RedeemCodeAsync(List<string> codes, string accessToken = null)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if (codes == null || codes.Count == 0 || codes.Count > 20)
		{
			throw new BadParameterException("codes cannot be null and must have between 1 and 20 items");
		}
		List<KeyValuePair<string, string>> list = codes.Select((string code) => new KeyValuePair<string, string>("code", code)).ToList();
		return ((ApiBase)this).TwitchPostGenericAsync<RedeemCodeResponse>("/entitlements/codes", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}
}
public class EventSub : ApiBase
{
	public EventSub(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<CreateEventSubSubscriptionResponse> CreateEventSubSubscriptionAsync(string type, string version, Dictionary<string, string> condition, EventSubTransportMethod method, string websocketSessionId = null, string webhookCallback = null, string webhookSecret = null, string clientId = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Invalid comparison between Unknown and I4
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(type))
		{
			throw new BadParameterException("type must be set");
		}
		if (string.IsNullOrEmpty(version))
		{
			throw new BadParameterException("version must be set");
		}
		if (condition == null || condition.Count == 0)
		{
			throw new BadParameterException("condition must be set");
		}
		if ((int)method != 0)
		{
			if ((int)method == 1)
			{
				if (string.IsNullOrWhiteSpace(websocketSessionId))
				{
					throw new BadParameterException("websocketSessionId must be set");
				}
				var anon = new
				{
					type = type,
					version = version,
					condition = condition,
					transport = new
					{
						method = ((object)(EventSubTransportMethod)(ref method)).ToString().ToLowerInvariant(),
						session_id = websocketSessionId
					}
				};
				return ((ApiBase)this).TwitchPostGenericAsync<CreateEventSubSubscriptionResponse>("/eventsub/subscriptions", (ApiVersion)6, JsonConvert.SerializeObject((object)anon), (List<KeyValuePair<string, string>>)null, accessToken, clientId, (string)null);
			}
			throw new ArgumentOutOfRangeException("method", method, null);
		}
		if (string.IsNullOrWhiteSpace(webhookCallback))
		{
			throw new BadParameterException("webhookCallback must be set");
		}
		if (webhookSecret == null || webhookSecret.Length < 10 || webhookSecret.Length > 100)
		{
			throw new BadParameterException("webhookSecret must be set, and be between 10 (inclusive) and 100 (inclusive)");
		}
		var anon2 = new
		{
			type = type,
			version = version,
			condition = condition,
			transport = new
			{
				method = ((object)(EventSubTransportMethod)(ref method)).ToString().ToLowerInvariant(),
				callback = webhookCallback,
				secret = webhookSecret
			}
		};
		return ((ApiBase)this).TwitchPostGenericAsync<CreateEventSubSubscriptionResponse>("/eventsub/subscriptions", (ApiVersion)6, JsonConvert.SerializeObject((object)anon2), (List<KeyValuePair<string, string>>)null, accessToken, clientId, (string)null);
	}

	public Task<GetEventSubSubscriptionsResponse> GetEventSubSubscriptionsAsync(string status = null, string type = null, string userId = null, string after = null, string clientId = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (!string.IsNullOrWhiteSpace(status))
		{
			list.Add(new KeyValuePair<string, string>("status", status));
		}
		if (!string.IsNullOrWhiteSpace(type))
		{
			list.Add(new KeyValuePair<string, string>("type", type));
		}
		if (!string.IsNullOrWhiteSpace(userId))
		{
			list.Add(new KeyValuePair<string, string>("user_id", userId));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetEventSubSubscriptionsResponse>("/eventsub/subscriptions", (ApiVersion)6, list, accessToken, clientId, (string)null);
	}

	public async Task<bool> DeleteEventSubSubscriptionAsync(string id, string clientId = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("id", id)
		};
		return (await ((ApiBase)this).TwitchDeleteAsync("/eventsub/subscriptions", (ApiVersion)6, list, accessToken, clientId, (string)null)).Key == 204;
	}
}
public class Extensions : ApiBase
{
	public Extensions(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetExtensionTransactionsResponse> GetExtensionTransactionsAsync(string extensionId, List<string> ids = null, string after = null, int first = 20, string applicationAccessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(extensionId))
		{
			throw new BadParameterException("extensionId cannot be null");
		}
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("'first' must between 1 (inclusive) and 100 (inclusive).");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("extension_id", extensionId)
		};
		if (ids != null)
		{
			list.AddRange(ids.Select((string id) => new KeyValuePair<string, string>("id", id)));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		list.Add(new KeyValuePair<string, string>("first", first.ToString()));
		return ((ApiBase)this).TwitchGetGenericAsync<GetExtensionTransactionsResponse>("/extensions/transactions", (ApiVersion)6, list, applicationAccessToken, (string)null, (string)null);
	}

	public Task<GetExtensionLiveChannelsResponse> GetExtensionLiveChannelsAsync(string extensionId, int first = 20, string after = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(extensionId))
		{
			throw new BadParameterException("extensionId must be set");
		}
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("'first' must between 1 (inclusive) and 100 (inclusive).");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("extension_id", extensionId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetExtensionLiveChannelsResponse>("/extensions/live", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetReleasedExtensionsResponse> GetReleasedExtensionsAsync(string extensionId, string extensionVersion = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(extensionId))
		{
			throw new BadParameterException("extensionId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("extension_id", extensionId)
		};
		if (!string.IsNullOrWhiteSpace(extensionVersion))
		{
			list.Add(new KeyValuePair<string, string>("extension_version", extensionVersion));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetReleasedExtensionsResponse>("/extensions/released", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Games : ApiBase
{
	public Games(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetGamesResponse> GetGamesAsync(List<string> gameIds = null, List<string> gameNames = null, string accessToken = null)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		if ((gameIds == null && gameNames == null) || (gameIds != null && gameIds.Count == 0 && gameNames == null) || (gameNames != null && gameNames.Count == 0 && gameIds == null))
		{
			throw new BadParameterException("Either gameIds or gameNames must have at least one value");
		}
		if (gameIds != null && gameIds.Count > 100)
		{
			throw new BadParameterException("gameIds list cannot exceed 100 items");
		}
		if (gameNames != null && gameNames.Count > 100)
		{
			throw new BadParameterException("gameNames list cannot exceed 100 items");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (gameIds != null && gameIds.Count > 0)
		{
			list.AddRange(gameIds.Select((string gameId) => new KeyValuePair<string, string>("id", gameId)));
		}
		if (gameNames != null && gameNames.Count > 0)
		{
			list.AddRange(gameNames.Select((string gameName) => new KeyValuePair<string, string>("name", gameName)));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetGamesResponse>("/games", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetTopGamesResponse> GetTopGamesAsync(string before = null, string after = null, int first = 20, string accessToken = null)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (first < 0 || first > 100)
		{
			throw new BadParameterException("'first' parameter must be between 1 (inclusive) and 100 (inclusive).");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(before))
		{
			list.Add(new KeyValuePair<string, string>("before", before));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetTopGamesResponse>("/games/top", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Goals : ApiBase
{
	public Goals(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetCreatorGoalsResponse> GetCreatorGoalsAsync(string broadcasterId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null or empty");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetCreatorGoalsResponse>("/goals", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Helix
{
	private readonly ILogger<Helix> _logger;

	public IApiSettings Settings { get; }

	public Analytics Analytics { get; }

	public Ads Ads { get; }

	public Bits Bits { get; }

	public Chat Chat { get; }

	public Channels Channels { get; }

	public ChannelPoints ChannelPoints { get; }

	public Charity Charity { get; }

	public Clips Clips { get; }

	public Entitlements Entitlements { get; }

	public EventSub EventSub { get; }

	public Extensions Extensions { get; }

	public Games Games { get; }

	public Goals Goals { get; }

	public HypeTrain HypeTrain { get; }

	public Moderation Moderation { get; }

	public Polls Polls { get; }

	public Predictions Predictions { get; }

	public Raids Raids { get; }

	public Schedule Schedule { get; }

	public Search Search { get; }

	public Soundtrack Soundtrack { get; }

	public Streams Streams { get; }

	public Subscriptions Subscriptions { get; }

	public Tags Tags { get; }

	public Teams Teams { get; }

	public Videos Videos { get; }

	public Users Users { get; }

	public Helix(ILoggerFactory loggerFactory = null, IRateLimiter rateLimiter = null, IApiSettings settings = null, IHttpCallHandler http = null)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		_logger = loggerFactory?.CreateLogger<Helix>();
		rateLimiter = (IRateLimiter)(((object)rateLimiter) ?? ((object)BypassLimiter.CreateLimiterBypassInstance()));
		http = (IHttpCallHandler)(((object)http) ?? ((object)new TwitchHttpClient(loggerFactory?.CreateLogger<TwitchHttpClient>())));
		Settings = (IApiSettings)(((object)settings) ?? ((object)new ApiSettings()));
		Analytics = new Analytics(Settings, rateLimiter, http);
		Ads = new Ads(Settings, rateLimiter, http);
		Bits = new Bits(Settings, rateLimiter, http);
		Chat = new Chat(Settings, rateLimiter, http);
		Channels = new Channels(Settings, rateLimiter, http);
		ChannelPoints = new ChannelPoints(Settings, rateLimiter, http);
		Charity = new Charity(Settings, rateLimiter, http);
		Clips = new Clips(Settings, rateLimiter, http);
		Entitlements = new Entitlements(Settings, rateLimiter, http);
		EventSub = new EventSub(Settings, rateLimiter, http);
		Extensions = new Extensions(Settings, rateLimiter, http);
		Games = new Games(Settings, rateLimiter, http);
		Goals = new Goals(settings, rateLimiter, http);
		HypeTrain = new HypeTrain(Settings, rateLimiter, http);
		Moderation = new Moderation(Settings, rateLimiter, http);
		Polls = new Polls(Settings, rateLimiter, http);
		Predictions = new Predictions(Settings, rateLimiter, http);
		Raids = new Raids(settings, rateLimiter, http);
		Schedule = new Schedule(Settings, rateLimiter, http);
		Search = new Search(Settings, rateLimiter, http);
		Soundtrack = new Soundtrack(Settings, rateLimiter, http);
		Streams = new Streams(Settings, rateLimiter, http);
		Subscriptions = new Subscriptions(Settings, rateLimiter, http);
		Tags = new Tags(Settings, rateLimiter, http);
		Teams = new Teams(Settings, rateLimiter, http);
		Users = new Users(Settings, rateLimiter, http);
		Videos = new Videos(Settings, rateLimiter, http);
	}
}
public class HypeTrain : ApiBase
{
	public HypeTrain(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetHypeTrainResponse> GetHypeTrainEventsAsync(string broadcasterId, int first = 1, string cursor = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("BroadcasterId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(cursor))
		{
			list.Add(new KeyValuePair<string, string>("cursor", cursor));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetHypeTrainResponse>("/hypetrain/events", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Moderation : ApiBase
{
	public Moderation(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task ManageHeldAutoModMessagesAsync(string userId, string msgId, ManageHeldAutoModMessageActionEnum action, string accessToken = null)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected O, but got Unknown
		if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(msgId))
		{
			throw new BadParameterException("userId and msgId cannot be null and must be greater than 0 length");
		}
		JObject val = new JObject
		{
			["user_id"] = JToken.op_Implicit(userId),
			["msg_id"] = JToken.op_Implicit(msgId),
			["action"] = JToken.op_Implicit(((object)(ManageHeldAutoModMessageActionEnum)(ref action)).ToString().ToUpper())
		};
		return ((ApiBase)this).TwitchPostAsync("/moderation/automod/message", (ApiVersion)6, ((object)val).ToString(), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<CheckAutoModStatusResponse> CheckAutoModStatusAsync(List<Message> messages, string broadcasterId, string accessToken = null)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (messages == null || messages.Count == 0)
		{
			throw new BadParameterException("messages cannot be null and must be greater than 0 length");
		}
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null/empty/whitespace");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		MessageRequest val = new MessageRequest
		{
			Messages = messages.ToArray()
		};
		return ((ApiBase)this).TwitchPostGenericAsync<CheckAutoModStatusResponse>("/moderation/enforcements/status", (ApiVersion)6, JsonConvert.SerializeObject((object)val), list, accessToken, (string)null, (string)null);
	}

	public Task<GetBannedEventsResponse> GetBannedEventsAsync(string broadcasterId, List<string> userIds = null, string after = null, int first = 20, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null/empty/whitespace");
		}
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("first cannot be less than 1 or greater than 100");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		if (userIds != null && userIds.Count > 0)
		{
			list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("user_id", userId)));
		}
		if (string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		list.Add(new KeyValuePair<string, string>("first", first.ToString()));
		return ((ApiBase)this).TwitchGetGenericAsync<GetBannedEventsResponse>("/moderation/banned/events", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetBannedUsersResponse> GetBannedUsersAsync(string broadcasterId, List<string> userIds = null, int first = 20, string after = null, string before = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null/empty/whitespace");
		}
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("first cannot be less than 1 or greater than 100");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (userIds != null && userIds.Count > 0)
		{
			list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("user_id", userId)));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		if (!string.IsNullOrWhiteSpace(before))
		{
			list.Add(new KeyValuePair<string, string>("before", before));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetBannedUsersResponse>("/moderation/banned", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetModeratorsResponse> GetModeratorsAsync(string broadcasterId, List<string> userIds = null, int first = 20, string after = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null/empty/whitespace");
		}
		if (first > 100 || first < 1)
		{
			throw new BadParameterException("first must be greater than 0 and less than 101");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (userIds != null && userIds.Count > 0)
		{
			list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("user_id", userId)));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetModeratorsResponse>("/moderation/moderators", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetModeratorEventsResponse> GetModeratorEventsAsync(string broadcasterId, List<string> userIds = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId cannot be null/empty/whitespace");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		if (userIds != null && userIds.Count > 0)
		{
			list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("user_id", userId)));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetModeratorEventsResponse>("/moderation/moderators/events", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<BanUserResponse> BanUserAsync(string broadcasterId, string moderatorId, BanUserRequest banUserRequest, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrEmpty(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (banUserRequest == null)
		{
			throw new BadParameterException("banUserRequest cannot be null");
		}
		if (string.IsNullOrWhiteSpace(banUserRequest.UserId))
		{
			throw new BadParameterException("banUserRequest.UserId must be set");
		}
		if (banUserRequest.Reason == null)
		{
			throw new BadParameterException("banUserRequest.Reason cannot be null and must be set to at least an empty string");
		}
		if (banUserRequest.Duration.HasValue && (banUserRequest.Duration.Value <= 0 || banUserRequest.Duration.Value > 1209600))
		{
			throw new BadParameterException("banUserRequest.Duration has to be between including 1 and including 1209600");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		var anon = new
		{
			data = banUserRequest
		};
		return ((ApiBase)this).TwitchPostGenericAsync<BanUserResponse>("/moderation/bans", (ApiVersion)6, JsonConvert.SerializeObject((object)anon), list, accessToken, (string)null, (string)null);
	}

	public Task UnbanUserAsync(string broadcasterId, string moderatorId, string userId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (string.IsNullOrWhiteSpace(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId),
			new KeyValuePair<string, string>("user_id", userId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/moderation/bans", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetAutomodSettingsResponse> GetAutomodSettingsAsync(string broadcasterId, string moderatorId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetAutomodSettingsResponse>("/moderation/automod/settings", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateAutomodSettingsResponse> UpdateAutomodSettingsAsync(string broadcasterId, string moderatorId, AutomodSettings settings, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		return ((ApiBase)this).TwitchPutGenericAsync<UpdateAutomodSettingsResponse>("/moderation/automod/settings", (ApiVersion)6, JsonConvert.SerializeObject((object)settings), list, accessToken, (string)null, (string)null);
	}

	public Task<GetBlockedTermsResponse> GetBlockedTermsAsync(string broadcasterId, string moderatorId, string after = null, int first = 20, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("first must be greater than 0 and less than 101");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetBlockedTermsResponse>("/moderation/blocked_terms", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<AddBlockedTermResponse> AddBlockedTermAsync(string broadcasterId, string moderatorId, string term, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (string.IsNullOrWhiteSpace(term))
		{
			throw new BadParameterException("term must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		JObject val = new JObject { ["text"] = JToken.op_Implicit(term) };
		return ((ApiBase)this).TwitchPostGenericAsync<AddBlockedTermResponse>("/moderation/blocked_terms", (ApiVersion)6, ((object)val).ToString(), list, accessToken, (string)null, (string)null);
	}

	public Task DeleteBlockedTermAsync(string broadcasterId, string moderatorId, string termId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		if (string.IsNullOrWhiteSpace(termId))
		{
			throw new BadParameterException("termId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId),
			new KeyValuePair<string, string>("id", termId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/moderation/blocked_terms", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task DeleteChatMessagesAsync(string broadcasterId, string moderatorId, string messageId = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(moderatorId))
		{
			throw new BadParameterException("moderatorId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("moderator_id", moderatorId)
		};
		if (!string.IsNullOrWhiteSpace(messageId))
		{
			list.Add(new KeyValuePair<string, string>("message_id", messageId));
		}
		return ((ApiBase)this).TwitchDeleteAsync("/moderation/chat", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task AddChannelModeratorAsync(string broadcasterId, string userId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("user_id", userId)
		};
		return ((ApiBase)this).TwitchPostAsync("/moderation/moderators", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}

	public Task DeleteChannelModeratorAsync(string broadcasterId, string userId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("broadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(userId))
		{
			throw new BadParameterException("userId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("user_id", userId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/moderation/moderators", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Polls : ApiBase
{
	public Polls(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetPollsResponse> GetPollsAsync(string broadcasterId, List<string> ids = null, string after = null, int first = 20, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (ids != null && ids.Count > 0)
		{
			list.AddRange(ids.Select((string id) => new KeyValuePair<string, string>("id", id)));
		}
		if (!string.IsNullOrWhiteSpace(accessToken))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetPollsResponse>("/polls", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<CreatePollResponse> CreatePollAsync(CreatePollRequest request, string accessToken = null)
	{
		return ((ApiBase)this).TwitchPostGenericAsync<CreatePollResponse>("/polls", (ApiVersion)6, JsonConvert.SerializeObject((object)request), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<EndPollResponse> EndPollAsync(string broadcasterId, string id, PollStatusEnum status, string accessToken = null)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		JObject val = new JObject
		{
			["broadcaster_id"] = JToken.op_Implicit(broadcasterId),
			["id"] = JToken.op_Implicit(id),
			["status"] = JToken.op_Implicit(((object)(PollStatusEnum)(ref status)).ToString())
		};
		return ((ApiBase)this).TwitchPatchGenericAsync<EndPollResponse>("/polls", (ApiVersion)6, ((object)val).ToString(), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}
}
public class Predictions : ApiBase
{
	public Predictions(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetPredictionsResponse> GetPredictionsAsync(string broadcasterId, List<string> ids = null, string after = null, int first = 20, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (ids != null && ids.Count > 0)
		{
			list.AddRange(ids.Select((string id) => new KeyValuePair<string, string>("id", id)));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetPredictionsResponse>("/predictions", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<CreatePredictionResponse> CreatePredictionAsync(CreatePredictionRequest request, string accessToken = null)
	{
		return ((ApiBase)this).TwitchPostGenericAsync<CreatePredictionResponse>("/predictions", (ApiVersion)6, JsonConvert.SerializeObject((object)request), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<EndPredictionResponse> EndPredictionAsync(string broadcasterId, string id, PredictionEndStatus status, string winningOutcomeId = null, string accessToken = null)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		JObject val = new JObject
		{
			["broadcaster_id"] = JToken.op_Implicit(broadcasterId),
			["id"] = JToken.op_Implicit(id),
			["status"] = JToken.op_Implicit(((object)(PredictionEndStatus)(ref status)).ToString())
		};
		if (!string.IsNullOrWhiteSpace(winningOutcomeId))
		{
			val["winning_outcome_id"] = JToken.op_Implicit(winningOutcomeId);
		}
		return ((ApiBase)this).TwitchPatchGenericAsync<EndPredictionResponse>("/predictions", (ApiVersion)6, ((object)val).ToString(), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}
}
public class Raids : ApiBase
{
	public Raids(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<StartRaidResponse> StartRaidAsync(string fromBroadcasterId, string toBroadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("from_broadcaster_id", fromBroadcasterId),
			new KeyValuePair<string, string>("to_broadcaster_id", toBroadcasterId)
		};
		return ((ApiBase)this).TwitchPostGenericAsync<StartRaidResponse>("/raids", (ApiVersion)6, string.Empty, list, accessToken, (string)null, (string)null);
	}

	public Task CancelRaidAsync(string broadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/raids", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Schedule : ApiBase
{
	public Schedule(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetChannelStreamScheduleResponse> GetChannelStreamScheduleAsync(string broadcasterId, List<string> segmentIds = null, string startTime = null, string utcOffset = null, int first = 20, string after = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (segmentIds != null && segmentIds.Count > 0)
		{
			list.AddRange(segmentIds.Select((string segmentId) => new KeyValuePair<string, string>("id", segmentId)));
		}
		if (!string.IsNullOrWhiteSpace(startTime))
		{
			list.Add(new KeyValuePair<string, string>("start_time", startTime));
		}
		if (!string.IsNullOrWhiteSpace(utcOffset))
		{
			list.Add(new KeyValuePair<string, string>("utc_offset", utcOffset));
		}
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelStreamScheduleResponse>("/schedule", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task UpdateChannelStreamScheduleAsync(string broadcasterId, bool? isVacationEnabled = null, DateTime? vacationStartTime = null, DateTime? vacationEndTime = null, string timezone = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		if (isVacationEnabled.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("is_vacation_enabled", isVacationEnabled.Value.ToString()));
		}
		if (vacationStartTime.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("vacation_start_time", vacationStartTime.Value.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo)));
		}
		if (vacationEndTime.HasValue)
		{
			list.Add(new KeyValuePair<string, string>("vacation_end_time", vacationEndTime.Value.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo)));
		}
		if (!string.IsNullOrWhiteSpace(timezone))
		{
			list.Add(new KeyValuePair<string, string>("timezone", timezone));
		}
		return ((ApiBase)this).TwitchPatchAsync("/schedule/settings", (ApiVersion)6, (string)null, list, accessToken, (string)null, (string)null);
	}

	public Task<CreateChannelStreamSegmentResponse> CreateChannelStreamScheduleSegmentAsync(string broadcasterId, CreateChannelStreamSegmentRequest payload, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchPostGenericAsync<CreateChannelStreamSegmentResponse>("/schedule/segment", (ApiVersion)6, JsonConvert.SerializeObject((object)payload), list, accessToken, (string)null, (string)null);
	}

	public Task<UpdateChannelStreamSegmentResponse> UpdateChannelStreamScheduleSegmentAsync(string broadcasterId, string segmentId, UpdateChannelStreamSegmentRequest payload, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("id", segmentId)
		};
		return ((ApiBase)this).TwitchPatchGenericAsync<UpdateChannelStreamSegmentResponse>("/schedule/segment", (ApiVersion)6, JsonConvert.SerializeObject((object)payload), list, accessToken, (string)null, (string)null);
	}

	public Task DeleteChannelStreamScheduleSegmentAsync(string broadcasterId, string segmentId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("id", segmentId)
		};
		return ((ApiBase)this).TwitchDeleteAsync("/schedule/segment", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task GetChanneliCalendarAsync(string broadcasterId)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetAsync("/schedule/icalendar", (ApiVersion)6, list, (string)null, (string)null, (string)null);
	}
}
public class Search : ApiBase
{
	public Search(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<SearchCategoriesResponse> SearchCategoriesAsync(string encodedSearchQuery, string after = null, int first = 20, string accessToken = null)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (first < 0 || first > 100)
		{
			throw new BadParameterException("'first' parameter must be between 1 (inclusive) and 100 (inclusive).");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("query", encodedSearchQuery)
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		list.Add(new KeyValuePair<string, string>("first", first.ToString()));
		return ((ApiBase)this).TwitchGetGenericAsync<SearchCategoriesResponse>("/search/categories", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<SearchChannelsResponse> SearchChannelsAsync(string encodedSearchQuery, bool liveOnly = false, string after = null, int first = 20, string accessToken = null)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		if (first < 0 || first > 100)
		{
			throw new BadParameterException("'first' parameter must be between 1 (inclusive) and 100 (inclusive).");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("query", encodedSearchQuery),
			new KeyValuePair<string, string>("live_only", liveOnly.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		list.Add(new KeyValuePair<string, string>("first", first.ToString()));
		return ((ApiBase)this).TwitchGetGenericAsync<SearchChannelsResponse>("/search/channels", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Soundtrack : ApiBase
{
	public Soundtrack(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetCurrentTrackResponse> GetCurrentTrackAsync(string broadcasterId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("'broadcasterId' must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetCurrentTrackResponse>("/soundtrack/current_track", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetPlaylistResponse> GetPlaylistAsync(string id, int first = 20, string after = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(id))
		{
			throw new BadParameterException("'id' must be set");
		}
		if (first < 1 || first > 50)
		{
			throw new BadParameterException("'first' must be value of 1 - 50");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("id", id),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetPlaylistResponse>("/soundtrack/playlist", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetPlaylistsResponse> GetPlaylistsAsync(string id = null, int first = 20, string after = null, string accessToken = null)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (first < 1 || first > 50)
		{
			throw new BadParameterException("'first' must be value of 1 - 50");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		if (!string.IsNullOrWhiteSpace(id))
		{
			list.Add(new KeyValuePair<string, string>("id", id));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetPlaylistsResponse>("/soundtrack/playlists", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Streams : ApiBase
{
	public Streams(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetStreamsResponse> GetStreamsAsync(string after = null, int first = 20, List<string> gameIds = null, List<string> languages = null, List<string> userIds = null, List<string> userLogins = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		if (gameIds != null && gameIds.Count > 0)
		{
			list.AddRange(gameIds.Select((string gameId) => new KeyValuePair<string, string>("game_id", gameId)));
		}
		if (languages != null && languages.Count > 0)
		{
			list.AddRange(languages.Select((string language) => new KeyValuePair<string, string>("language", language)));
		}
		if (userIds != null && userIds.Count > 0)
		{
			list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("user_id", userId)));
		}
		if (userLogins != null && userLogins.Count > 0)
		{
			list.AddRange(userLogins.Select((string userLogin) => new KeyValuePair<string, string>("user_login", userLogin)));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetStreamsResponse>("/streams", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetStreamTagsResponse> GetStreamTagsAsync(string broadcasterId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("BroadcasterId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetStreamTagsResponse>("/streams/tags", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task ReplaceStreamTagsAsync(string broadcasterId, List<string> tagIds = null, string accessToken = null)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_0040: Expected O, but got Unknown
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		string text = null;
		if (tagIds != null && tagIds.Count > 0)
		{
			JObject val = new JObject();
			val.Add("tag_ids", (JToken)new JArray((object)tagIds));
			text = ((object)val).ToString();
		}
		return ((ApiBase)this).TwitchPutAsync("/streams/tags", (ApiVersion)6, text, list, accessToken, (string)null, (string)null);
	}

	public Task<GetStreamKeyResponse> GetStreamKeyAsync(string broadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetStreamKeyResponse>("/streams/key", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<CreateStreamMarkerResponse> CreateStreamMarkerAsync(CreateStreamMarkerRequest request, string accessToken = null)
	{
		return ((ApiBase)this).TwitchPostGenericAsync<CreateStreamMarkerResponse>("/streams/markers", (ApiVersion)6, JsonConvert.SerializeObject((object)request), (List<KeyValuePair<string, string>>)null, accessToken, (string)null, (string)null);
	}

	public Task<GetStreamMarkersResponse> GetStreamMarkersAsync(string userId = null, string videoId = null, int first = 20, string after = null, string accessToken = null)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(userId) && string.IsNullOrWhiteSpace(videoId))
		{
			throw new BadParameterException("One of userId and videoId has to be specified");
		}
		if (!string.IsNullOrWhiteSpace(userId) && !string.IsNullOrWhiteSpace(videoId))
		{
			throw new BadParameterException("userId and videoId are mutually exclusive");
		}
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("first cannot be less than 1 or greater than 100");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (!string.IsNullOrWhiteSpace(userId))
		{
			list.Add(new KeyValuePair<string, string>("user_id", userId));
		}
		if (!string.IsNullOrWhiteSpace(videoId))
		{
			list.Add(new KeyValuePair<string, string>("video_id", videoId));
		}
		list.Add(new KeyValuePair<string, string>("first", first.ToString()));
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetStreamMarkersResponse>("/streams/markers", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetFollowedStreamsResponse> GetFollowedStreamsAsync(string userId, int first = 100, string after = null, string accessToken = null)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (first < 1 || first > 100)
		{
			throw new BadParameterException("first cannot be less than 1 or greater than 100");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("user_id", userId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetFollowedStreamsResponse>("/streams/followed", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Subscriptions : ApiBase
{
	public Subscriptions(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<CheckUserSubscriptionResponse> CheckUserSubscriptionAsync(string broadcasterId, string userId, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("BroadcasterId must be set");
		}
		if (string.IsNullOrWhiteSpace(userId))
		{
			throw new BadParameterException("UserId must be set");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("user_id", userId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<CheckUserSubscriptionResponse>("/subscriptions/user", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetUserSubscriptionsResponse> GetUserSubscriptionsAsync(string broadcasterId, List<string> userIds, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("BroadcasterId must be set");
		}
		if (userIds == null || userIds.Count == 0)
		{
			throw new BadParameterException("UserIds must be set contain at least one user id");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		list.AddRange(userIds.Select((string userId) => new KeyValuePair<string, string>("user_id", userId)));
		return ((ApiBase)this).TwitchGetGenericAsync<GetUserSubscriptionsResponse>("/subscriptions", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetBroadcasterSubscriptionsResponse> GetBroadcasterSubscriptionsAsync(string broadcasterId, int first = 20, string after = null, string accessToken = null)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrWhiteSpace(broadcasterId))
		{
			throw new BadParameterException("BroadcasterId must be set");
		}
		if (first > 100)
		{
			throw new BadParameterException("First must be 100 or less");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetBroadcasterSubscriptionsResponse>("/subscriptions", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Tags : ApiBase
{
	public Tags(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetAllStreamTagsResponse> GetAllStreamTagsAsync(string after = null, int first = 20, List<string> tagIds = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		if (first >= 0 && first <= 100)
		{
			list.Add(new KeyValuePair<string, string>("first", first.ToString()));
			if (tagIds != null && tagIds.Count > 0)
			{
				list.AddRange(tagIds.Select((string tagId) => new KeyValuePair<string, string>("tag_id", tagId)));
			}
			return ((ApiBase)this).TwitchGetGenericAsync<GetAllStreamTagsResponse>("/tags/streams", (ApiVersion)6, list, accessToken, (string)null, (string)null);
		}
		throw new ArgumentOutOfRangeException("first", "first value cannot exceed 100 and cannot be less than 1");
	}
}
public class Teams : ApiBase
{
	public Teams(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetChannelTeamsResponse> GetChannelTeamsAsync(string broadcasterId, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId)
		};
		return ((ApiBase)this).TwitchGetGenericAsync<GetChannelTeamsResponse>("/teams/channel", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task<GetTeamsResponse> GetTeamsAsync(string teamId = null, string teamName = null, string accessToken = null)
	{
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
		if (!string.IsNullOrWhiteSpace(teamId))
		{
			list.Add(new KeyValuePair<string, string>("id", teamId));
		}
		if (!string.IsNullOrWhiteSpace(teamName))
		{
			list.Add(new KeyValuePair<string, string>("name", teamName));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetTeamsResponse>("/teams", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}
}
public class Users : ApiBase
{
	public Users(IApiSettings settings, IRateLimiter rateLimiter, IHttpCallHandler http)
		: base(settings, rateLimiter, http)
	{
	}

	public Task<GetUserBlockListResponse> GetUserBlockListAsync(string broadcasterId, int first = 20, string after = null, string accessToken = null)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		if (first > 100)
		{
			throw new BadParameterException($"Maximum allowed objects is 100 (you passed {first})");
		}
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("broadcaster_id", broadcasterId),
			new KeyValuePair<string, string>("first", first.ToString())
		};
		if (!string.IsNullOrWhiteSpace(after))
		{
			list.Add(new KeyValuePair<string, string>("after", after));
		}
		return ((ApiBase)this).TwitchGetGenericAsync<GetUserBlockListResponse>("/users/blocks", (ApiVersion)6, list, accessToken, (string)null, (string)null);
	}

	public Task BlockUserAsync(string targetUserId, BlockUserSourceContextEnum? sourceContext = null, BlockUserReasonEnum? reason = null, string accessToken = null)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>
		{
			new KeyValuePair<string, string>("target_user_id", targetUserId)
		};
		if (sourceContext.HasValue)
		{
			BlockUserSourceContextEnum value = sourceContext.V

plugins/TwitchLib/TwitchLib.Api.Helix.Models.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using TwitchLib.Api.Core.Enums;
using TwitchLib.Api.Helix.Models.Common;
using TwitchLib.Api.Helix.Models.Games;
using TwitchLib.Api.Helix.Models.Users.Internal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Project containing the Helix models used in TwitchLib.Api")]
[assembly: AssemblyFileVersion("3.8.0")]
[assembly: AssemblyInformationalVersion("3.8.0")]
[assembly: AssemblyProduct("TwitchLib.Api.Helix.Models")]
[assembly: AssemblyTitle("TwitchLib.Api.Helix.Models")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/swiftyspiffy/TwitchLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.8.0.0")]
namespace TwitchLib.Api.Helix.Models.Videos.GetVideos
{
	public class GetVideosResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Video[] Videos { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class MutedSegment
	{
		[JsonProperty(PropertyName = "duration")]
		public int Duration { get; protected set; }

		[JsonProperty(PropertyName = "offset")]
		public int Offset { get; protected set; }
	}
	public class Video
	{
		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }

		[JsonProperty(PropertyName = "duration")]
		public string Duration { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "language")]
		public string Language { get; protected set; }

		[JsonProperty(PropertyName = "published_at")]
		public string PublishedAt { get; protected set; }

		[JsonProperty(PropertyName = "thumbnail_url")]
		public string ThumbnailUrl { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "url")]
		public string Url { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "viewable")]
		public string Viewable { get; protected set; }

		[JsonProperty(PropertyName = "view_count")]
		public int ViewCount { get; protected set; }

		[JsonProperty(PropertyName = "stream_id")]
		public string StreamId { get; protected set; }

		[JsonProperty(PropertyName = "muted_segments")]
		public MutedSegment[] MutedSegments { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Videos.DeleteVideos
{
	public class DeleteVideosResponse
	{
		[JsonProperty(PropertyName = "data")]
		public string[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Users.UpdateUserExtensions
{
	public class UpdateUserExtensionsRequest
	{
		[JsonProperty(PropertyName = "panel")]
		public Dictionary<string, UserExtensionState> Panel { get; set; }

		[JsonProperty(PropertyName = "component")]
		public Dictionary<string, UserExtensionState> Component { get; set; }

		[JsonProperty(PropertyName = "overlay")]
		public Dictionary<string, UserExtensionState> Overlay { get; set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Users.Internal
{
	public class ActiveExtensions
	{
		[JsonProperty(PropertyName = "panel")]
		public Dictionary<string, UserActiveExtension> Panel { get; protected set; }

		[JsonProperty(PropertyName = "overlay")]
		public Dictionary<string, UserActiveExtension> Overlay { get; protected set; }

		[JsonProperty(PropertyName = "component")]
		public Dictionary<string, UserActiveExtension> Component { get; protected set; }
	}
	public class ExtensionSlot
	{
		public ExtensionType Type;

		public string Slot;

		public UserExtensionState UserExtensionState;

		public ExtensionSlot(ExtensionType type, string slot, UserExtensionState userExtensionState)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Type = type;
			Slot = slot;
			UserExtensionState = userExtensionState;
		}
	}
	public class UserActiveExtension
	{
		[JsonProperty(PropertyName = "active")]
		public bool Active { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "x")]
		public int X { get; protected set; }

		[JsonProperty(PropertyName = "y")]
		public int Y { get; protected set; }
	}
	public class UserExtension
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "can_activate")]
		public bool CanActivate { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string[] Type { get; protected set; }
	}
	public class UserExtensionState
	{
		[JsonProperty(PropertyName = "active")]
		public bool Active { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		public UserExtensionState(bool active, string id, string version)
		{
			Active = active;
			Id = id;
			Version = version;
		}
	}
}
namespace TwitchLib.Api.Helix.Models.Users.GetUsers
{
	public class GetUsersResponse
	{
		[JsonProperty(PropertyName = "data")]
		public User[] Users { get; protected set; }
	}
	public class User
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "login")]
		public string Login { get; protected set; }

		[JsonProperty(PropertyName = "display_name")]
		public string DisplayName { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_type")]
		public string BroadcasterType { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }

		[JsonProperty(PropertyName = "profile_image_url")]
		public string ProfileImageUrl { get; protected set; }

		[JsonProperty(PropertyName = "offline_image_url")]
		public string OfflineImageUrl { get; protected set; }

		[JsonProperty(PropertyName = "view_count")]
		public long ViewCount { get; protected set; }

		[JsonProperty(PropertyName = "email")]
		public string Email { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Users.GetUserFollows
{
	public class Follow
	{
		[JsonProperty(PropertyName = "from_id")]
		public string FromUserId { get; protected set; }

		[JsonProperty(PropertyName = "from_login")]
		public string FromLogin { get; protected set; }

		[JsonProperty(PropertyName = "from_name")]
		public string FromUserName { get; protected set; }

		[JsonProperty(PropertyName = "to_id")]
		public string ToUserId { get; protected set; }

		[JsonProperty(PropertyName = "to_login")]
		public string ToLogin { get; protected set; }

		[JsonProperty(PropertyName = "to_name")]
		public string ToUserName { get; protected set; }

		[JsonProperty(PropertyName = "followed_at")]
		public DateTime FollowedAt { get; protected set; }
	}
	public class GetUsersFollowsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Follow[] Follows { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }

		[JsonProperty(PropertyName = "total")]
		public long TotalFollows { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Users.GetUserExtensions
{
	public class GetUserExtensionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public UserExtension[] Users { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Users.GetUserBlockList
{
	public class BlockedUser
	{
		[JsonProperty(PropertyName = "user_id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "display_name")]
		public string DisplayName { get; protected set; }
	}
	public class GetUserBlockListResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BlockedUser[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Users.GetUserActiveExtensions
{
	public class GetUserActiveExtensionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ActiveExtensions Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Teams
{
	public class ChannelTeam : TeamBase
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }
	}
	public class GetChannelTeamsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ChannelTeam[] ChannelTeams { get; protected set; }
	}
	public class GetTeamsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Team[] Teams { get; protected set; }
	}
	public class Team : TeamBase
	{
		[JsonProperty(PropertyName = "users")]
		public TeamMember[] Users { get; protected set; }
	}
	public abstract class TeamBase
	{
		[JsonProperty(PropertyName = "banner")]
		public string Banner { get; protected set; }

		[JsonProperty(PropertyName = "background_image_url")]
		public string BackgroundImageUrl { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "updated_at")]
		public string UpdatedAt { get; protected set; }

		public string Info { get; protected set; }

		[JsonProperty(PropertyName = "thumbnail_url")]
		public string ThumbnailUrl { get; protected set; }

		[JsonProperty(PropertyName = "team_name")]
		public string TeamName { get; protected set; }

		[JsonProperty(PropertyName = "team_display_name")]
		public string TeamDisplayName { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }
	}
	public class TeamMember
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Tags
{
	public class GetAllStreamTagsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Tag[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Subscriptions
{
	public class CheckUserSubscriptionResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Subscription[] Data { get; protected set; }
	}
	public class GetBroadcasterSubscriptionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Subscription[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }

		[JsonProperty(PropertyName = "total")]
		public int Total { get; protected set; }

		[JsonProperty(PropertyName = "points")]
		public int Points { get; protected set; }
	}
	public class GetUserSubscriptionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Subscription[] Data { get; protected set; }
	}
	public class Subscription
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "is_gift")]
		public bool IsGift { get; protected set; }

		[JsonProperty(PropertyName = "tier")]
		public string Tier { get; protected set; }

		[JsonProperty(PropertyName = "plan_name")]
		public string PlanName { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "gifter_id")]
		public string GiftertId { get; protected set; }

		[JsonProperty(PropertyName = "gifter_name")]
		public string GifterName { get; protected set; }

		[JsonProperty(PropertyName = "gifter_login")]
		public string GifterLogin { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Streams.GetStreamTags
{
	public class GetStreamTagsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Tag[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Streams.GetStreams
{
	public class GetStreamsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Stream[] Streams { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class LiveStreams
	{
		[JsonProperty(PropertyName = "_total")]
		public int Total { get; protected set; }

		[JsonProperty(PropertyName = "streams")]
		public Stream[] Streams { get; protected set; }
	}
	public class Stream
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "game_name")]
		public string GameName { get; protected set; }

		[JsonProperty(PropertyName = "community_ids")]
		public string[] CommunityIds { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "viewer_count")]
		public int ViewerCount { get; protected set; }

		[JsonProperty(PropertyName = "started_at")]
		public DateTime StartedAt { get; protected set; }

		[JsonProperty(PropertyName = "language")]
		public string Language { get; protected set; }

		[JsonProperty(PropertyName = "thumbnail_url")]
		public string ThumbnailUrl { get; protected set; }

		[JsonProperty(PropertyName = "tag_ids")]
		public string[] TagIds { get; protected set; }

		[JsonProperty(PropertyName = "is_mature")]
		public bool IsMature { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Streams.GetStreamMarkers
{
	public class GetStreamMarkersResponse
	{
		[JsonProperty(PropertyName = "data")]
		public UserMarkerListing[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class Marker
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }

		[JsonProperty(PropertyName = "position_seconds")]
		public int PositionSeconds { get; protected set; }

		[JsonProperty(PropertyName = "URL")]
		public string Url { get; protected set; }
	}
	public class UserMarkerListing
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "username")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "videos")]
		public Video[] Videos { get; protected set; }
	}
	public class Video
	{
		[JsonProperty(PropertyName = "video_id")]
		public string VideoId { get; protected set; }

		[JsonProperty(PropertyName = "markers")]
		public Marker[] Markers { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Streams.GetStreamKey
{
	public class GetStreamKeyResponse
	{
		[JsonProperty(PropertyName = "data")]
		public StreamKey[] Streams { get; protected set; }
	}
	public class StreamKey
	{
		[JsonProperty(PropertyName = "stream_key")]
		public string Key { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Streams.GetFollowedStreams
{
	public class GetFollowedStreamsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Stream[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class Stream
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "game_name")]
		public string GameName { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "viewer_count")]
		public int ViewerCount { get; protected set; }

		[JsonProperty(PropertyName = "started_at")]
		public DateTime StartedAt { get; protected set; }

		[JsonProperty(PropertyName = "language")]
		public string Language { get; protected set; }

		[JsonProperty(PropertyName = "thumbnail_url")]
		public string ThumbnailUrl { get; protected set; }

		[JsonProperty(PropertyName = "tag_ids")]
		public string[] TagIds { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Streams.CreateStreamMarker
{
	public class CreatedMarker
	{
		[JsonProperty(PropertyName = "id")]
		public int Id { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }

		[JsonProperty(PropertyName = "position_seconds")]
		public int PositionSeconds { get; protected set; }
	}
	[JsonObject(/*Could not decode attribute arguments.*/)]
	public class CreateStreamMarkerRequest
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; set; }
	}
	public class CreateStreamMarkerResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CreatedMarker[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Soundtrack
{
	public class Album
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "image_url")]
		public string ImageUrl { get; protected set; }
	}
	public class Artist
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "creator_channel_id")]
		public string CreatorChannelId { get; protected set; }
	}
	public class Source
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "content_type")]
		public string ContentType { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "image_url")]
		public string ImageUrl { get; protected set; }

		[JsonProperty(PropertyName = "soundtrack_url")]
		public string SoundtrackUrl { get; protected set; }

		[JsonProperty(PropertyName = "spotify_url")]
		public string SpotifyUrl { get; protected set; }
	}
	public class Track
	{
		[JsonProperty(PropertyName = "artists")]
		public Artist[] Artists { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "duration")]
		public int Duration { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "album")]
		public Album Album { get; protected set; }

		[JsonProperty(PropertyName = "isrc")]
		public string ISRC { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Soundtrack.GetPlaylists
{
	public class GetPlaylistsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public PlaylistMetadata[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class PlaylistMetadata
	{
		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "image_url")]
		public string ImageUrl { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Soundtrack.GetPlaylist
{
	public class GetPlaylistResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Track[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Soundtrack.GetCurrentTrack
{
	public class CurrentTrack
	{
		[JsonProperty(PropertyName = "track")]
		public Track Track { get; protected set; }

		[JsonProperty(PropertyName = "source")]
		public Source Source { get; protected set; }
	}
	public class GetCurrentTrackResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CurrentTrack[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Search
{
	public class Channel
	{
		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "game_name")]
		public string GameName { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "display_name")]
		public string DisplayName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_language")]
		public string BroadcasterLanguage { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "thumbnail_url")]
		public string ThumbnailUrl { get; protected set; }

		[JsonProperty(PropertyName = "is_live")]
		public bool IsLive { get; protected set; }

		[JsonProperty(PropertyName = "started_at")]
		public DateTime? StartedAt { get; protected set; }

		[JsonProperty(PropertyName = "tag_ids")]
		public List<string> TagIds { get; protected set; }
	}
	public class SearchCategoriesResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Game[] Games { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class SearchChannelsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Channel[] Channels { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Schedule
{
	public class Category
	{
		[JsonProperty("id")]
		public string Id { get; protected set; }

		[JsonProperty("name")]
		public string Name { get; protected set; }
	}
	public class ChannelStreamSchedule
	{
		[JsonProperty("segments")]
		public Segment[] Segments { get; protected set; }

		[JsonProperty("broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty("broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty("broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty("vacation")]
		public Vacation Vacation { get; protected set; }
	}
	public class Segment
	{
		[JsonProperty("id")]
		public string Id { get; protected set; }

		[JsonProperty("start_time")]
		public DateTime StartTime { get; protected set; }

		[JsonProperty("end_time")]
		public DateTime EndTime { get; protected set; }

		[JsonProperty("title")]
		public string Title { get; protected set; }

		[JsonProperty("canceled_until")]
		public DateTime? CanceledUntil { get; protected set; }

		[JsonProperty("category")]
		public Category Category { get; protected set; }

		[JsonProperty("is_recurring")]
		public bool IsRecurring { get; protected set; }
	}
	public class Vacation
	{
		[JsonProperty("start_time")]
		public DateTime StartTime { get; protected set; }

		[JsonProperty("end_time")]
		public DateTime EndTime { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Schedule.UpdateChannelStreamSegment
{
	public class UpdateChannelStreamSegmentRequest
	{
		[JsonProperty("start_time")]
		public DateTime StartTime { get; set; }

		[JsonProperty("duration")]
		public string Duration { get; set; }

		[JsonProperty("category_id")]
		public string CategoryId { get; set; }

		[JsonProperty("is_canceled")]
		public bool IsCanceled { get; set; }

		[JsonProperty("timezone")]
		public string Timezone { get; set; }
	}
	public class UpdateChannelStreamSegmentResponse
	{
		[JsonProperty("data")]
		public ChannelStreamSchedule Schedule { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Schedule.GetChannelStreamSchedule
{
	public class GetChannelStreamScheduleResponse
	{
		[JsonProperty("data")]
		public ChannelStreamSchedule Schedule { get; protected set; }

		[JsonProperty("pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Schedule.CreateChannelStreamSegment
{
	public class CreateChannelStreamSegmentRequest
	{
		[JsonProperty("start_time")]
		public DateTime StartTime { get; set; }

		[JsonProperty("timezone")]
		public string Timezone { get; set; }

		[JsonProperty("is_recurring")]
		public bool IsRecurring { get; set; }

		[JsonProperty("duration")]
		public string Duration { get; set; }

		[JsonProperty("category_id")]
		public string CategoryId { get; set; }

		[JsonProperty("title")]
		public string Title { get; set; }
	}
	public class CreateChannelStreamSegmentResponse
	{
		[JsonProperty("data")]
		public ChannelStreamSchedule Schedule { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Raids
{
	public class Raid
	{
		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "is_mature")]
		public bool IsMature { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Raids.StartRaid
{
	public class StartRaidResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Raid[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Predictions
{
	public class Outcome
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "users")]
		public int ChannelPoints { get; protected set; }

		[JsonProperty(PropertyName = "channel_points")]
		public int ChannelPointsVotes { get; protected set; }

		[JsonProperty(PropertyName = "top_predictors")]
		public TopPredictor[] TopPredictors { get; protected set; }

		[JsonProperty(PropertyName = "color")]
		public string Color { get; protected set; }
	}
	public class Prediction
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "winning_outcome_id")]
		public string WinningOutcomeId { get; protected set; }

		[JsonProperty(PropertyName = "outcomes")]
		public Outcome[] Outcomes { get; protected set; }

		[JsonProperty(PropertyName = "prediction_window")]
		public string PredictionWindow { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public PredictionStatus Status { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "ended_at")]
		public string EndedAt { get; protected set; }

		[JsonProperty(PropertyName = "locked_at")]
		public string LockedAt { get; protected set; }
	}
	public class TopPredictor
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "channel_points_used")]
		public int ChannelPointsUsed { get; protected set; }

		[JsonProperty(PropertyName = "channel_points_won")]
		public int ChannelPointsWon { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Predictions.GetPredictions
{
	public class GetPredictionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Prediction[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Predictions.EndPrediction
{
	public class EndPredictionResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Prediction[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Predictions.CreatePrediction
{
	public class CreatePredictionRequest
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; set; }

		[JsonProperty(PropertyName = "outcomes")]
		public Outcome[] Outcomes { get; set; }

		[JsonProperty(PropertyName = "prediction_window")]
		public int PredictionWindowSeconds { get; set; }
	}
	public class CreatePredictionResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Prediction[] Data { get; protected set; }
	}
	public class Outcome
	{
		[JsonProperty(PropertyName = "title")]
		public string Title { get; set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Polls
{
	public class Choice
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "votes")]
		public int Votes { get; protected set; }

		[JsonProperty(PropertyName = "channel_points_votes")]
		public int ChannelPointsVotes { get; protected set; }

		[JsonProperty(PropertyName = "bits_votes")]
		public int BitsVotes { get; protected set; }
	}
	public class Poll
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "choices")]
		public Choice[] Choices { get; protected set; }

		[JsonProperty(PropertyName = "bits_voting_enabled")]
		public bool BitsVotingEnabled { get; protected set; }

		[JsonProperty(PropertyName = "bits_per_vote")]
		public int BitsPerVote { get; protected set; }

		[JsonProperty(PropertyName = "channel_points_voting_enabled")]
		public bool ChannelPointsVotingEnabled { get; protected set; }

		[JsonProperty(PropertyName = "channel_points_per_vote")]
		public int ChannelPointsPerVote { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public string Status { get; protected set; }

		[JsonProperty(PropertyName = "duration")]
		public int DurationSeconds { get; protected set; }

		[JsonProperty(PropertyName = "started_at")]
		public DateTime StartedAt { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Polls.GetPolls
{
	public class GetPollsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Poll[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Polls.EndPoll
{
	public class EndPollResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Poll[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Polls.CreatePoll
{
	public class Choice
	{
		[JsonProperty(PropertyName = "title")]
		public string Title { get; set; }
	}
	public class CreatePollRequest
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; set; }

		[JsonProperty(PropertyName = "choices")]
		public Choice[] Choices { get; set; }

		[JsonProperty(PropertyName = "bits_voting_enabled")]
		public bool BitsVotingEnabled { get; set; }

		[JsonProperty(PropertyName = "bits_per_vote")]
		public int BitsPerVote { get; set; }

		[JsonProperty(PropertyName = "channel_points_voting_enabled")]
		public bool ChannelPointsVotingEnabled { get; set; }

		[JsonProperty(PropertyName = "channel_points_per_vote")]
		public int ChannelPointsPerVote { get; set; }

		[JsonProperty(PropertyName = "duration")]
		public int DurationSeconds { get; set; }
	}
	public class CreatePollResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Poll[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.GetModerators
{
	public class GetModeratorsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Moderator[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class Moderator
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.GetModeratorEvents
{
	public class EventData
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }
	}
	public class GetModeratorEventsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ModeratorEvent[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class ModeratorEvent
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "event_type")]
		public string EventType { get; protected set; }

		[JsonProperty(PropertyName = "event_timestamp")]
		public DateTime EventTimestamp { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "event_data")]
		public EventData EventData { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.GetBannedUsers
{
	public class BannedUserEvent
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "expires_at")]
		public DateTime? ExpiresAt { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "reason")]
		public string Reason { get; protected set; }

		[JsonProperty(PropertyName = "moderator_id")]
		public string ModeratorId { get; protected set; }

		[JsonProperty(PropertyName = "moderator_login")]
		public string ModeratorLogin { get; protected set; }

		[JsonProperty(PropertyName = "moderator_name")]
		public string ModeratorName { get; protected set; }
	}
	public class GetBannedUsersResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BannedUserEvent[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.GetBannedEvents
{
	public class BannedEvent
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "event_type")]
		public string EventType { get; protected set; }

		[JsonProperty(PropertyName = "event_timestamp")]
		public DateTime EventTimestamp { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "event_data")]
		public EventData EventData { get; protected set; }
	}
	public class EventData
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "expires_at")]
		public DateTime? ExpiresAt { get; protected set; }

		[JsonProperty(PropertyName = "reason")]
		public string Reason { get; protected set; }

		[JsonProperty(PropertyName = "moderator_id")]
		public string ModeratorId { get; protected set; }

		[JsonProperty(PropertyName = "moderator_login")]
		public string ModeratorLogin { get; protected set; }

		[JsonProperty(PropertyName = "moderator_name")]
		public string ModeratorName { get; protected set; }
	}
	public class GetBannedEventsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BannedEvent[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.CheckAutoModStatus
{
	public class AutoModResult
	{
		[JsonProperty(PropertyName = "msg_id")]
		public string MsgId { get; protected set; }

		[JsonProperty(PropertyName = "is_permitted")]
		public bool IsPermitted { get; protected set; }
	}
	public class CheckAutoModStatusResponse
	{
		[JsonProperty(PropertyName = "data")]
		public AutoModResult[] Data { get; protected set; }
	}
	public class Message
	{
		[JsonProperty(PropertyName = "msg_id")]
		public string MsgId { get; set; }

		[JsonProperty(PropertyName = "msg_text")]
		public string MsgText { get; set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.CheckAutoModStatus.Request
{
	public class MessageRequest
	{
		[JsonProperty(PropertyName = "data")]
		public Message[] Messages { get; set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.BlockedTerms
{
	public class AddBlockedTermResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BlockedTerm[] Data { get; protected set; }
	}
	public class BlockedTerm
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "moderator_id")]
		public string ModeratorId { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "text")]
		public string Text { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "updated_at")]
		public DateTime UpdatedAt { get; protected set; }

		[JsonProperty(PropertyName = "expires_at")]
		public DateTime? ExpiresAt { get; protected set; }
	}
	public class GetBlockedTermsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BlockedTerm[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.BanUser
{
	public class BannedUser
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "moderator_id")]
		public string ModeratorId { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "end_time")]
		public DateTime? EndTime { get; protected set; }
	}
	public class BanUser
	{
		public string UserId;

		public string Reason;
	}
	public class BanUserRequest
	{
		[JsonProperty("user_id")]
		public string UserId { get; set; }

		[JsonProperty("reason")]
		public string Reason { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int? Duration { get; set; }
	}
	public class BanUserResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BannedUser[] Data { get; protected set; }
	}
	public class TimeoutUser
	{
		public string UserId;

		public string Reason;

		public TimeSpan Duration;
	}
}
namespace TwitchLib.Api.Helix.Models.Moderation.AutomodSettings
{
	public class AutomodSettings
	{
		[JsonProperty(PropertyName = "overall_level")]
		public int? OverallLevel;

		[JsonProperty(PropertyName = "disability")]
		public int? Disability;

		[JsonProperty(PropertyName = "aggression")]
		public int? Aggression;

		[JsonProperty(PropertyName = "sexuality_sex_or_gender")]
		public int? SexualitySexOrGender;

		[JsonProperty(PropertyName = "misogyny")]
		public int? Misogyny;

		[JsonProperty(PropertyName = "bullying")]
		public int? Bullying;

		[JsonProperty(PropertyName = "swearing")]
		public int? Swearing;

		[JsonProperty(PropertyName = "race_ethnicity_or_religion")]
		public int? RaceEthnicityOrReligion;

		[JsonProperty(PropertyName = "sex_based_terms")]
		public int? SexBasedTerms;
	}
	public class AutomodSettingsResponseModel
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId;

		[JsonProperty(PropertyName = "moderator_id")]
		public string ModeratorId;

		[JsonProperty(PropertyName = "overall_level")]
		public int? OverallLevel;

		[JsonProperty(PropertyName = "disability")]
		public int? Disability;

		[JsonProperty(PropertyName = "aggression")]
		public int? Aggression;

		[JsonProperty(PropertyName = "sexuality_sex_or_gender")]
		public int? SexualitySexOrGender;

		[JsonProperty(PropertyName = "misogyny")]
		public int? Misogyny;

		[JsonProperty(PropertyName = "bullying")]
		public int? Bullying;

		[JsonProperty(PropertyName = "swearing")]
		public int? Swearing;

		[JsonProperty(PropertyName = "race_ethnicity_or_religion")]
		public int? RaceEthnicityOrReligion;

		[JsonProperty(PropertyName = "sex_based_terms")]
		public int? SexBasedTerms;
	}
	public class GetAutomodSettingsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public AutomodSettingsResponseModel[] Data { get; protected set; }
	}
	public class UpdateAutomodSettingsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public AutomodSettings[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.HypeTrain
{
	public class GetHypeTrainResponse
	{
		[JsonProperty(PropertyName = "data")]
		public HypeTrain[] HypeTrain { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class HypeTrain
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "event_type")]
		public string EventType { get; protected set; }

		[JsonProperty(PropertyName = "event_timestamp")]
		public string EventTimeStamp { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "event_data")]
		public HypeTrainEventData EventData { get; protected set; }
	}
	public class HypeTrainContribution
	{
		[JsonProperty(PropertyName = "total")]
		public int Total { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "user")]
		public string UserId { get; protected set; }
	}
	public class HypeTrainEventData
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "started_at")]
		public string StartedAt { get; protected set; }

		[JsonProperty(PropertyName = "expires_at")]
		public string ExpiresAt { get; protected set; }

		[JsonProperty(PropertyName = "cooldown_end_time")]
		public string CooldownEndTime { get; protected set; }

		[JsonProperty(PropertyName = "level")]
		public int Level { get; protected set; }

		[JsonProperty(PropertyName = "goal")]
		public int Goal { get; protected set; }

		[JsonProperty(PropertyName = "total")]
		public int Total { get; protected set; }

		[JsonProperty(PropertyName = "top_contribution")]
		public HypeTrainContribution TopContribution { get; protected set; }

		[JsonProperty(PropertyName = "last_contribution")]
		public HypeTrainContribution LastContribution { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Helpers
{
	public class ExtensionAnalytics
	{
		public string Date { get; protected set; }

		public string ExtensionName { get; protected set; }

		public string ExtensionClientId { get; protected set; }

		public int Installs { get; protected set; }

		public int Uninstalls { get; protected set; }

		public int Activations { get; protected set; }

		public int UniqueActiveChannels { get; protected set; }

		public int Renders { get; protected set; }

		public int UniqueRenders { get; protected set; }

		public int Views { get; protected set; }

		public int UniqueViewers { get; protected set; }

		public int UniqueInteractors { get; protected set; }

		public int Clicks { get; protected set; }

		public double ClicksPerInteractor { get; protected set; }

		public double InteractionRate { get; protected set; }

		public ExtensionAnalytics(string row)
		{
			string[] array = row.Split(new char[1] { ',' });
			Date = array[0];
			ExtensionName = array[1];
			ExtensionClientId = array[2];
			Installs = int.Parse(array[3]);
			Uninstalls = int.Parse(array[4]);
			Activations = int.Parse(array[5]);
			UniqueActiveChannels = int.Parse(array[6]);
			Renders = int.Parse(array[7]);
			UniqueRenders = int.Parse(array[8]);
			Views = int.Parse(array[9]);
			UniqueViewers = int.Parse(array[10]);
			UniqueInteractors = int.Parse(array[11]);
			Clicks = int.Parse(array[12]);
			ClicksPerInteractor = double.Parse(array[13]);
			InteractionRate = double.Parse(array[14]);
		}
	}
}
namespace TwitchLib.Api.Helix.Models.Goals
{
	public class CreatorGoal
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }

		[JsonProperty(PropertyName = "current_amount")]
		public int CurrentAmount { get; protected set; }

		[JsonProperty(PropertyName = "target_amount")]
		public int TargetAmount { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }
	}
	public class GetCreatorGoalsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CreatorGoal[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Games
{
	public class Game
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "box_art_url")]
		public string BoxArtUrl { get; protected set; }
	}
	public class GetGamesResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Game[] Games { get; protected set; }
	}
	public class GetTopGamesResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Game[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Extensions.Transactions
{
	public class GetExtensionTransactionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Transaction[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
	public class ProductData
	{
		[JsonProperty(PropertyName = "domain")]
		public string Domain { get; protected set; }

		[JsonProperty(PropertyName = "sku")]
		public string SKU { get; protected set; }

		[JsonProperty(PropertyName = "cost")]
		public Cost Cost { get; protected set; }

		[JsonProperty(PropertyName = "inDevelopment")]
		public bool InDevelopment { get; protected set; }

		[JsonProperty(PropertyName = "displayName")]
		public string DisplayName { get; protected set; }

		[JsonProperty(PropertyName = "expiration")]
		public string Expiration { get; protected set; }

		[JsonProperty(PropertyName = "broadcast")]
		public bool Broadcast { get; protected set; }
	}
	public class Cost
	{
		[JsonProperty(PropertyName = "amount")]
		public int Amount { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }
	}
	public class Transaction
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "timestamp")]
		public DateTime Timestamp { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "product_type")]
		public string ProductType { get; protected set; }

		[JsonProperty(PropertyName = "product_data")]
		public ProductData ProductData { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Extensions.ReleasedExtensions
{
	public class Component
	{
		[JsonProperty(PropertyName = "viewer_url")]
		public string ViewerUrl { get; protected set; }

		[JsonProperty(PropertyName = "aspect_width")]
		public int AspectWidth { get; protected set; }

		[JsonProperty(PropertyName = "aspect_height")]
		public int AspectHeight { get; protected set; }

		[JsonProperty(PropertyName = "aspect_ratio_x")]
		public int AspectRatioX { get; protected set; }

		[JsonProperty(PropertyName = "aspect_ratio_y")]
		public int AspectRatioY { get; protected set; }

		[JsonProperty(PropertyName = "autoscale")]
		public bool Autoscale { get; protected set; }

		[JsonProperty(PropertyName = "scale_pixels")]
		public int ScalePixels { get; protected set; }

		[JsonProperty(PropertyName = "target_height")]
		public int TargetHeight { get; protected set; }

		[JsonProperty(PropertyName = "size")]
		public int Size { get; protected set; }

		[JsonProperty(PropertyName = "zoom")]
		public bool Zoom { get; protected set; }

		[JsonProperty(PropertyName = "zoom_pixels")]
		public int ZoomPixels { get; protected set; }

		[JsonProperty(PropertyName = "can_link_external_content")]
		public string CanLinkExternalContent { get; protected set; }
	}
	public class GetReleasedExtensionsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ReleasedExtension[] Data { get; protected set; }
	}
	public class IconUrls
	{
		[JsonProperty(PropertyName = "100x100")]
		public string Size100x100 { get; protected set; }

		[JsonProperty(PropertyName = "24x24")]
		public string Size24x24 { get; protected set; }

		[JsonProperty(PropertyName = "300x200")]
		public string Size300x200 { get; protected set; }
	}
	public class Mobile
	{
		[JsonProperty(PropertyName = "viewer_url")]
		public string ViewerUrl { get; protected set; }
	}
	public class Panel
	{
		[JsonProperty(PropertyName = "viewer_url")]
		public string ViewerUrl { get; protected set; }

		[JsonProperty(PropertyName = "height")]
		public int Height { get; protected set; }

		[JsonProperty(PropertyName = "can_link_external_content")]
		public bool CanLinkExternalContent { get; protected set; }
	}
	public class ReleasedExtension
	{
		[JsonProperty(PropertyName = "author_name")]
		public string AuthorName { get; protected set; }

		[JsonProperty(PropertyName = "bits_enabled")]
		public bool BitsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "can_install")]
		public bool CanInstall { get; protected set; }

		[JsonProperty(PropertyName = "configuration_location")]
		public string ConfigurationLocation { get; protected set; }

		[JsonProperty(PropertyName = "description")]
		public string Description { get; protected set; }

		[JsonProperty(PropertyName = "eula_tos_url")]
		public string EulaTosUrl { get; protected set; }

		[JsonProperty(PropertyName = "has_chat_support")]
		public bool HasChatSupport { get; protected set; }

		[JsonProperty(PropertyName = "icon_url")]
		public string IconUrl { get; protected set; }

		[JsonProperty(PropertyName = "icon_urls")]
		public IconUrls IconUrls { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "name")]
		public string Name { get; protected set; }

		[JsonProperty(PropertyName = "privacy_policy_url")]
		public string PrivacyPolicyUrl { get; protected set; }

		[JsonProperty(PropertyName = "request_identity_link")]
		public bool RequestIdentityLink { get; protected set; }

		[JsonProperty(PropertyName = "screenshot_urls")]
		public string[] ScreenshotUrls { get; protected set; }

		[JsonProperty(PropertyName = "state")]
		public ExtensionState State { get; protected set; }

		[JsonProperty(PropertyName = "subscriptions_support_level")]
		public string SubscriptionsSupportLevel { get; protected set; }

		[JsonProperty(PropertyName = "summary")]
		public string Summary { get; protected set; }

		[JsonProperty(PropertyName = "support_email")]
		public string SupportEmail { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "viewer_summary")]
		public string ViewerSummary { get; protected set; }

		[JsonProperty(PropertyName = "views")]
		public Views Views { get; protected set; }

		[JsonProperty(PropertyName = "allowlisted_config_urls")]
		public string[] AllowlistedConfigUrls { get; protected set; }

		[JsonProperty(PropertyName = "allowlisted_panel_urls")]
		public string[] AllowlistedPanelUrls { get; protected set; }
	}
	public class VideoOverlay
	{
		[JsonProperty(PropertyName = "viewer_url")]
		public string ViewerUrl { get; protected set; }

		[JsonProperty(PropertyName = "can_link_external_content")]
		public bool CanLinkExternalContent { get; protected set; }
	}
	public class Views
	{
		[JsonProperty(PropertyName = "mobile")]
		public Mobile Mobile { get; protected set; }

		[JsonProperty(PropertyName = "panel")]
		public Panel Panel { get; protected set; }

		[JsonProperty(PropertyName = "video_overlay")]
		public VideoOverlay VideoOverlay { get; protected set; }

		[JsonProperty(PropertyName = "component")]
		public Component Component { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Extensions.LiveChannels
{
	public class GetExtensionLiveChannelsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public LiveChannel[] Data { get; protected set; }
	}
	public class LiveChannel
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "game_name")]
		public string GameName { get; protected set; }

		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.EventSub
{
	public class CreateEventSubSubscriptionResponse
	{
		[JsonProperty(PropertyName = "data")]
		public EventSubSubscription[] Subscriptions { get; protected set; }

		[JsonProperty(PropertyName = "total")]
		public int Total { get; protected set; }

		[JsonProperty(PropertyName = "total_cost")]
		public int TotalCost { get; protected set; }

		[JsonProperty(PropertyName = "max_total_cost")]
		public int MaxTotalCost { get; protected set; }
	}
	public class EventSubSubscription
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public string Status { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "version")]
		public string Version { get; protected set; }

		[JsonProperty(PropertyName = "condition")]
		public Dictionary<string, string> Condition { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "transport")]
		public EventSubTransport Transport { get; protected set; }

		[JsonProperty(PropertyName = "cost")]
		public int Cost { get; protected set; }
	}
	public class EventSubTransport
	{
		[JsonProperty(PropertyName = "method")]
		public string Method { get; protected set; }

		[JsonProperty(PropertyName = "callback")]
		public string Callback { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime? CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "disconnected_at")]
		public DateTime? DisconnectedAt { get; protected set; }
	}
	public class GetEventSubSubscriptionsResponse
	{
		[JsonProperty(PropertyName = "total")]
		public int Total { get; protected set; }

		[JsonProperty(PropertyName = "data")]
		public EventSubSubscription[] Subscriptions { get; protected set; }

		[JsonProperty(PropertyName = "total_cost")]
		public int TotalCost { get; protected set; }

		[JsonProperty(PropertyName = "max_total_cost")]
		public int MaxTotalCost { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Entitlements
{
	public class Status
	{
		[JsonProperty(PropertyName = "code")]
		public string Code { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public CodeStatusEnum StatusEnum { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Entitlements.UpdateDropsEntitlements
{
	public class DropEntitlementUpdate
	{
		[JsonProperty(PropertyName = "status")]
		public DropEntitlementUpdateStatus Status { get; protected set; }

		[JsonProperty(PropertyName = "ids")]
		public string[] Ids { get; protected set; }
	}
	public class UpdateDropsEntitlementsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public DropEntitlementUpdate[] DropEntitlementUpdates { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Entitlements.RedeemCode
{
	public class RedeemCodeResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Status[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Entitlements.GetDropsEntitlements
{
	public class DropsEntitlement
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "benefit_id")]
		public string BenefitId { get; protected set; }

		[JsonProperty(PropertyName = "timestamp")]
		public DateTime Timestamp { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "fulfillment_status")]
		public FulfillmentStatus FulfillmentStatus { get; protected set; }

		[JsonProperty(PropertyName = "updated_at")]
		public DateTime UpdatedAt { get; protected set; }
	}
	public class GetDropsEntitlementsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public DropsEntitlement[] DropEntitlements { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Entitlements.GetCodeStatus
{
	public class GetCodeStatusResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Status[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Common
{
	public class DateRange
	{
		[JsonProperty(PropertyName = "started_at")]
		public DateTime StartedAt { get; protected set; }

		[JsonProperty(PropertyName = "ended_at")]
		public DateTime EndedAt { get; protected set; }
	}
	public class Pagination
	{
		[JsonProperty(PropertyName = "cursor")]
		public string Cursor { get; protected set; }
	}
	public class Tag
	{
		[JsonProperty(PropertyName = "tag_id")]
		public string TagId { get; protected set; }

		[JsonProperty(PropertyName = "is_auto")]
		public bool IsAuto { get; protected set; }

		[JsonProperty(PropertyName = "localization_names")]
		public Dictionary<string, string> LocalizationNames { get; protected set; }

		[JsonProperty(PropertyName = "localization_descriptions")]
		public Dictionary<string, string> LocalizationDescriptions { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Clips.GetClips
{
	public class Clip
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "url")]
		public string Url { get; protected set; }

		[JsonProperty(PropertyName = "embed_url")]
		public string EmbedUrl { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "creator_id")]
		public string CreatorId { get; protected set; }

		[JsonProperty(PropertyName = "creator_name")]
		public string CreatorName { get; protected set; }

		[JsonProperty(PropertyName = "video_id")]
		public string VideoId { get; protected set; }

		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "language")]
		public string Language { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "view_count")]
		public int ViewCount { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public string CreatedAt { get; protected set; }

		[JsonProperty(PropertyName = "thumbnail_url")]
		public string ThumbnailUrl { get; protected set; }

		[JsonProperty(PropertyName = "duration")]
		public float Duration { get; protected set; }

		[JsonProperty(PropertyName = "vod_offset")]
		public int VodOffset { get; protected set; }
	}
	public class GetClipsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Clip[] Clips { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Clips.CreateClip
{
	public class CreatedClip
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "edit_url")]
		public string EditUrl { get; protected set; }
	}
	public class CreatedClipResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CreatedClip[] CreatedClips { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat
{
	public class AnnouncementColors
	{
		public string Value { get; private set; }

		public static AnnouncementColors Blue => new AnnouncementColors("blue");

		public static AnnouncementColors Green => new AnnouncementColors("green");

		public static AnnouncementColors Orange => new AnnouncementColors("orange");

		public static AnnouncementColors Purple => new AnnouncementColors("purple");

		public static AnnouncementColors Primary => new AnnouncementColors("primary");

		private AnnouncementColors(string value)
		{
			Value = value;
		}
	}
	public class UserColors
	{
		public string Value { get; private set; }

		public static UserColors Blue => new UserColors("blue");

		public static UserColors BlueVoilet => new UserColors("blue_violet");

		public static UserColors CadetBlue => new UserColors("cadet_blue");

		public static UserColors Chocolate => new UserColors("chocolate");

		public static UserColors Coral => new UserColors("coral");

		public static UserColors DodgerBlue => new UserColors("dodger_blue");

		public static UserColors Firebrick => new UserColors("firebrick");

		public static UserColors GoldenRod => new UserColors("golden_rod");

		public static UserColors HotPink => new UserColors("hot_pink");

		public static UserColors OrangeRed => new UserColors("orange_red");

		public static UserColors Red => new UserColors("red");

		public static UserColors SeaGreen => new UserColors("sea_green");

		public static UserColors SpringGreen => new UserColors("spring_green");

		public static UserColors YellowGreen => new UserColors("yellow_green");

		private UserColors(string value)
		{
			Value = value;
		}
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.GetUserChatColor
{
	public class GetUserChatColorResponse
	{
		[JsonProperty(PropertyName = "data")]
		public UserChatColorResponseModel[] Data { get; protected set; }
	}
	public class UserChatColorResponseModel
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "color")]
		public string Color { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.GetChatters
{
	public class Chatter
	{
		[JsonProperty("user_login")]
		public string UserLogin { get; protected set; }
	}
	public class GetChattersResponse
	{
		[JsonProperty("data")]
		public Chatter[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }

		[JsonProperty("total")]
		public int Total { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Emotes
{
	public class ChannelEmote : Emote
	{
		[JsonProperty("tier")]
		public string Tier { get; protected set; }

		[JsonProperty("emote_type")]
		public string EmoteType { get; protected set; }

		[JsonProperty("emote_set_id")]
		public string EmoteSetId { get; protected set; }
	}
	public abstract class Emote
	{
		[JsonProperty("id")]
		public string Id { get; protected set; }

		[JsonProperty("name")]
		public string Name { get; protected set; }

		[JsonProperty("images")]
		public EmoteImages Images { get; protected set; }

		[JsonProperty("format")]
		public string[] Format { get; protected set; }

		[JsonProperty("scale")]
		public string[] Scale { get; protected set; }

		[JsonProperty("theme_mode")]
		public string[] ThemeMode { get; protected set; }
	}
	public class EmoteImages
	{
		[JsonProperty("url_1x")]
		public string Url1X { get; protected set; }

		[JsonProperty("url_2x")]
		public string Url2X { get; protected set; }

		[JsonProperty("url_4x")]
		public string Url4X { get; protected set; }
	}
	public class EmoteSet : Emote
	{
		[JsonProperty("emote_type")]
		public string EmoteType { get; protected set; }

		[JsonProperty("emote_set_id")]
		public string EmoteSetId { get; protected set; }

		[JsonProperty("owner_id")]
		public string OwnerId { get; protected set; }
	}
	public class GlobalEmote : Emote
	{
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Emotes.GetGlobalEmotes
{
	public class GetGlobalEmotesResponse
	{
		[JsonProperty("data")]
		public GlobalEmote[] GlobalEmotes { get; protected set; }

		[JsonProperty("template")]
		public string Template { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Emotes.GetEmoteSets
{
	public class GetEmoteSetsResponse
	{
		[JsonProperty("data")]
		public EmoteSet[] EmoteSets { get; protected set; }

		[JsonProperty("template")]
		public string Template { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Emotes.GetChannelEmotes
{
	public class GetChannelEmotesResponse
	{
		[JsonProperty("data")]
		public ChannelEmote[] ChannelEmotes { get; protected set; }

		[JsonProperty("template")]
		public string Template { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.ChatSettings
{
	public class ChatSettings
	{
		[JsonProperty(PropertyName = "slow_mode")]
		public bool SlowMode;

		[JsonProperty(PropertyName = "slow_mode_wait_time")]
		public int? SlowModeWaitTime;

		[JsonProperty(PropertyName = "follower_mode")]
		public bool FollowerMode;

		[JsonProperty(PropertyName = "follower_mode_duration")]
		public int? FollowerModeDuration;

		[JsonProperty(PropertyName = "subscriber_mode")]
		public bool SubscriberMode;

		[JsonProperty(PropertyName = "emote_mode")]
		public bool EmoteMode;

		[JsonProperty(PropertyName = "unique_chat_mode")]
		public bool UniqueChatMode;

		[JsonProperty(PropertyName = "non_moderator_chat_delay")]
		public bool NonModeratorChatDelay;

		[JsonProperty(PropertyName = "non_moderator_chat_delay_duration")]
		public int? NonModeratorChatDelayDuration;
	}
	public class ChatSettingsResponseModel
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "slow_mode")]
		public bool SlowMode { get; protected set; }

		[JsonProperty(PropertyName = "slow_mode_wait_time")]
		public int? SlowModeWaitDuration { get; protected set; }

		[JsonProperty(PropertyName = "follower_mode")]
		public bool FollowerMode { get; protected set; }

		[JsonProperty(PropertyName = "follower_mode_duration")]
		public int? FollowerModeDuration { get; protected set; }

		[JsonProperty(PropertyName = "subscriber_mode")]
		public bool SubscriberMode { get; protected set; }

		[JsonProperty(PropertyName = "emote_mode")]
		public bool EmoteMode { get; protected set; }

		[JsonProperty(PropertyName = "unique_chat_mode")]
		public bool UniqueChatMode { get; protected set; }

		[JsonProperty(PropertyName = "non_moderator_chat_delay")]
		public bool NonModeratorChatDelay { get; protected set; }

		[JsonProperty(PropertyName = "non_moderator_chat_delay_duration")]
		public int? NonModeratorChatDelayDuration { get; protected set; }
	}
	public class GetChatSettingsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ChatSettingsResponseModel[] Data { get; protected set; }
	}
	public class UpdateChatSettingsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public UpdateChatSettingsResponseModel[] Data { get; protected set; }
	}
	public class UpdateChatSettingsResponseModel
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "moderator_id")]
		public string ModeratorId { get; protected set; }

		[JsonProperty(PropertyName = "slow_mode")]
		public bool SlowMode { get; protected set; }

		[JsonProperty(PropertyName = "slow_mode_wait_time")]
		public int? SlowModeWaitDuration { get; protected set; }

		[JsonProperty(PropertyName = "follower_mode")]
		public bool FollowerMode { get; protected set; }

		[JsonProperty(PropertyName = "follower_mode_duration")]
		public int? FollowerModeDuration { get; protected set; }

		[JsonProperty(PropertyName = "subscriber_mode")]
		public bool SubscriberMode { get; protected set; }

		[JsonProperty(PropertyName = "emote_mode")]
		public bool EmoteMode { get; protected set; }

		[JsonProperty(PropertyName = "unique_chat_mode")]
		public bool UniqueChatMode { get; protected set; }

		[JsonProperty(PropertyName = "non_moderator_chat_delay")]
		public bool NonModeratorChatDelay { get; protected set; }

		[JsonProperty(PropertyName = "non_moderator_chat_delay_duration")]
		public int? NonModeratorChatDelayDuration { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Badges
{
	public class BadgeEmoteSet
	{
		[JsonProperty(PropertyName = "set_id")]
		public string SetId { get; protected set; }

		[JsonProperty(PropertyName = "versions")]
		public BadgeVersion[] Versions { get; protected set; }
	}
	public class BadgeVersion
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "image_url_1x")]
		public string ImageUrl1x { get; protected set; }

		[JsonProperty(PropertyName = "image_url_2x")]
		public string ImageUrl2x { get; protected set; }

		[JsonProperty(PropertyName = "image_url_4x")]
		public string ImageUrl4x { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Badges.GetGlobalChatBadges
{
	public class GetGlobalChatBadgesResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BadgeEmoteSet[] EmoteSet { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Chat.Badges.GetChannelChatBadges
{
	public class GetChannelChatBadgesResponse
	{
		[JsonProperty(PropertyName = "data")]
		public BadgeEmoteSet[] EmoteSet { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Charity.GetCharityCampaign
{
	public class Amount
	{
		[JsonProperty(PropertyName = "value")]
		public int? Value { get; protected set; }

		[JsonProperty(PropertyName = "decimal_places")]
		public int? DecimalPlaces { get; protected set; }

		[JsonProperty(PropertyName = "currency")]
		public string Currency { get; protected set; }
	}
	public class CharityCampaignResponseModel
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "charity_name")]
		public string CharityName { get; protected set; }

		[JsonProperty(PropertyName = "charity_description")]
		public string CharityDescription { get; protected set; }

		[JsonProperty(PropertyName = "charity_logo")]
		public string CharityLogo { get; protected set; }

		[JsonProperty(PropertyName = "charity_website")]
		public string CharityWebsite { get; protected set; }

		[JsonProperty(PropertyName = "current_amount")]
		public Amount CurrentAmount { get; protected set; }

		[JsonProperty(PropertyName = "target_amount")]
		public Amount TargetAmount { get; protected set; }
	}
	public class GetCharityCampaignResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CharityCampaignResponseModel[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Channels.ModifyChannelInformation
{
	[JsonObject(/*Could not decode attribute arguments.*/)]
	public class ModifyChannelInformationRequest
	{
		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string GameId { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string Title { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string BroadcasterLanguage { get; set; }

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int? Delay { get; set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Channels.GetChannelVIPs
{
	public class ChannelVIPsResponseModel
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }
	}
	public class GetChannelVIPsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ChannelVIPsResponseModel[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Channels.GetChannelInformation
{
	public class ChannelInformation
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_language")]
		public string BroadcasterLanguage { get; protected set; }

		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "game_name")]
		public string GameName { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "delay")]
		public int Delay { get; protected set; }
	}
	public class GetChannelInformationResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ChannelInformation[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Channels.GetChannelEditors
{
	public class ChannelEditor
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "created_at")]
		public DateTime CreatedAt { get; protected set; }
	}
	public class GetChannelEditorsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ChannelEditor[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints
{
	public class CustomReward
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "prompt")]
		public string Prompt { get; protected set; }

		[JsonProperty(PropertyName = "cost")]
		public int Cost { get; protected set; }

		[JsonProperty(PropertyName = "image")]
		public Image Image { get; protected set; }

		[JsonProperty(PropertyName = "default_image")]
		public DefaultImage DefaultImage { get; protected set; }

		[JsonProperty(PropertyName = "background_color")]
		public string BackgroundColor { get; protected set; }

		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "is_user_input_required")]
		public bool IsUserInputRequired { get; protected set; }

		[JsonProperty(PropertyName = "max_per_stream_setting")]
		public MaxPerStreamSetting MaxPerStreamSetting { get; protected set; }

		[JsonProperty(PropertyName = "max_per_user_per_stream_setting")]
		public MaxPerUserPerStreamSetting MaxPerUserPerStreamSetting { get; protected set; }

		[JsonProperty(PropertyName = "global_cooldown_setting")]
		public GlobalCooldownSetting GlobalCooldownSetting { get; protected set; }

		[JsonProperty(PropertyName = "is_paused")]
		public bool IsPaused { get; protected set; }

		[JsonProperty(PropertyName = "is_in_stock")]
		public bool IsInStock { get; protected set; }

		[JsonProperty(PropertyName = "should_redemptions_skip_request_queue")]
		public bool ShouldRedemptionsSkipQueue { get; protected set; }

		[JsonProperty(PropertyName = "redemptions_redeemed_current_stream")]
		public int? RedemptionsRedeemedCurrentStream { get; protected set; }

		[JsonProperty(PropertyName = "cooldown_expires_at")]
		public string CooldownExpiresAt { get; protected set; }
	}
	public class DefaultImage
	{
		[JsonProperty(PropertyName = "url_1x")]
		public string Url1x { get; }

		[JsonProperty(PropertyName = "url_2x")]
		public string Url2x { get; }

		[JsonProperty(PropertyName = "url_4x")]
		public string Url4x { get; }
	}
	public class GlobalCooldownSetting
	{
		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "global_cooldown_seconds")]
		public int GlobalCooldownSeconds { get; protected set; }
	}
	public class Image
	{
		[JsonProperty(PropertyName = "url_1x")]
		public string Url1x { get; protected set; }

		[JsonProperty(PropertyName = "url_2x")]
		public string Url2x { get; protected set; }

		[JsonProperty(PropertyName = "url_4x")]
		public string Url4x { get; protected set; }
	}
	public class MaxPerStreamSetting
	{
		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "max_per_stream")]
		public int MaxPerStream { get; protected set; }
	}
	public class MaxPerUserPerStreamSetting
	{
		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "max_per_user_per_stream")]
		public int MaxPerUserPerStream { get; protected set; }
	}
	public class Reward
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "prompt")]
		public string Prompt { get; protected set; }

		[JsonProperty(PropertyName = "cost")]
		public int Cost { get; protected set; }
	}
	public class RewardRedemption
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_login")]
		public string BroadcasterLogin { get; protected set; }

		[JsonProperty(PropertyName = "broadcaster_name")]
		public string BroadcasterName { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "user_input")]
		public string UserInput { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public CustomRewardRedemptionStatus Status { get; protected set; }

		[JsonProperty(PropertyName = "redeemed_at")]
		public DateTime RedeemedAt { get; protected set; }

		[JsonProperty(PropertyName = "reward")]
		public Reward Reward { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints.UpdateRedemptionStatus
{
	public class UpdateRedemptionStatusResponse
	{
		[JsonProperty(PropertyName = "data")]
		public RewardRedemption[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints.UpdateCustomRewardRedemptionStatus
{
	public class UpdateCustomRewardRedemptionStatusRequest
	{
		[JsonConverter(typeof(StringEnumConverter))]
		[JsonProperty(PropertyName = "status")]
		public CustomRewardRedemptionStatus Status { get; set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints.UpdateCustomReward
{
	[JsonObject(/*Could not decode attribute arguments.*/)]
	public class UpdateCustomRewardRequest
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; set; }

		[JsonProperty(PropertyName = "prompt")]
		public string Prompt { get; set; }

		[JsonProperty(PropertyName = "cost")]
		public int? Cost { get; set; }

		[JsonProperty(PropertyName = "is_enabled")]
		public bool? IsEnabled { get; set; }

		[JsonProperty(PropertyName = "background_color")]
		public string BackgroundColor { get; set; }

		[JsonProperty(PropertyName = "is_user_input_required")]
		public bool? IsUserInputRequired { get; set; }

		[JsonProperty(PropertyName = "is_max_per_stream_enabled")]
		public bool? IsMaxPerStreamEnabled { get; set; }

		[JsonProperty(PropertyName = "max_per_stream")]
		public int? MaxPerStream { get; set; }

		[JsonProperty(PropertyName = "is_max_per_user_per_stream_enabled")]
		public bool? IsMaxPerUserPerStreamEnabled { get; set; }

		[JsonProperty(PropertyName = "max_per_user_per_stream")]
		public int? MaxPerUserPerStream { get; set; }

		[JsonProperty(PropertyName = "is_global_cooldown_enabled")]
		public bool? IsGlobalCooldownEnabled { get; set; }

		[JsonProperty(PropertyName = "global_cooldown_seconds")]
		public int? GlobalCooldownSeconds { get; set; }

		[JsonProperty(PropertyName = "is_paused")]
		public bool? IsPaused { get; set; }

		[JsonProperty(PropertyName = "should_redemptions_skip_request_queue")]
		public bool? ShouldRedemptionsSkipRequestQueue { get; set; }
	}
	public class UpdateCustomRewardResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CustomReward[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints.GetCustomRewardRedemption
{
	public class GetCustomRewardRedemptionResponse
	{
		[JsonProperty(PropertyName = "data")]
		public RewardRedemption[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints.GetCustomReward
{
	public class GetCustomRewardsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CustomReward[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.ChannelPoints.CreateCustomReward
{
	public class CreateCustomRewardsRequest
	{
		[JsonProperty(PropertyName = "title")]
		public string Title { get; set; }

		[JsonProperty(PropertyName = "prompt")]
		public string Prompt { get; set; }

		[JsonProperty(PropertyName = "cost")]
		public int Cost { get; set; }

		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; set; }

		[JsonProperty(PropertyName = "background_color")]
		public string BackgroundColor { get; set; }

		[JsonProperty(PropertyName = "is_user_input_required")]
		public bool IsUserInputRequired { get; set; }

		[JsonProperty(PropertyName = "is_max_per_stream-Enabled")]
		public bool IsMaxPerStreamEnabled { get; set; }

		[JsonProperty(PropertyName = "max_per_stream")]
		public int? MaxPerStream { get; set; }

		[JsonProperty(PropertyName = "is_max_per_user_per_stream_enabled")]
		public bool IsMaxPerUserPerStreamEnabled { get; set; }

		[JsonProperty(PropertyName = "max_per_user_per_stream")]
		public int? MaxPerUserPerStream { get; set; }

		[JsonProperty(PropertyName = "is_global_cooldown_enabled")]
		public bool IsGlobalCooldownEnabled { get; set; }

		[JsonProperty(PropertyName = "global_cooldown_seconds")]
		public int? GlobalCooldownSeconds { get; set; }

		[JsonProperty(PropertyName = "should_redemptions_skip_request_queue")]
		public bool ShouldRedemptionsSkipRequestQueue { get; set; }
	}
	public class CreateCustomRewardsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public CustomReward[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Bits
{
	public class Cheermote
	{
		[JsonProperty(PropertyName = "prefix")]
		public string Prefix { get; protected set; }

		[JsonProperty(PropertyName = "tiers")]
		public Tier[] Tiers { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "order")]
		public int Order { get; protected set; }

		[JsonProperty(PropertyName = "last_updated")]
		public DateTime LastUpdated { get; protected set; }

		[JsonProperty(PropertyName = "is_charitable")]
		public bool IsCharitable { get; protected set; }
	}
	public class DateRange
	{
		[JsonProperty(PropertyName = "started_at")]
		public DateTime StartedAt { get; protected set; }

		[JsonProperty(PropertyName = "ended_at")]
		public DateTime EndedAt { get; protected set; }
	}
	public class GetBitsLeaderboardResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Listing[] Listings { get; protected set; }

		[JsonProperty(PropertyName = "date_range")]
		public DateRange DateRange { get; protected set; }

		[JsonProperty(PropertyName = "total")]
		public int Total { get; protected set; }
	}
	public class GetCheermotesResponse
	{
		[JsonProperty(PropertyName = "data")]
		public Cheermote[] Listings { get; protected set; }
	}
	public class ImageList
	{
		[JsonProperty(PropertyName = "animated")]
		public Dictionary<string, string> Animated { get; protected set; }

		[JsonProperty(PropertyName = "static")]
		public Dictionary<string, string> Static { get; protected set; }
	}
	public class Images
	{
		[JsonProperty(PropertyName = "dark")]
		public ImageList Dark { get; protected set; }

		[JsonProperty(PropertyName = "light")]
		public ImageList Light { get; protected set; }
	}
	public class Listing
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "user_login")]
		public string UserLogin { get; protected set; }

		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "rank")]
		public int Rank { get; protected set; }

		[JsonProperty(PropertyName = "score")]
		public int Score { get; protected set; }
	}
	public class Tier
	{
		[JsonProperty(PropertyName = "min_bits")]
		public int MinBits { get; protected set; }

		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "color")]
		public string Color { get; protected set; }

		[JsonProperty(PropertyName = "images")]
		public Images Images { get; protected set; }

		[JsonProperty(PropertyName = "can_cheer")]
		public bool CanCheer { get; protected set; }

		[JsonProperty(PropertyName = "show_in_bits_card")]
		public bool ShowInBitsCard { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Bits.ExtensionBitsProducts
{
	public class Cost
	{
		[JsonProperty(PropertyName = "amount")]
		public int Amount { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }
	}
	public class ExtensionBitsProduct
	{
		[JsonProperty(PropertyName = "sku")]
		public string Sku { get; protected set; }

		[JsonProperty(PropertyName = "cost")]
		public Cost Cost { get; protected set; }

		[JsonProperty(PropertyName = "in_development")]
		public bool InDevelopment { get; protected set; }

		[JsonProperty(PropertyName = "display_name")]
		public string DisplayName { get; protected set; }

		[JsonProperty(PropertyName = "expiration")]
		public DateTime Expiration { get; protected set; }

		[JsonProperty(PropertyName = "is_broadcast")]
		public bool IsBroadcast { get; protected set; }
	}
	public class GetExtensionBitsProductsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ExtensionBitsProduct[] Data { get; protected set; }
	}
	public class UpdateExtensionBitsProductResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ExtensionBitsProduct[] Data { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Analytics
{
	public class ExtensionAnalytics
	{
		[JsonProperty(PropertyName = "extension_id")]
		public string ExtensionId { get; protected set; }

		[JsonProperty(PropertyName = "URL")]
		public string Url { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "date_range")]
		public DateRange DateRange { get; protected set; }
	}
	public class GameAnalytics
	{
		[JsonProperty(PropertyName = "game_id")]
		public string GameId { get; protected set; }

		[JsonProperty(PropertyName = "URL")]
		public string Url { get; protected set; }

		[JsonProperty(PropertyName = "type")]
		public string Type { get; protected set; }

		[JsonProperty(PropertyName = "date_range")]
		public DateRange DateRange { get; protected set; }
	}
	public class GetExtensionAnalyticsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public ExtensionAnalytics[] Data { get; protected set; }
	}
	public class GetGameAnalyticsResponse
	{
		[JsonProperty(PropertyName = "data")]
		public GameAnalytics[] Data { get; protected set; }

		[JsonProperty(PropertyName = "pagination")]
		public Pagination Pagination { get; protected set; }
	}
}
namespace TwitchLib.Api.Helix.Models.Ads
{
	public class StartCommercialRequest
	{
		[JsonProperty(PropertyName = "broadcaster_id")]
		public string BroadcasterId { get; set; }

		[JsonProperty(PropertyName = "length")]
		public int Length { get; set; }
	}
	public class StartCommercialResponse
	{
		[JsonProperty(PropertyName = "length")]
		public int Length { get; protected set; }

		[JsonProperty(PropertyName = "message")]
		public string Message { get; protected set; }

		[JsonProperty(PropertyName = "retry_after")]
		public int RetryAfter { get; protected set; }
	}
}

plugins/TwitchLib/TwitchLib.Client.dll

Decompiled 6 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using Microsoft.Extensions.Logging;
using TwitchLib.Client.Enums;
using TwitchLib.Client.Enums.Internal;
using TwitchLib.Client.Events;
using TwitchLib.Client.Exceptions;
using TwitchLib.Client.Interfaces;
using TwitchLib.Client.Internal;
using TwitchLib.Client.Internal.Parsing;
using TwitchLib.Client.Manager;
using TwitchLib.Client.Models;
using TwitchLib.Client.Models.Internal;
using TwitchLib.Communication.Clients;
using TwitchLib.Communication.Events;
using TwitchLib.Communication.Interfaces;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Client component of TwitchLib. This component allows you to access Twitch chat and whispers, as well as the events that are sent over this connection.")]
[assembly: AssemblyFileVersion("3.3.1")]
[assembly: AssemblyInformationalVersion("3.3.1")]
[assembly: AssemblyProduct("TwitchLib.Client")]
[assembly: AssemblyTitle("TwitchLib.Client")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.Client")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.3.1.0")]
namespace TwitchLib.Client
{
	public class TwitchClient : ITwitchClient
	{
		private IClient _client;

		private MessageEmoteCollection _channelEmotes = new MessageEmoteCollection();

		private readonly ICollection<char> _chatCommandIdentifiers = new HashSet<char>();

		private readonly ICollection<char> _whisperCommandIdentifiers = new HashSet<char>();

		private readonly Queue<JoinedChannel> _joinChannelQueue = new Queue<JoinedChannel>();

		private readonly ILogger<TwitchClient> _logger;

		private readonly ClientProtocol _protocol;

		private bool _currentlyJoiningChannels;

		private Timer _joinTimer;

		private List<KeyValuePair<string, DateTime>> _awaitingJoins;

		private readonly IrcParser _ircParser;

		private readonly JoinedChannelManager _joinedChannelManager;

		private readonly List<string> _hasSeenJoinedChannels = new List<string>();

		private string _lastMessageSent;

		public Version Version => Assembly.GetEntryAssembly().GetName().Version;

		public bool IsInitialized => _client != null;

		public IReadOnlyList<JoinedChannel> JoinedChannels => _joinedChannelManager.GetJoinedChannels();

		public string TwitchUsername { get; private set; }

		public WhisperMessage PreviousWhisper { get; private set; }

		public bool IsConnected
		{
			get
			{
				if (!IsInitialized || _client == null)
				{
					return false;
				}
				return _client.IsConnected;
			}
		}

		public MessageEmoteCollection ChannelEmotes => _channelEmotes;

		public bool DisableAutoPong { get; set; }

		public bool WillReplaceEmotes { get; set; }

		public ConnectionCredentials ConnectionCredentials { get; private set; }

		public bool AutoReListenOnException { get; set; }

		public event EventHandler<OnAnnouncementArgs> OnAnnouncement;

		public event EventHandler<OnVIPsReceivedArgs> OnVIPsReceived;

		public event EventHandler<OnLogArgs> OnLog;

		public event EventHandler<OnConnectedArgs> OnConnected;

		public event EventHandler<OnJoinedChannelArgs> OnJoinedChannel;

		public event EventHandler<OnIncorrectLoginArgs> OnIncorrectLogin;

		public event EventHandler<OnChannelStateChangedArgs> OnChannelStateChanged;

		public event EventHandler<OnUserStateChangedArgs> OnUserStateChanged;

		public event EventHandler<OnMessageReceivedArgs> OnMessageReceived;

		public event EventHandler<OnWhisperReceivedArgs> OnWhisperReceived;

		public event EventHandler<OnMessageSentArgs> OnMessageSent;

		public event EventHandler<OnWhisperSentArgs> OnWhisperSent;

		public event EventHandler<OnChatCommandReceivedArgs> OnChatCommandReceived;

		public event EventHandler<OnWhisperCommandReceivedArgs> OnWhisperCommandReceived;

		public event EventHandler<OnUserJoinedArgs> OnUserJoined;

		public event EventHandler<OnModeratorJoinedArgs> OnModeratorJoined;

		public event EventHandler<OnModeratorLeftArgs> OnModeratorLeft;

		public event EventHandler<OnMessageClearedArgs> OnMessageCleared;

		public event EventHandler<OnNewSubscriberArgs> OnNewSubscriber;

		public event EventHandler<OnReSubscriberArgs> OnReSubscriber;

		public event EventHandler<OnPrimePaidSubscriberArgs> OnPrimePaidSubscriber;

		public event EventHandler<OnExistingUsersDetectedArgs> OnExistingUsersDetected;

		public event EventHandler<OnUserLeftArgs> OnUserLeft;

		public event EventHandler<OnDisconnectedEventArgs> OnDisconnected;

		public event EventHandler<OnConnectionErrorArgs> OnConnectionError;

		public event EventHandler<OnChatClearedArgs> OnChatCleared;

		public event EventHandler<OnUserTimedoutArgs> OnUserTimedout;

		public event EventHandler<OnLeftChannelArgs> OnLeftChannel;

		public event EventHandler<OnUserBannedArgs> OnUserBanned;

		public event EventHandler<OnModeratorsReceivedArgs> OnModeratorsReceived;

		public event EventHandler<OnChatColorChangedArgs> OnChatColorChanged;

		public event EventHandler<OnSendReceiveDataArgs> OnSendReceiveData;

		public event EventHandler<OnRaidNotificationArgs> OnRaidNotification;

		public event EventHandler<OnGiftedSubscriptionArgs> OnGiftedSubscription;

		public event EventHandler<OnCommunitySubscriptionArgs> OnCommunitySubscription;

		public event EventHandler<OnContinuedGiftedSubscriptionArgs> OnContinuedGiftedSubscription;

		public event EventHandler<OnMessageThrottledEventArgs> OnMessageThrottled;

		public event EventHandler<OnWhisperThrottledEventArgs> OnWhisperThrottled;

		public event EventHandler<OnErrorEventArgs> OnError;

		public event EventHandler<OnReconnectedEventArgs> OnReconnected;

		public event EventHandler<OnRequiresVerifiedEmailArgs> OnRequiresVerifiedEmail;

		public event EventHandler<OnRequiresVerifiedPhoneNumberArgs> OnRequiresVerifiedPhoneNumber;

		public event EventHandler<OnRateLimitArgs> OnRateLimit;

		public event EventHandler<OnDuplicateArgs> OnDuplicate;

		public event EventHandler<OnBannedEmailAliasArgs> OnBannedEmailAlias;

		public event EventHandler OnSelfRaidError;

		public event EventHandler OnNoPermissionError;

		public event EventHandler OnRaidedChannelIsMatureAudience;

		public event EventHandler<OnFailureToReceiveJoinConfirmationArgs> OnFailureToReceiveJoinConfirmation;

		public event EventHandler<OnFollowersOnlyArgs> OnFollowersOnly;

		public event EventHandler<OnSubsOnlyArgs> OnSubsOnly;

		public event EventHandler<OnEmoteOnlyArgs> OnEmoteOnly;

		public event EventHandler<OnSuspendedArgs> OnSuspended;

		public event EventHandler<OnBannedArgs> OnBanned;

		public event EventHandler<OnSlowModeArgs> OnSlowMode;

		public event EventHandler<OnR9kModeArgs> OnR9kMode;

		public event EventHandler<OnUserIntroArgs> OnUserIntro;

		public event EventHandler<OnUnaccountedForArgs> OnUnaccountedFor;

		public TwitchClient(IClient client = null, ClientProtocol protocol = 1, ILogger<TwitchClient> logger = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			_logger = logger;
			_client = client;
			_protocol = protocol;
			_joinedChannelManager = new JoinedChannelManager();
			_ircParser = new IrcParser();
		}

		public void Initialize(ConnectionCredentials credentials, string channel = null, char chatCommandIdentifier = '!', char whisperCommandIdentifier = '!', bool autoReListenOnExceptions = true)
		{
			if (channel != null && channel[0] == '#')
			{
				channel = channel.Substring(1);
			}
			initializeHelper(credentials, new List<string> { channel }, chatCommandIdentifier, whisperCommandIdentifier, autoReListenOnExceptions);
		}

		public void Initialize(ConnectionCredentials credentials, List<string> channels, char chatCommandIdentifier = '!', char whisperCommandIdentifier = '!', bool autoReListenOnExceptions = true)
		{
			channels = channels.Select((string x) => (x[0] != '#') ? x : x.Substring(1)).ToList();
			initializeHelper(credentials, channels, chatCommandIdentifier, whisperCommandIdentifier, autoReListenOnExceptions);
		}

		private void initializeHelper(ConnectionCredentials credentials, List<string> channels, char chatCommandIdentifier = '!', char whisperCommandIdentifier = '!', bool autoReListenOnExceptions = true)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			Log($"TwitchLib-TwitchClient initialized, assembly version: {Assembly.GetExecutingAssembly().GetName().Version}");
			ConnectionCredentials = credentials;
			TwitchUsername = ConnectionCredentials.TwitchUsername;
			if (chatCommandIdentifier != 0)
			{
				_chatCommandIdentifiers.Add(chatCommandIdentifier);
			}
			if (whisperCommandIdentifier != 0)
			{
				_whisperCommandIdentifiers.Add(whisperCommandIdentifier);
			}
			AutoReListenOnException = autoReListenOnExceptions;
			if (channels != null && channels.Count > 0)
			{
				int i;
				for (i = 0; i < channels.Count; i++)
				{
					if (!string.IsNullOrEmpty(channels[i]))
					{
						if (((IEnumerable<JoinedChannel>)JoinedChannels).FirstOrDefault((Func<JoinedChannel, bool>)((JoinedChannel x) => x.Channel.ToLower() == channels[i])) != null)
						{
							return;
						}
						_joinChannelQueue.Enqueue(new JoinedChannel(channels[i]));
					}
				}
			}
			InitializeClient();
		}

		private void InitializeClient()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if (_client == null)
			{
				ClientProtocol protocol = _protocol;
				if ((int)protocol != 0)
				{
					if ((int)protocol == 1)
					{
						_client = (IClient)new WebSocketClient((IClientOptions)null);
					}
				}
				else
				{
					_client = (IClient)new TcpClient((IClientOptions)null);
				}
			}
			_client.OnConnected += _client_OnConnected;
			_client.OnMessage += _client_OnMessage;
			_client.OnDisconnected += _client_OnDisconnected;
			_client.OnFatality += _client_OnFatality;
			_client.OnMessageThrottled += _client_OnMessageThrottled;
			_client.OnWhisperThrottled += _client_OnWhisperThrottled;
			_client.OnReconnected += _client_OnReconnected;
		}

		internal void RaiseEvent(string eventName, object args = null)
		{
			Delegate[] invocationList = (GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this) as MulticastDelegate).GetInvocationList();
			foreach (Delegate @delegate in invocationList)
			{
				@delegate.Method.Invoke(@delegate.Target, (args == null) ? new object[2]
				{
					this,
					new EventArgs()
				} : new object[2] { this, args });
			}
		}

		public void SendRaw(string message)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			Log("Writing: " + message);
			_client.Send(message);
			this.OnSendReceiveData?.Invoke(this, new OnSendReceiveDataArgs
			{
				Direction = (SendReceiveDirection)0,
				Data = message
			});
		}

		private void SendTwitchMessage(JoinedChannel channel, string message, string replyToId = null, bool dryRun = false)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			if (channel == null || message == null || dryRun)
			{
				return;
			}
			if (message.Length > 500)
			{
				LogError("Message length has exceeded the maximum character count. (500)");
				return;
			}
			OutboundChatMessage val = new OutboundChatMessage
			{
				Channel = channel.Channel,
				Username = ConnectionCredentials.TwitchUsername,
				Message = message
			};
			if (replyToId != null)
			{
				val.ReplyToId = replyToId;
			}
			_lastMessageSent = message;
			_client.Send(((object)val).ToString());
		}

		public void SendMessage(JoinedChannel channel, string message, bool dryRun = false)
		{
			SendTwitchMessage(channel, message, null, dryRun);
		}

		public void SendMessage(string channel, string message, bool dryRun = false)
		{
			SendMessage(GetJoinedChannel(channel), message, dryRun);
		}

		public void SendReply(JoinedChannel channel, string replyToId, string message, bool dryRun = false)
		{
			SendTwitchMessage(channel, message, replyToId, dryRun);
		}

		public void SendReply(string channel, string replyToId, string message, bool dryRun = false)
		{
			SendReply(GetJoinedChannel(channel), replyToId, message, dryRun);
		}

		public void SendWhisper(string receiver, string message, bool dryRun = false)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			if (!dryRun)
			{
				OutboundWhisperMessage val = new OutboundWhisperMessage
				{
					Receiver = receiver,
					Username = ConnectionCredentials.TwitchUsername,
					Message = message
				};
				_client.SendWhisper(((object)val).ToString());
				this.OnWhisperSent?.Invoke(this, new OnWhisperSentArgs
				{
					Receiver = receiver,
					Message = message
				});
			}
		}

		public bool Connect()
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			Log("Connecting to: " + ConnectionCredentials.TwitchWebsocketURI);
			_joinedChannelManager.Clear();
			if (_client.Open())
			{
				Log("Should be connected!");
				return true;
			}
			return false;
		}

		public void Disconnect()
		{
			Log("Disconnect Twitch Chat Client...");
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			_client.Close(true);
			_joinedChannelManager.Clear();
			PreviousWhisper = null;
		}

		public void Reconnect()
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			Log("Reconnecting to Twitch");
			_client.Reconnect();
		}

		public void AddChatCommandIdentifier(char identifier)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			_chatCommandIdentifiers.Add(identifier);
		}

		public void RemoveChatCommandIdentifier(char identifier)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			_chatCommandIdentifiers.Remove(identifier);
		}

		public void AddWhisperCommandIdentifier(char identifier)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			_whisperCommandIdentifiers.Add(identifier);
		}

		public void RemoveWhisperCommandIdentifier(char identifier)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			_whisperCommandIdentifiers.Remove(identifier);
		}

		public void SetConnectionCredentials(ConnectionCredentials credentials)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			if (IsConnected)
			{
				throw new IllegalAssignmentException("While the client is connected, you are unable to change the connection credentials. Please disconnect first and then change them.");
			}
			ConnectionCredentials = credentials;
		}

		public void JoinChannel(string channel, bool overrideCheck = false)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			if (!IsConnected)
			{
				HandleNotConnected();
			}
			if (((IEnumerable<JoinedChannel>)JoinedChannels).FirstOrDefault((Func<JoinedChannel, bool>)((JoinedChannel x) => x.Channel.ToLower() == channel && !overrideCheck)) == null)
			{
				if (channel[0] == '#')
				{
					channel = channel.Substring(1);
				}
				_joinChannelQueue.Enqueue(new JoinedChannel(channel));
				if (!_currentlyJoiningChannels)
				{
					QueueingJoinCheck();
				}
			}
		}

		public JoinedChannel GetJoinedChannel(string channel)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			if (JoinedChannels.Count == 0)
			{
				throw new BadStateException("Must be connected to at least one channel.");
			}
			if (channel[0] == '#')
			{
				channel = channel.Substring(1);
			}
			return _joinedChannelManager.GetJoinedChannel(channel);
		}

		public void LeaveChannel(string channel)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			channel = channel.ToLower();
			if (channel[0] == '#')
			{
				channel = channel.Substring(1);
			}
			Log("Leaving channel: " + channel);
			if (_joinedChannelManager.GetJoinedChannel(channel) != null)
			{
				_client.Send(Rfc2812.Part("#" + channel));
			}
		}

		public void LeaveChannel(JoinedChannel channel)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			LeaveChannel(channel.Channel);
		}

		public void OnReadLineTest(string rawIrc)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			HandleIrcMessage(_ircParser.ParseIrcMessage(rawIrc));
		}

		private void _client_OnWhisperThrottled(object sender, OnWhisperThrottledEventArgs e)
		{
			this.OnWhisperThrottled?.Invoke(sender, e);
		}

		private void _client_OnMessageThrottled(object sender, OnMessageThrottledEventArgs e)
		{
			this.OnMessageThrottled?.Invoke(sender, e);
		}

		private void _client_OnFatality(object sender, OnFatalErrorEventArgs e)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			this.OnConnectionError?.Invoke(this, new OnConnectionErrorArgs
			{
				BotUsername = TwitchUsername,
				Error = new ErrorEvent
				{
					Message = e.Reason
				}
			});
		}

		private void _client_OnDisconnected(object sender, OnDisconnectedEventArgs e)
		{
			this.OnDisconnected?.Invoke(sender, e);
		}

		private void _client_OnReconnected(object sender, OnReconnectedEventArgs e)
		{
			foreach (JoinedChannel joinedChannel in _joinedChannelManager.GetJoinedChannels())
			{
				if (!string.Equals(joinedChannel.Channel, TwitchUsername, StringComparison.CurrentCultureIgnoreCase))
				{
					_joinChannelQueue.Enqueue(joinedChannel);
				}
			}
			_joinedChannelManager.Clear();
			this.OnReconnected?.Invoke(sender, e);
		}

		private void _client_OnMessage(object sender, OnMessageEventArgs e)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			string[] separator = new string[1] { "\r\n" };
			string[] array = e.Message.Split(separator, StringSplitOptions.None);
			foreach (string text in array)
			{
				if (text.Length > 1)
				{
					Log("Received: " + text);
					this.OnSendReceiveData?.Invoke(this, new OnSendReceiveDataArgs
					{
						Direction = (SendReceiveDirection)1,
						Data = text
					});
					HandleIrcMessage(_ircParser.ParseIrcMessage(text));
				}
			}
		}

		private void _client_OnConnected(object sender, object e)
		{
			_client.Send(Rfc2812.Pass(ConnectionCredentials.TwitchOAuth));
			_client.Send(Rfc2812.Nick(ConnectionCredentials.TwitchUsername));
			_client.Send(Rfc2812.User(ConnectionCredentials.TwitchUsername, 0, ConnectionCredentials.TwitchUsername));
			if (ConnectionCredentials.Capabilities.Membership)
			{
				_client.Send("CAP REQ twitch.tv/membership");
			}
			if (ConnectionCredentials.Capabilities.Commands)
			{
				_client.Send("CAP REQ twitch.tv/commands");
			}
			if (ConnectionCredentials.Capabilities.Tags)
			{
				_client.Send("CAP REQ twitch.tv/tags");
			}
			if (_joinChannelQueue != null && _joinChannelQueue.Count > 0)
			{
				QueueingJoinCheck();
			}
		}

		private void QueueingJoinCheck()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (_joinChannelQueue.Count > 0)
			{
				_currentlyJoiningChannels = true;
				JoinedChannel val = _joinChannelQueue.Dequeue();
				Log("Joining channel: " + val.Channel);
				_client.Send(Rfc2812.Join("#" + val.Channel.ToLower()));
				_joinedChannelManager.AddJoinedChannel(new JoinedChannel(val.Channel));
				StartJoinedChannelTimer(val.Channel);
			}
			else
			{
				Log("Finished channel joining queue.");
			}
		}

		private void StartJoinedChannelTimer(string channel)
		{
			if (_joinTimer == null)
			{
				_joinTimer = new Timer(1000.0);
				_joinTimer.Elapsed += JoinChannelTimeout;
				_awaitingJoins = new List<KeyValuePair<string, DateTime>>();
			}
			_awaitingJoins.Add(new KeyValuePair<string, DateTime>(channel.ToLower(), DateTime.Now));
			if (!_joinTimer.Enabled)
			{
				_joinTimer.Start();
			}
		}

		private void JoinChannelTimeout(object sender, ElapsedEventArgs e)
		{
			if (_awaitingJoins.Any())
			{
				List<KeyValuePair<string, DateTime>> list = _awaitingJoins.Where((KeyValuePair<string, DateTime> x) => (DateTime.Now - x.Value).TotalSeconds > 5.0).ToList();
				if (!list.Any())
				{
					return;
				}
				_awaitingJoins.RemoveAll((KeyValuePair<string, DateTime> x) => (DateTime.Now - x.Value).TotalSeconds > 5.0);
				{
					foreach (KeyValuePair<string, DateTime> item in list)
					{
						_joinedChannelManager.RemoveJoinedChannel(item.Key.ToLowerInvariant());
						this.OnFailureToReceiveJoinConfirmation?.Invoke(this, new OnFailureToReceiveJoinConfirmationArgs
						{
							Exception = new FailureToReceiveJoinConfirmationException(item.Key)
						});
					}
					return;
				}
			}
			_joinTimer.Stop();
			_currentlyJoiningChannels = false;
			QueueingJoinCheck();
		}

		private void HandleIrcMessage(IrcMessage ircMessage)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected I4, but got Unknown
			if (ircMessage.Message.Contains("Login authentication failed"))
			{
				this.OnIncorrectLogin?.Invoke(this, new OnIncorrectLoginArgs
				{
					Exception = new ErrorLoggingInException(ircMessage.ToString(), TwitchUsername)
				});
				return;
			}
			IrcCommand command = ircMessage.Command;
			switch ((int)command)
			{
			case 1:
				HandlePrivMsg(ircMessage);
				break;
			case 2:
				HandleNotice(ircMessage);
				break;
			case 3:
				if (!DisableAutoPong)
				{
					SendRaw("PONG");
				}
				break;
			case 4:
				break;
			case 5:
				HandleJoin(ircMessage);
				break;
			case 6:
				HandlePart(ircMessage);
				break;
			case 7:
				HandleClearChat(ircMessage);
				break;
			case 8:
				HandleClearMsg(ircMessage);
				break;
			case 9:
				HandleUserState(ircMessage);
				break;
			case 17:
				Handle004();
				break;
			case 18:
				Handle353(ircMessage);
				break;
			case 19:
				Handle366();
				break;
			case 23:
				HandleWhisper(ircMessage);
				break;
			case 24:
				HandleRoomState(ircMessage);
				break;
			case 25:
				Reconnect();
				break;
			case 27:
				HandleUserNotice(ircMessage);
				break;
			case 28:
				HandleMode(ircMessage);
				break;
			case 13:
				HandleCap(ircMessage);
				break;
			default:
				this.OnUnaccountedFor?.Invoke(this, new OnUnaccountedForArgs
				{
					BotUsername = TwitchUsername,
					Channel = null,
					Location = "HandleIrcMessage",
					RawIRC = ircMessage.ToString()
				});
				UnaccountedFor(ircMessage.ToString());
				break;
			case 10:
			case 14:
			case 15:
			case 16:
			case 20:
			case 21:
			case 22:
				break;
			}
		}

		private void HandlePrivMsg(IrcMessage ircMessage)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			ChatMessage val = new ChatMessage(TwitchUsername, ircMessage, ref _channelEmotes, WillReplaceEmotes);
			foreach (JoinedChannel item in JoinedChannels.Where((JoinedChannel x) => string.Equals(x.Channel, ircMessage.Channel, StringComparison.InvariantCultureIgnoreCase)))
			{
				item.HandleMessage(val);
			}
			this.OnMessageReceived?.Invoke(this, new OnMessageReceivedArgs
			{
				ChatMessage = val
			});
			if (ircMessage.Tags.TryGetValue("msg-id", out var value) && value == "user-intro")
			{
				this.OnUserIntro?.Invoke(this, new OnUserIntroArgs
				{
					ChatMessage = val
				});
			}
			if (_chatCommandIdentifiers != null && _chatCommandIdentifiers.Count != 0 && !string.IsNullOrEmpty(val.Message) && _chatCommandIdentifiers.Contains(val.Message[0]))
			{
				ChatCommand command = new ChatCommand(val);
				this.OnChatCommandReceived?.Invoke(this, new OnChatCommandReceivedArgs
				{
					Command = command
				});
			}
		}

		private void HandleNotice(IrcMessage ircMessage)
		{
			if (ircMessage.Message.Contains("Improperly formatted auth"))
			{
				this.OnIncorrectLogin?.Invoke(this, new OnIncorrectLoginArgs
				{
					Exception = new ErrorLoggingInException(ircMessage.ToString(), TwitchUsername)
				});
				return;
			}
			if (!ircMessage.Tags.TryGetValue("msg-id", out var value))
			{
				this.OnUnaccountedFor?.Invoke(this, new OnUnaccountedForArgs
				{
					BotUsername = TwitchUsername,
					Channel = ircMessage.Channel,
					Location = "NoticeHandling",
					RawIRC = ircMessage.ToString()
				});
				UnaccountedFor(ircMessage.ToString());
			}
			switch (value)
			{
			case "color_changed":
				this.OnChatColorChanged?.Invoke(this, new OnChatColorChangedArgs
				{
					Channel = ircMessage.Channel
				});
				break;
			case "room_mods":
				this.OnModeratorsReceived?.Invoke(this, new OnModeratorsReceivedArgs
				{
					Channel = ircMessage.Channel,
					Moderators = ircMessage.Message.Replace(" ", "").Split(new char[1] { ':' })[1].Split(new char[1] { ',' }).ToList()
				});
				break;
			case "no_mods":
				this.OnModeratorsReceived?.Invoke(this, new OnModeratorsReceivedArgs
				{
					Channel = ircMessage.Channel,
					Moderators = new List<string>()
				});
				break;
			case "no_permission":
				this.OnNoPermissionError?.Invoke(this, null);
				break;
			case "raid_error_self":
				this.OnSelfRaidError?.Invoke(this, null);
				break;
			case "raid_notice_mature":
				this.OnRaidedChannelIsMatureAudience?.Invoke(this, null);
				break;
			case "msg_banned_email_alias":
				this.OnBannedEmailAlias?.Invoke(this, new OnBannedEmailAliasArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_channel_suspended":
				_awaitingJoins.RemoveAll((KeyValuePair<string, DateTime> x) => x.Key.ToLower() == ircMessage.Channel);
				_joinedChannelManager.RemoveJoinedChannel(ircMessage.Channel);
				QueueingJoinCheck();
				this.OnFailureToReceiveJoinConfirmation?.Invoke(this, new OnFailureToReceiveJoinConfirmationArgs
				{
					Exception = new FailureToReceiveJoinConfirmationException(ircMessage.Channel, ircMessage.Message)
				});
				break;
			case "msg_requires_verified_phone_number":
				this.OnRequiresVerifiedPhoneNumber?.Invoke(this, new OnRequiresVerifiedPhoneNumberArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_verified_email":
				this.OnRequiresVerifiedEmail?.Invoke(this, new OnRequiresVerifiedEmailArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "no_vips":
				this.OnVIPsReceived?.Invoke(this, new OnVIPsReceivedArgs
				{
					Channel = ircMessage.Channel,
					VIPs = new List<string>()
				});
				break;
			case "vips_success":
				this.OnVIPsReceived?.Invoke(this, new OnVIPsReceivedArgs
				{
					Channel = ircMessage.Channel,
					VIPs = ircMessage.Message.Replace(" ", "").Replace(".", "").Split(new char[1] { ':' })[1].Split(new char[1] { ',' }).ToList()
				});
				break;
			case "msg_ratelimit":
				this.OnRateLimit?.Invoke(this, new OnRateLimitArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_duplicate":
				this.OnDuplicate?.Invoke(this, new OnDuplicateArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_followersonly":
				this.OnFollowersOnly?.Invoke(this, new OnFollowersOnlyArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_subsonly":
				this.OnSubsOnly?.Invoke(this, new OnSubsOnlyArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_emoteonly":
				this.OnEmoteOnly?.Invoke(this, new OnEmoteOnlyArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_suspended":
				this.OnSuspended?.Invoke(this, new OnSuspendedArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_banned":
				this.OnBanned?.Invoke(this, new OnBannedArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_slowmode":
				this.OnSlowMode?.Invoke(this, new OnSlowModeArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			case "msg_r9k":
				this.OnR9kMode?.Invoke(this, new OnR9kModeArgs
				{
					Channel = ircMessage.Channel,
					Message = ircMessage.Message
				});
				break;
			default:
				this.OnUnaccountedFor?.Invoke(this, new OnUnaccountedForArgs
				{
					BotUsername = TwitchUsername,
					Channel = ircMessage.Channel,
					Location = "NoticeHandling",
					RawIRC = ircMessage.ToString()
				});
				UnaccountedFor(ircMessage.ToString());
				break;
			}
		}

		private void HandleJoin(IrcMessage ircMessage)
		{
			this.OnUserJoined?.Invoke(this, new OnUserJoinedArgs
			{
				Channel = ircMessage.Channel,
				Username = ircMessage.User
			});
		}

		private void HandlePart(IrcMessage ircMessage)
		{
			if (string.Equals(TwitchUsername, ircMessage.User, StringComparison.InvariantCultureIgnoreCase))
			{
				_joinedChannelManager.RemoveJoinedChannel(ircMessage.Channel);
				_hasSeenJoinedChannels.Remove(ircMessage.Channel);
				this.OnLeftChannel?.Invoke(this, new OnLeftChannelArgs
				{
					BotUsername = TwitchUsername,
					Channel = ircMessage.Channel
				});
			}
			else
			{
				this.OnUserLeft?.Invoke(this, new OnUserLeftArgs
				{
					Channel = ircMessage.Channel,
					Username = ircMessage.User
				});
			}
		}

		private void HandleClearChat(IrcMessage ircMessage)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			string value;
			if (string.IsNullOrWhiteSpace(ircMessage.Message))
			{
				this.OnChatCleared?.Invoke(this, new OnChatClearedArgs
				{
					Channel = ircMessage.Channel
				});
			}
			else if (ircMessage.Tags.TryGetValue("ban-duration", out value))
			{
				UserTimeout userTimeout = new UserTimeout(ircMessage);
				this.OnUserTimedout?.Invoke(this, new OnUserTimedoutArgs
				{
					UserTimeout = userTimeout
				});
			}
			else
			{
				UserBan userBan = new UserBan(ircMessage);
				this.OnUserBanned?.Invoke(this, new OnUserBannedArgs
				{
					UserBan = userBan
				});
			}
		}

		private void HandleClearMsg(IrcMessage ircMessage)
		{
			this.OnMessageCleared?.Invoke(this, new OnMessageClearedArgs
			{
				Channel = ircMessage.Channel,
				Message = ircMessage.Message,
				TargetMessageId = ircMessage.ToString().Split(new char[1] { '=' })[3].Split(new char[1] { ';' })[0],
				TmiSentTs = ircMessage.ToString().Split(new char[1] { '=' })[4].Split(new char[1] { ' ' })[0]
			});
		}

		private void HandleUserState(IrcMessage ircMessage)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			UserState val = new UserState(ircMessage);
			if (!_hasSeenJoinedChannels.Contains(val.Channel.ToLowerInvariant()))
			{
				_hasSeenJoinedChannels.Add(val.Channel.ToLowerInvariant());
				this.OnUserStateChanged?.Invoke(this, new OnUserStateChangedArgs
				{
					UserState = val
				});
			}
			else
			{
				this.OnMessageSent?.Invoke(this, new OnMessageSentArgs
				{
					SentMessage = new SentMessage(val, _lastMessageSent)
				});
			}
		}

		private void Handle004()
		{
			this.OnConnected?.Invoke(this, new OnConnectedArgs
			{
				BotUsername = TwitchUsername
			});
		}

		private void Handle353(IrcMessage ircMessage)
		{
			this.OnExistingUsersDetected?.Invoke(this, new OnExistingUsersDetectedArgs
			{
				Channel = ircMessage.Channel,
				Users = ircMessage.Message.Split(new char[1] { ' ' }).ToList()
			});
		}

		private void Handle366()
		{
			_currentlyJoiningChannels = false;
			QueueingJoinCheck();
		}

		private void HandleWhisper(IrcMessage ircMessage)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			WhisperMessage val2 = (PreviousWhisper = new WhisperMessage(ircMessage, TwitchUsername));
			this.OnWhisperReceived?.Invoke(this, new OnWhisperReceivedArgs
			{
				WhisperMessage = val2
			});
			if (_whisperCommandIdentifiers != null && _whisperCommandIdentifiers.Count != 0 && !string.IsNullOrEmpty(val2.Message) && _whisperCommandIdentifiers.Contains(val2.Message[0]))
			{
				WhisperCommand command = new WhisperCommand(val2);
				this.OnWhisperCommandReceived?.Invoke(this, new OnWhisperCommandReceivedArgs
				{
					Command = command
				});
				return;
			}
			this.OnUnaccountedFor?.Invoke(this, new OnUnaccountedForArgs
			{
				BotUsername = TwitchUsername,
				Channel = ircMessage.Channel,
				Location = "WhispergHandling",
				RawIRC = ircMessage.ToString()
			});
			UnaccountedFor(ircMessage.ToString());
		}

		private void HandleRoomState(IrcMessage ircMessage)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			if (ircMessage.Tags.Count > 2)
			{
				KeyValuePair<string, DateTime> item = _awaitingJoins.FirstOrDefault((KeyValuePair<string, DateTime> x) => x.Key == ircMessage.Channel);
				_awaitingJoins.Remove(item);
				this.OnJoinedChannel?.Invoke(this, new OnJoinedChannelArgs
				{
					BotUsername = TwitchUsername,
					Channel = ircMessage.Channel
				});
			}
			this.OnChannelStateChanged?.Invoke(this, new OnChannelStateChangedArgs
			{
				ChannelState = new ChannelState(ircMessage),
				Channel = ircMessage.Channel
			});
		}

		private void HandleUserNotice(IrcMessage ircMessage)
		{
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Expected O, but got Unknown
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Expected O, but got Unknown
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Expected O, but got Unknown
			if (!ircMessage.Tags.TryGetValue("msg-id", out var value))
			{
				this.OnUnaccountedFor?.Invoke(this, new OnUnaccountedForArgs
				{
					BotUsername = TwitchUsername,
					Channel = ircMessage.Channel,
					Location = "UserNoticeHandling",
					RawIRC = ircMessage.ToString()
				});
				UnaccountedFor(ircMessage.ToString());
				return;
			}
			switch (value)
			{
			case "announcement":
			{
				Announcement announcement = new Announcement(ircMessage);
				this.OnAnnouncement?.Invoke(this, new OnAnnouncementArgs
				{
					Announcement = announcement,
					Channel = ircMessage.Channel
				});
				break;
			}
			case "raid":
			{
				RaidNotification raidNotification = new RaidNotification(ircMessage);
				this.OnRaidNotification?.Invoke(this, new OnRaidNotificationArgs
				{
					Channel = ircMessage.Channel,
					RaidNotification = raidNotification
				});
				break;
			}
			case "resub":
			{
				ReSubscriber reSubscriber = new ReSubscriber(ircMessage);
				this.OnReSubscriber?.Invoke(this, new OnReSubscriberArgs
				{
					ReSubscriber = reSubscriber,
					Channel = ircMessage.Channel
				});
				break;
			}
			case "subgift":
			{
				GiftedSubscription giftedSubscription2 = new GiftedSubscription(ircMessage);
				this.OnGiftedSubscription?.Invoke(this, new OnGiftedSubscriptionArgs
				{
					GiftedSubscription = giftedSubscription2,
					Channel = ircMessage.Channel
				});
				break;
			}
			case "submysterygift":
			{
				CommunitySubscription giftedSubscription = new CommunitySubscription(ircMessage);
				this.OnCommunitySubscription?.Invoke(this, new OnCommunitySubscriptionArgs
				{
					GiftedSubscription = giftedSubscription,
					Channel = ircMessage.Channel
				});
				break;
			}
			case "giftpaidupgrade":
			{
				ContinuedGiftedSubscription continuedGiftedSubscription = new ContinuedGiftedSubscription(ircMessage);
				this.OnContinuedGiftedSubscription?.Invoke(this, new OnContinuedGiftedSubscriptionArgs
				{
					ContinuedGiftedSubscription = continuedGiftedSubscription,
					Channel = ircMessage.Channel
				});
				break;
			}
			case "sub":
			{
				Subscriber subscriber = new Subscriber(ircMessage);
				this.OnNewSubscriber?.Invoke(this, new OnNewSubscriberArgs
				{
					Subscriber = subscriber,
					Channel = ircMessage.Channel
				});
				break;
			}
			case "primepaidupgrade":
			{
				PrimePaidSubscriber primePaidSubscriber = new PrimePaidSubscriber(ircMessage);
				this.OnPrimePaidSubscriber?.Invoke(this, new OnPrimePaidSubscriberArgs
				{
					PrimePaidSubscriber = primePaidSubscriber,
					Channel = ircMessage.Channel
				});
				break;
			}
			default:
				this.OnUnaccountedFor?.Invoke(this, new OnUnaccountedForArgs
				{
					BotUsername = TwitchUsername,
					Channel = ircMessage.Channel,
					Location = "UserNoticeHandling",
					RawIRC = ircMessage.ToString()
				});
				UnaccountedFor(ircMessage.ToString());
				break;
			}
		}

		private void HandleMode(IrcMessage ircMessage)
		{
			if (ircMessage.Message.StartsWith("+o"))
			{
				this.OnModeratorJoined?.Invoke(this, new OnModeratorJoinedArgs
				{
					Channel = ircMessage.Channel,
					Username = ircMessage.Message.Split(new char[1] { ' ' })[1]
				});
			}
			else if (ircMessage.Message.StartsWith("-o"))
			{
				this.OnModeratorLeft?.Invoke(this, new OnModeratorLeftArgs
				{
					Channel = ircMessage.Channel,
					Username = ircMessage.Message.Split(new char[1] { ' ' })[1]
				});
			}
		}

		private void HandleCap(IrcMessage ircMessage)
		{
		}

		private void UnaccountedFor(string ircString)
		{
			Log("Unaccounted for: " + ircString + " (please create a TwitchLib GitHub issue :P)");
		}

		private void Log(string message, bool includeDate = false, bool includeTime = false)
		{
			string arg = ((includeDate && includeTime) ? $"{DateTime.UtcNow}" : ((!includeDate) ? (DateTime.UtcNow.ToShortTimeString() ?? "") : (DateTime.UtcNow.ToShortDateString() ?? "")));
			if (includeDate || includeTime)
			{
				_logger?.LogInformation($"[TwitchLib, {Assembly.GetExecutingAssembly().GetName().Version} - {arg}] {message}");
			}
			else
			{
				_logger?.LogInformation($"[TwitchLib, {Assembly.GetExecutingAssembly().GetName().Version}] {message}");
			}
			EventHandler<OnLogArgs> onLog = this.OnLog;
			if (onLog != null)
			{
				OnLogArgs onLogArgs = new OnLogArgs();
				ConnectionCredentials connectionCredentials = ConnectionCredentials;
				onLogArgs.BotUsername = ((connectionCredentials != null) ? connectionCredentials.TwitchUsername : null);
				onLogArgs.Data = message;
				onLogArgs.DateTime = DateTime.UtcNow;
				onLog(this, onLogArgs);
			}
		}

		private void LogError(string message, bool includeDate = false, bool includeTime = false)
		{
			string arg = ((includeDate && includeTime) ? $"{DateTime.UtcNow}" : ((!includeDate) ? (DateTime.UtcNow.ToShortTimeString() ?? "") : (DateTime.UtcNow.ToShortDateString() ?? "")));
			if (includeDate || includeTime)
			{
				_logger?.LogError($"[TwitchLib, {Assembly.GetExecutingAssembly().GetName().Version} - {arg}] {message}");
			}
			else
			{
				_logger?.LogError($"[TwitchLib, {Assembly.GetExecutingAssembly().GetName().Version}] {message}");
			}
			EventHandler<OnLogArgs> onLog = this.OnLog;
			if (onLog != null)
			{
				OnLogArgs onLogArgs = new OnLogArgs();
				ConnectionCredentials connectionCredentials = ConnectionCredentials;
				onLogArgs.BotUsername = ((connectionCredentials != null) ? connectionCredentials.TwitchUsername : null);
				onLogArgs.Data = message;
				onLogArgs.DateTime = DateTime.UtcNow;
				onLog(this, onLogArgs);
			}
		}

		public void SendQueuedItem(string message)
		{
			if (!IsInitialized)
			{
				HandleNotInitialized();
			}
			_client.Send(message);
		}

		protected static void HandleNotInitialized()
		{
			throw new ClientNotInitializedException("The twitch client has not been initialized and cannot be used. Please call Initialize();");
		}

		protected static void HandleNotConnected()
		{
			throw new ClientNotConnectedException("In order to perform this action, the client must be connected to Twitch. To confirm connection, try performing this action in or after the OnConnected event has been fired.");
		}
	}
}
namespace TwitchLib.Client.Manager
{
	internal class JoinedChannelManager
	{
		private readonly ConcurrentDictionary<string, JoinedChannel> _joinedChannels;

		public JoinedChannelManager()
		{
			_joinedChannels = new ConcurrentDictionary<string, JoinedChannel>(StringComparer.OrdinalIgnoreCase);
		}

		public void AddJoinedChannel(JoinedChannel joinedChannel)
		{
			_joinedChannels.TryAdd(joinedChannel.Channel, joinedChannel);
		}

		public JoinedChannel GetJoinedChannel(string channel)
		{
			_joinedChannels.TryGetValue(channel, out var value);
			return value;
		}

		public IReadOnlyList<JoinedChannel> GetJoinedChannels()
		{
			return _joinedChannels.Values.ToList().AsReadOnly();
		}

		public void RemoveJoinedChannel(string channel)
		{
			_joinedChannels.TryRemove(channel, out var _);
		}

		public void Clear()
		{
			_joinedChannels.Clear();
		}
	}
}
namespace TwitchLib.Client.Internal
{
	public sealed class Rfc2812
	{
		private static readonly Regex NicknameRegex = new Regex("^[A-Za-z\\[\\]\\\\`_^{|}][A-Za-z0-9\\[\\]\\\\`_\\-^{|}]+$", RegexOptions.Compiled);

		private Rfc2812()
		{
		}

		public static bool IsValidNickname(string nickname)
		{
			if (!string.IsNullOrEmpty(nickname))
			{
				return NicknameRegex.Match(nickname).Success;
			}
			return false;
		}

		public static string Pass(string password)
		{
			return "PASS " + password;
		}

		public static string Nick(string nickname)
		{
			return "NICK " + nickname;
		}

		public static string User(string username, int usermode, string realname)
		{
			return $"USER {username} {usermode} * :{realname}";
		}

		public static string Oper(string name, string password)
		{
			return "OPER " + name + " " + password;
		}

		public static string Privmsg(string destination, string message)
		{
			return "PRIVMSG " + destination + " :" + message;
		}

		public static string Notice(string destination, string message)
		{
			return "NOTICE " + destination + " :" + message;
		}

		public static string Join(string channel)
		{
			return "JOIN " + channel;
		}

		public static string Join(string[] channels)
		{
			return "JOIN " + string.Join(",", channels);
		}

		public static string Join(string channel, string key)
		{
			return "JOIN " + channel + " " + key;
		}

		public static string Join(string[] channels, string[] keys)
		{
			return "JOIN " + string.Join(",", channels) + " " + string.Join(",", keys);
		}

		public static string Part(string channel)
		{
			return "PART " + channel;
		}

		public static string Part(string[] channels)
		{
			return "PART " + string.Join(",", channels);
		}

		public static string Part(string channel, string partmessage)
		{
			return "PART " + channel + " :" + partmessage;
		}

		public static string Part(string[] channels, string partmessage)
		{
			return "PART " + string.Join(",", channels) + " :" + partmessage;
		}

		public static string Kick(string channel, string nickname)
		{
			return "KICK " + channel + " " + nickname;
		}

		public static string Kick(string channel, string nickname, string comment)
		{
			return "KICK " + channel + " " + nickname + " :" + comment;
		}

		public static string Kick(string[] channels, string nickname)
		{
			return "KICK " + string.Join(",", channels) + " " + nickname;
		}

		public static string Kick(string[] channels, string nickname, string comment)
		{
			return "KICK " + string.Join(",", channels) + " " + nickname + " :" + comment;
		}

		public static string Kick(string channel, string[] nicknames)
		{
			return "KICK " + channel + " " + string.Join(",", nicknames);
		}

		public static string Kick(string channel, string[] nicknames, string comment)
		{
			return "KICK " + channel + " " + string.Join(",", nicknames) + " :" + comment;
		}

		public static string Kick(string[] channels, string[] nicknames)
		{
			return "KICK " + string.Join(",", channels) + " " + string.Join(",", nicknames);
		}

		public static string Kick(string[] channels, string[] nicknames, string comment)
		{
			return "KICK " + string.Join(",", channels) + " " + string.Join(",", nicknames) + " :" + comment;
		}

		public static string Motd()
		{
			return "MOTD";
		}

		public static string Motd(string target)
		{
			return "MOTD " + target;
		}

		public static string Lusers()
		{
			return "LUSERS";
		}

		public static string Lusers(string mask)
		{
			return "LUSER " + mask;
		}

		public static string Lusers(string mask, string target)
		{
			return "LUSER " + mask + " " + target;
		}

		public static string Version()
		{
			return "VERSION";
		}

		public static string Version(string target)
		{
			return "VERSION " + target;
		}

		public static string Stats()
		{
			return "STATS";
		}

		public static string Stats(string query)
		{
			return "STATS " + query;
		}

		public static string Stats(string query, string target)
		{
			return "STATS " + query + " " + target;
		}

		public static string Links()
		{
			return "LINKS";
		}

		public static string Links(string servermask)
		{
			return "LINKS " + servermask;
		}

		public static string Links(string remoteserver, string servermask)
		{
			return "LINKS " + remoteserver + " " + servermask;
		}

		public static string Time()
		{
			return "TIME";
		}

		public static string Time(string target)
		{
			return "TIME " + target;
		}

		public static string Connect(string targetserver, string port)
		{
			return "CONNECT " + targetserver + " " + port;
		}

		public static string Connect(string targetserver, string port, string remoteserver)
		{
			return "CONNECT " + targetserver + " " + port + " " + remoteserver;
		}

		public static string Trace()
		{
			return "TRACE";
		}

		public static string Trace(string target)
		{
			return "TRACE " + target;
		}

		public static string Admin()
		{
			return "ADMIN";
		}

		public static string Admin(string target)
		{
			return "ADMIN " + target;
		}

		public static string Info()
		{
			return "INFO";
		}

		public static string Info(string target)
		{
			return "INFO " + target;
		}

		public static string Servlist()
		{
			return "SERVLIST";
		}

		public static string Servlist(string mask)
		{
			return "SERVLIST " + mask;
		}

		public static string Servlist(string mask, string type)
		{
			return "SERVLIST " + mask + " " + type;
		}

		public static string Squery(string servicename, string servicetext)
		{
			return "SQUERY " + servicename + " :" + servicename;
		}

		public static string List()
		{
			return "LIST";
		}

		public static string List(string channel)
		{
			return "LIST " + channel;
		}

		public static string List(string[] channels)
		{
			return "LIST " + string.Join(",", channels);
		}

		public static string List(string channel, string target)
		{
			return "LIST " + channel + " " + target;
		}

		public static string List(string[] channels, string target)
		{
			return "LIST " + string.Join(",", channels) + " " + target;
		}

		public static string Names()
		{
			return "NAMES";
		}

		public static string Names(string channel)
		{
			return "NAMES " + channel;
		}

		public static string Names(string[] channels)
		{
			return "NAMES " + string.Join(",", channels);
		}

		public static string Names(string channel, string target)
		{
			return "NAMES " + channel + " " + target;
		}

		public static string Names(string[] channels, string target)
		{
			return "NAMES " + string.Join(",", channels) + " " + target;
		}

		public static string Topic(string channel)
		{
			return "TOPIC " + channel;
		}

		public static string Topic(string channel, string newtopic)
		{
			return "TOPIC " + channel + " :" + newtopic;
		}

		public static string Mode(string target)
		{
			return "MODE " + target;
		}

		public static string Mode(string target, string newmode)
		{
			return "MODE " + target + " " + newmode + target + " " + newmode;
		}

		public static string Mode(string target, string[] newModes, string[] newModeParameters)
		{
			if (newModes == null)
			{
				throw new ArgumentNullException("newModes");
			}
			if (newModeParameters == null)
			{
				throw new ArgumentNullException("newModeParameters");
			}
			if (newModes.Length != newModeParameters.Length)
			{
				throw new ArgumentException("newModes and newModeParameters must have the same size.");
			}
			StringBuilder stringBuilder = new StringBuilder(newModes.Length);
			StringBuilder stringBuilder2 = new StringBuilder();
			if (newModes.Length > 3)
			{
				throw new ArgumentOutOfRangeException("Length", newModes.Length, $"Mode change list is too large (> {3}).");
			}
			for (int i = 0; i <= newModes.Length; i += 3)
			{
				for (int j = 0; j < 3 && i + j < newModes.Length; j++)
				{
					stringBuilder.Append(newModes[i + j]);
				}
				for (int k = 0; k < 3 && i + k < newModeParameters.Length; k++)
				{
					stringBuilder2.Append(newModeParameters[i + k]);
					stringBuilder2.Append(" ");
				}
			}
			if (stringBuilder2.Length <= 0)
			{
				return Mode(target, stringBuilder.ToString());
			}
			stringBuilder2.Length--;
			stringBuilder.Append(" ");
			stringBuilder.Append((object?)stringBuilder2);
			return Mode(target, stringBuilder.ToString());
		}

		public static string Service(string nickname, string distribution, string info)
		{
			return "SERVICE " + nickname + " * " + distribution + " * * :" + info;
		}

		public static string Invite(string nickname, string channel)
		{
			return "INVITE " + nickname + " " + channel;
		}

		public static string Who()
		{
			return "WHO";
		}

		public static string Who(string mask)
		{
			return "WHO " + mask;
		}

		public static string Who(string mask, bool ircop)
		{
			if (!ircop)
			{
				return "WHO " + mask;
			}
			return "WHO " + mask + " o";
		}

		public static string Whois(string mask)
		{
			return "WHOIS " + mask;
		}

		public static string Whois(string[] masks)
		{
			return "WHOIS " + string.Join(",", masks);
		}

		public static string Whois(string target, string mask)
		{
			return "WHOIS " + target + " " + mask;
		}

		public static string Whois(string target, string[] masks)
		{
			return "WHOIS " + target + " " + string.Join(",", masks);
		}

		public static string Whowas(string nickname)
		{
			return "WHOWAS " + nickname;
		}

		public static string Whowas(string[] nicknames)
		{
			return "WHOWAS " + string.Join(",", nicknames);
		}

		public static string Whowas(string nickname, string count)
		{
			return "WHOWAS " + nickname + " " + count + " ";
		}

		public static string Whowas(string[] nicknames, string count)
		{
			return "WHOWAS " + string.Join(",", nicknames) + " " + count + " ";
		}

		public static string Whowas(string nickname, string count, string target)
		{
			return "WHOWAS " + nickname + " " + count + " " + target;
		}

		public static string Whowas(string[] nicknames, string count, string target)
		{
			return "WHOWAS " + string.Join(",", nicknames) + " " + count + " " + target;
		}

		public static string Kill(string nickname, string comment)
		{
			return "KILL " + nickname + " :" + comment;
		}

		public static string Ping(string server)
		{
			return "PING " + server;
		}

		public static string Ping(string server, string server2)
		{
			return "PING " + server + " " + server2;
		}

		public static string Pong(string server)
		{
			return "PONG " + server;
		}

		public static string Pong(string server, string server2)
		{
			return "PONG " + server + " " + server2;
		}

		public static string Error(string errormessage)
		{
			return "ERROR :" + errormessage;
		}

		public static string Away()
		{
			return "AWAY";
		}

		public static string Away(string awaytext)
		{
			return "AWAY :" + awaytext;
		}

		public static string Rehash()
		{
			return "REHASH";
		}

		public static string Die()
		{
			return "DIE";
		}

		public static string Restart()
		{
			return "RESTART";
		}

		public static string Summon(string user)
		{
			return "SUMMON " + user;
		}

		public static string Summon(string user, string target)
		{
			return "SUMMON " + user + " " + target + user + " " + target;
		}

		public static string Summon(string user, string target, string channel)
		{
			return "SUMMON " + user + " " + target + " " + channel;
		}

		public static string Users()
		{
			return "USERS";
		}

		public static string Users(string target)
		{
			return "USERS " + target;
		}

		public static string Wallops(string wallopstext)
		{
			return "WALLOPS :" + wallopstext;
		}

		public static string Userhost(string nickname)
		{
			return "USERHOST " + nickname;
		}

		public static string Userhost(string[] nicknames)
		{
			return "USERHOST " + string.Join(" ", nicknames);
		}

		public static string Ison(string nickname)
		{
			return "ISON " + nickname;
		}

		public static string Ison(string[] nicknames)
		{
			return "ISON " + string.Join(" ", nicknames);
		}

		public static string Quit()
		{
			return "QUIT";
		}

		public static string Quit(string quitmessage)
		{
			return "QUIT :" + quitmessage;
		}

		public static string Squit(string server, string comment)
		{
			return "SQUIT " + server + " :" + comment;
		}
	}
}
namespace TwitchLib.Client.Internal.Parsing
{
	internal class IrcParser
	{
		private enum ParserState
		{
			STATE_NONE,
			STATE_V3,
			STATE_PREFIX,
			STATE_COMMAND,
			STATE_PARAM,
			STATE_TRAILING
		}

		public IrcMessage ParseIrcMessage(string raw)
		{
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_068c: Unknown result type (might be due to invalid IL or missing references)
			//IL_064f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0691: Unknown result type (might be due to invalid IL or missing references)
			//IL_065f: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0728: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0743: Expected O, but got Unknown
			//IL_06ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0680: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06de: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_0657: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0677: Unknown result type (might be due to invalid IL or missing references)
			//IL_066f: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0686: Unknown result type (might be due to invalid IL or missing references)
			//IL_069c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			ParserState parserState = ParserState.STATE_NONE;
			int[] array = new int[6];
			int[] array2 = new int[6];
			for (int i = 0; i < raw.Length; i++)
			{
				array2[(int)parserState] = i - array[(int)parserState] - 1;
				if (parserState == ParserState.STATE_NONE && raw[i] == '@')
				{
					parserState = ParserState.STATE_V3;
					i = (array[(int)parserState] = i + 1);
					int num = i;
					string text = null;
					for (; i < raw.Length; i++)
					{
						if (raw[i] == '=')
						{
							text = raw.Substring(num, i - num);
							num = i + 1;
						}
						else if (raw[i] == ';')
						{
							if (text == null)
							{
								dictionary[raw.Substring(num, i - num)] = "1";
							}
							else
							{
								dictionary[text] = raw.Substring(num, i - num);
							}
							num = i + 1;
						}
						else if (raw[i] == ' ')
						{
							if (text == null)
							{
								dictionary[raw.Substring(num, i - num)] = "1";
							}
							else
							{
								dictionary[text] = raw.Substring(num, i - num);
							}
							break;
						}
					}
				}
				else if (parserState < ParserState.STATE_PREFIX && raw[i] == ':')
				{
					parserState = ParserState.STATE_PREFIX;
					i = (array[(int)parserState] = i + 1);
				}
				else if (parserState < ParserState.STATE_COMMAND)
				{
					parserState = ParserState.STATE_COMMAND;
					array[(int)parserState] = i;
				}
				else
				{
					if (parserState < ParserState.STATE_TRAILING && raw[i] == ':')
					{
						parserState = ParserState.STATE_TRAILING;
						i = (array[(int)parserState] = i + 1);
						break;
					}
					if ((parserState < ParserState.STATE_TRAILING && raw[i] == '+') || (parserState < ParserState.STATE_TRAILING && raw[i] == '-'))
					{
						parserState = ParserState.STATE_TRAILING;
						array[(int)parserState] = i;
						break;
					}
					if (parserState == ParserState.STATE_COMMAND)
					{
						parserState = ParserState.STATE_PARAM;
						array[(int)parserState] = i;
					}
				}
				for (; i < raw.Length && raw[i] != ' '; i++)
				{
				}
			}
			array2[(int)parserState] = raw.Length - array[(int)parserState];
			string text2 = raw.Substring(array[3], array2[3]);
			IrcCommand val = (IrcCommand)0;
			switch (text2)
			{
			case "PRIVMSG":
				val = (IrcCommand)1;
				break;
			case "NOTICE":
				val = (IrcCommand)2;
				break;
			case "PING":
				val = (IrcCommand)3;
				break;
			case "PONG":
				val = (IrcCommand)4;
				break;
			case "CLEARCHAT":
				val = (IrcCommand)7;
				break;
			case "CLEARMSG":
				val = (IrcCommand)8;
				break;
			case "USERSTATE":
				val = (IrcCommand)9;
				break;
			case "GLOBALUSERSTATE":
				val = (IrcCommand)10;
				break;
			case "NICK":
				val = (IrcCommand)11;
				break;
			case "JOIN":
				val = (IrcCommand)5;
				break;
			case "PART":
				val = (IrcCommand)6;
				break;
			case "PASS":
				val = (IrcCommand)12;
				break;
			case "CAP":
				val = (IrcCommand)13;
				break;
			case "001":
				val = (IrcCommand)14;
				break;
			case "002":
				val = (IrcCommand)15;
				break;
			case "003":
				val = (IrcCommand)16;
				break;
			case "004":
				val = (IrcCommand)17;
				break;
			case "353":
				val = (IrcCommand)18;
				break;
			case "366":
				val = (IrcCommand)19;
				break;
			case "372":
				val = (IrcCommand)20;
				break;
			case "375":
				val = (IrcCommand)21;
				break;
			case "376":
				val = (IrcCommand)22;
				break;
			case "WHISPER":
				val = (IrcCommand)23;
				break;
			case "SERVERCHANGE":
				val = (IrcCommand)26;
				break;
			case "RECONNECT":
				val = (IrcCommand)25;
				break;
			case "ROOMSTATE":
				val = (IrcCommand)24;
				break;
			case "USERNOTICE":
				val = (IrcCommand)27;
				break;
			case "MODE":
				val = (IrcCommand)28;
				break;
			}
			string text3 = raw.Substring(array[4], array2[4]);
			string text4 = raw.Substring(array[5], array2[5]);
			string text5 = raw.Substring(array[2], array2[2]);
			return new IrcMessage(val, new string[2] { text3, text4 }, text5, dictionary);
		}
	}
}
namespace TwitchLib.Client.Interfaces
{
	public interface ITwitchClient
	{
		bool AutoReListenOnException { get; set; }

		MessageEmoteCollection ChannelEmotes { get; }

		ConnectionCredentials ConnectionCredentials { get; }

		bool DisableAutoPong { get; set; }

		bool IsConnected { get; }

		bool IsInitialized { get; }

		IReadOnlyList<JoinedChannel> JoinedChannels { get; }

		WhisperMessage PreviousWhisper { get; }

		string TwitchUsername { get; }

		bool WillReplaceEmotes { get; set; }

		event EventHandler<OnChannelStateChangedArgs> OnChannelStateChanged;

		event EventHandler<OnChatClearedArgs> OnChatCleared;

		event EventHandler<OnChatColorChangedArgs> OnChatColorChanged;

		event EventHandler<OnChatCommandReceivedArgs> OnChatCommandReceived;

		event EventHandler<OnConnectedArgs> OnConnected;

		event EventHandler<OnConnectionErrorArgs> OnConnectionError;

		event EventHandler<OnDisconnectedEventArgs> OnDisconnected;

		event EventHandler<OnExistingUsersDetectedArgs> OnExistingUsersDetected;

		event EventHandler<OnGiftedSubscriptionArgs> OnGiftedSubscription;

		event EventHandler<OnIncorrectLoginArgs> OnIncorrectLogin;

		event EventHandler<OnJoinedChannelArgs> OnJoinedChannel;

		event EventHandler<OnLeftChannelArgs> OnLeftChannel;

		event EventHandler<OnLogArgs> OnLog;

		event EventHandler<OnMessageReceivedArgs> OnMessageReceived;

		event EventHandler<OnMessageSentArgs> OnMessageSent;

		event EventHandler<OnModeratorJoinedArgs> OnModeratorJoined;

		event EventHandler<OnModeratorLeftArgs> OnModeratorLeft;

		event EventHandler<OnModeratorsReceivedArgs> OnModeratorsReceived;

		event EventHandler<OnNewSubscriberArgs> OnNewSubscriber;

		event EventHandler<OnRaidNotificationArgs> OnRaidNotification;

		event EventHandler<OnReSubscriberArgs> OnReSubscriber;

		event EventHandler<OnSendReceiveDataArgs> OnSendReceiveData;

		event EventHandler<OnUserBannedArgs> OnUserBanned;

		event EventHandler<OnUserJoinedArgs> OnUserJoined;

		event EventHandler<OnUserLeftArgs> OnUserLeft;

		event EventHandler<OnUserStateChangedArgs> OnUserStateChanged;

		event EventHandler<OnUserTimedoutArgs> OnUserTimedout;

		event EventHandler<OnWhisperCommandReceivedArgs> OnWhisperCommandReceived;

		event EventHandler<OnWhisperReceivedArgs> OnWhisperReceived;

		event EventHandler<OnWhisperSentArgs> OnWhisperSent;

		event EventHandler<OnMessageThrottledEventArgs> OnMessageThrottled;

		event EventHandler<OnWhisperThrottledEventArgs> OnWhisperThrottled;

		event EventHandler<OnErrorEventArgs> OnError;

		event EventHandler<OnReconnectedEventArgs> OnReconnected;

		event EventHandler<OnVIPsReceivedArgs> OnVIPsReceived;

		event EventHandler<OnCommunitySubscriptionArgs> OnCommunitySubscription;

		event EventHandler<OnMessageClearedArgs> OnMessageCleared;

		event EventHandler<OnRequiresVerifiedEmailArgs> OnRequiresVerifiedEmail;

		event EventHandler<OnRequiresVerifiedPhoneNumberArgs> OnRequiresVerifiedPhoneNumber;

		event EventHandler<OnBannedEmailAliasArgs> OnBannedEmailAlias;

		event EventHandler<OnUserIntroArgs> OnUserIntro;

		event EventHandler<OnAnnouncementArgs> OnAnnouncement;

		void Initialize(ConnectionCredentials credentials, string channel = null, char chatCommandIdentifier = '!', char whisperCommandIdentifier = '!', bool autoReListenOnExceptions = true);

		void Initialize(ConnectionCredentials credentials, List<string> channels, char chatCommandIdentifier = '!', char whisperCommandIdentifier = '!', bool autoReListenOnExceptions = true);

		void SetConnectionCredentials(ConnectionCredentials credentials);

		void AddChatCommandIdentifier(char identifier);

		void AddWhisperCommandIdentifier(char identifier);

		void RemoveChatCommandIdentifier(char identifier);

		void RemoveWhisperCommandIdentifier(char identifier);

		bool Connect();

		void Disconnect();

		void Reconnect();

		JoinedChannel GetJoinedChannel(string channel);

		void JoinChannel(string channel, bool overrideCheck = false);

		void LeaveChannel(JoinedChannel channel);

		void LeaveChannel(string channel);

		void OnReadLineTest(string rawIrc);

		void SendMessage(JoinedChannel channel, string message, bool dryRun = false);

		void SendMessage(string channel, string message, bool dryRun = false);

		void SendReply(JoinedChannel channel, string replyToId, string message, bool dryRun = false);

		void SendReply(string channel, string replyToId, string message, bool dryRun = false);

		void SendQueuedItem(string message);

		void SendRaw(string message);

		void SendWhisper(string receiver, string message, bool dryRun = false);
	}
}
namespace TwitchLib.Client.Extensions
{
	public static class AnnoucementExt
	{
		public static void Announce(this ITwitchClient client, JoinedChannel channel, string message)
		{
			client.SendMessage(channel, ".announce " + message);
		}

		public static void Announce(this ITwitchClient client, string channel, string message)
		{
			client.SendMessage(channel, ".announce " + message);
		}
	}
	public static class BanUserExt
	{
		public static void BanUser(this ITwitchClient client, JoinedChannel channel, string viewer, string message = "", bool dryRun = false)
		{
			client.SendMessage(channel, ".ban " + viewer + " " + message);
		}

		public static void BanUser(this ITwitchClient client, string channel, string viewer, string message = "", bool dryRun = false)
		{
			JoinedChannel joinedChannel = client.GetJoinedChannel(channel);
			if (joinedChannel != null)
			{
				client.BanUser(joinedChannel, viewer, message, dryRun);
			}
		}
	}
	public static class ChangeChatColorExt
	{
		public static void ChangeChatColor(this ITwitchClient client, JoinedChannel channel, ChatColorPresets color)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			client.SendMessage(channel, $".color {color}");
		}

		public static void ChangeChatColor(this ITwitchClient client, string channel, ChatColorPresets color)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			client.SendMessage(channel, $".color {color}");
		}
	}
	public static class ClearChatExt
	{
		public static void ClearChat(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".clear");
		}

		public static void ClearChat(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".clear");
		}
	}
	public static class CommercialExt
	{
		public static void StartCommercial(this ITwitchClient client, JoinedChannel channel, CommercialLength length)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if ((int)length <= 90)
			{
				if ((int)length == 30)
				{
					client.SendMessage(channel, ".commercial 30");
					return;
				}
				if ((int)length == 60)
				{
					client.SendMessage(channel, ".commercial 60");
					return;
				}
				if ((int)length == 90)
				{
					client.SendMessage(channel, ".commercial 90");
					return;
				}
			}
			else
			{
				if ((int)length == 120)
				{
					client.SendMessage(channel, ".commercial 120");
					return;
				}
				if ((int)length == 150)
				{
					client.SendMessage(channel, ".commercial 150");
					return;
				}
				if ((int)length == 180)
				{
					client.SendMessage(channel, ".commercial 180");
					return;
				}
			}
			throw new ArgumentOutOfRangeException("length", length, null);
		}

		public static void StartCommercial(this ITwitchClient client, string channel, CommercialLength length)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if ((int)length <= 90)
			{
				if ((int)length == 30)
				{
					client.SendMessage(channel, ".commercial 30");
					return;
				}
				if ((int)length == 60)
				{
					client.SendMessage(channel, ".commercial 60");
					return;
				}
				if ((int)length == 90)
				{
					client.SendMessage(channel, ".commercial 90");
					return;
				}
			}
			else
			{
				if ((int)length == 120)
				{
					client.SendMessage(channel, ".commercial 120");
					return;
				}
				if ((int)length == 150)
				{
					client.SendMessage(channel, ".commercial 150");
					return;
				}
				if ((int)length == 180)
				{
					client.SendMessage(channel, ".commercial 180");
					return;
				}
			}
			throw new ArgumentOutOfRangeException("length", length, null);
		}
	}
	public static class DeleteMessageExt
	{
		public static void DeleteMessage(this ITwitchClient client, JoinedChannel channel, string messageId)
		{
			client.SendMessage(channel, ".delete " + messageId);
		}

		public static void DeleteMessage(this ITwitchClient client, string channel, string messageId)
		{
			client.SendMessage(channel, ".delete " + messageId);
		}

		public static void DeleteMessage(this ITwitchClient client, JoinedChannel channel, ChatMessage msg)
		{
			client.SendMessage(channel, ".delete " + msg.Id);
		}

		public static void DeleteMessage(this ITwitchClient client, string channel, ChatMessage msg)
		{
			client.SendMessage(channel, ".delete " + msg.Id);
		}
	}
	public static class EmoteOnlyExt
	{
		public static void EmoteOnlyOn(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".emoteonly");
		}

		public static void EmoteOnlyOn(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".emoteonly");
		}

		public static void EmoteOnlyOff(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".emoteonlyoff");
		}

		public static void EmoteOnlyOff(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".emoteonlyoff");
		}
	}
	public static class EventInvocationExt
	{
		public static void InvokeChannelStateChanged(this TwitchClient client, string channel, bool r9k, bool rituals, bool subOnly, int slowMode, bool emoteOnly, string broadcasterLanguage, TimeSpan followersOnly, bool mercury, string roomId)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			ChannelState channelState = new ChannelState(r9k, rituals, subOnly, slowMode, emoteOnly, broadcasterLanguage, channel, followersOnly, mercury, roomId);
			OnChannelStateChangedArgs args = new OnChannelStateChangedArgs
			{
				Channel = channel,
				ChannelState = channelState
			};
			client.RaiseEvent("OnChannelStateChanged", args);
		}

		public static void InvokeChatCleared(this TwitchClient client, string channel)
		{
			OnChatClearedArgs args = new OnChatClearedArgs
			{
				Channel = channel
			};
			client.RaiseEvent("OnChatCleared", args);
		}

		public static void InvokeChatCommandsReceived(this TwitchClient client, string botUsername, string userId, string userName, string displayName, string colorHex, Color color, EmoteSet emoteSet, string message, UserType userType, string channel, string id, bool isSubscriber, int subscribedMonthCount, string roomId, bool isTurbo, bool isModerator, bool isMe, bool isBroadcaster, bool isVip, bool isPartner, bool isStaff, Noisy noisy, string rawIrcMessage, string emoteReplacedMessage, List<KeyValuePair<string, string>> badges, CheerBadge cheerBadge, int bits, double bitsInDollars, string commandText, string argumentsAsString, List<string> argumentsAsList, char commandIdentifier)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			ChatMessage val = new ChatMessage(botUsername, userId, userName, displayName, colorHex, color, emoteSet, message, userType, channel, id, isSubscriber, subscribedMonthCount, roomId, isTurbo, isModerator, isMe, isBroadcaster, isVip, isPartner, isStaff, noisy, rawIrcMessage, emoteReplacedMessage, badges, cheerBadge, bits, bitsInDollars);
			OnChatCommandReceivedArgs args = new OnChatCommandReceivedArgs
			{
				Command = new ChatCommand(val, commandText, argumentsAsString, argumentsAsList, commandIdentifier)
			};
			client.RaiseEvent("OnChatCommandReceived", args);
		}

		public static void InvokeConnected(this TwitchClient client, string autoJoinChannel, string botUsername)
		{
			OnConnectedArgs args = new OnConnectedArgs
			{
				AutoJoinChannel = autoJoinChannel,
				BotUsername = botUsername
			};
			client.RaiseEvent("OnConnected", args);
		}

		public static void InvokeConnectionError(this TwitchClient client, string botUsername, ErrorEvent errorEvent)
		{
			OnConnectionErrorArgs args = new OnConnectionErrorArgs
			{
				BotUsername = botUsername,
				Error = errorEvent
			};
			client.RaiseEvent("OnConnectionError", args);
		}

		public static void InvokeDisconnected(this TwitchClient client, string botUsername)
		{
			OnDisconnectedArgs args = new OnDisconnectedArgs
			{
				BotUsername = botUsername
			};
			client.RaiseEvent("OnDisconnected", args);
		}

		public static void InvokeExistingUsersDetected(this TwitchClient client, string channel, List<string> users)
		{
			OnExistingUsersDetectedArgs args = new OnExistingUsersDetectedArgs
			{
				Channel = channel,
				Users = users
			};
			client.RaiseEvent("OnExistingUsersDetected", args);
		}

		public static void InvokeGiftedSubscription(this TwitchClient client, List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string color, string displayName, string emotes, string id, string login, bool isModerator, string msgId, string msgParamMonths, string msgParamRecipientDisplayName, string msgParamRecipientId, string msgParamRecipientUserName, string msgParamSubPlanName, string msgMultiMonthGiftDuration, SubscriptionPlan msgParamSubPlan, string roomId, bool isSubscriber, string systemMsg, string systemMsgParsed, string tmiSentTs, bool isTurbo, UserType userType, string userId)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			OnGiftedSubscriptionArgs args = new OnGiftedSubscriptionArgs
			{
				GiftedSubscription = new GiftedSubscription(badges, badgeInfo, color, displayName, emotes, id, login, isModerator, msgId, msgParamMonths, msgParamRecipientDisplayName, msgParamRecipientId, msgParamRecipientUserName, msgParamSubPlanName, msgMultiMonthGiftDuration, msgParamSubPlan, roomId, isSubscriber, systemMsg, systemMsgParsed, tmiSentTs, isTurbo, userType, userId)
			};
			client.RaiseEvent("OnGiftedSubscription", args);
		}

		public static void InvokeIncorrectLogin(this TwitchClient client, ErrorLoggingInException ex)
		{
			OnIncorrectLoginArgs args = new OnIncorrectLoginArgs
			{
				Exception = ex
			};
			client.RaiseEvent("OnIncorrectLogin", args);
		}

		public static void InvokeJoinedChannel(this TwitchClient client, string botUsername, string channel)
		{
			OnJoinedChannelArgs args = new OnJoinedChannelArgs
			{
				BotUsername = botUsername,
				Channel = channel
			};
			client.RaiseEvent("OnJoinedChannel", args);
		}

		public static void InvokeLeftChannel(this TwitchClient client, string botUsername, string channel)
		{
			OnLeftChannelArgs args = new OnLeftChannelArgs
			{
				BotUsername = botUsername,
				Channel = channel
			};
			client.RaiseEvent("OnLeftChannel", args);
		}

		public static void InvokeLog(this TwitchClient client, string botUsername, string data, DateTime dateTime)
		{
			OnLogArgs args = new OnLogArgs
			{
				BotUsername = botUsername,
				Data = data,
				DateTime = dateTime
			};
			client.RaiseEvent("OnLog", args);
		}

		public static void InvokeMessageReceived(this TwitchClient client, string botUsername, string userId, string userName, string displayName, string colorHex, Color color, EmoteSet emoteSet, string message, UserType userType, string channel, string id, bool isSubscriber, int subscribedMonthCount, string roomId, bool isTurbo, bool isModerator, bool isMe, bool isBroadcaster, bool isVip, bool isPartner, bool isStaff, Noisy noisy, string rawIrcMessage, string emoteReplacedMessage, List<KeyValuePair<string, string>> badges, CheerBadge cheerBadge, int bits, double bitsInDollars)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			OnMessageReceivedArgs args = new OnMessageReceivedArgs
			{
				ChatMessage = new ChatMessage(botUsername, userId, userName, displayName, colorHex, color, emoteSet, message, userType, channel, id, isSubscriber, subscribedMonthCount, roomId, isTurbo, isModerator, isMe, isBroadcaster, isVip, isPartner, isStaff, noisy, rawIrcMessage, emoteReplacedMessage, badges, cheerBadge, bits, bitsInDollars)
			};
			client.RaiseEvent("OnMessageReceived", args);
		}

		public static void InvokeMessageSent(this TwitchClient client, List<KeyValuePair<string, string>> badges, string channel, string colorHex, string displayName, string emoteSet, bool isModerator, bool isSubscriber, UserType userType, string message)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			OnMessageSentArgs args = new OnMessageSentArgs
			{
				SentMessage = new SentMessage(badges, channel, colorHex, displayName, emoteSet, isModerator, isSubscriber, userType, message)
			};
			client.RaiseEvent("OnMessageSent", args);
		}

		public static void InvokeModeratorJoined(this TwitchClient client, string channel, string username)
		{
			OnModeratorJoinedArgs args = new OnModeratorJoinedArgs
			{
				Channel = channel,
				Username = username
			};
			client.RaiseEvent("OnModeratorJoined", args);
		}

		public static void InvokeModeratorLeft(this TwitchClient client, string channel, string username)
		{
			OnModeratorLeftArgs args = new OnModeratorLeftArgs
			{
				Channel = channel,
				Username = username
			};
			client.RaiseEvent("OnModeratorLeft", args);
		}

		public static void InvokeModeratorsReceived(this TwitchClient client, string channel, List<string> moderators)
		{
			OnModeratorsReceivedArgs args = new OnModeratorsReceivedArgs
			{
				Channel = channel,
				Moderators = moderators
			};
			client.RaiseEvent("OnModeratorsReceived", args);
		}

		public static void InvokeNewSubscriber(this TwitchClient client, List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, Color color, string displayName, string emoteSet, string id, string login, string systemMessage, string msgId, string msgParamCumulativeMonths, string msgParamStreakMonths, bool msgParamShouldShareStreak, string systemMessageParsed, string resubMessage, SubscriptionPlan subscriptionPlan, string subscriptionPlanName, string roomId, string userId, bool isModerator, bool isTurbo, bool isSubscriber, bool isPartner, string tmiSentTs, UserType userType, string rawIrc, string channel)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			OnNewSubscriberArgs args = new OnNewSubscriberArgs
			{
				Subscriber = new Subscriber(badges, badgeInfo, colorHex, color, displayName, emoteSet, id, login, systemMessage, msgId, msgParamCumulativeMonths, msgParamStreakMonths, msgParamShouldShareStreak, systemMessageParsed, resubMessage, subscriptionPlan, subscriptionPlanName, roomId, userId, isModerator, isTurbo, isSubscriber, isPartner, tmiSentTs, userType, rawIrc, channel)
			};
			client.RaiseEvent("OnNewSubscriber", args);
		}

		public static void InvokeRaidNotification(this TwitchClient client, string channel, List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string color, string displayName, string emotes, string id, string login, bool moderator, string msgId, string msgParamDisplayName, string msgParamLogin, string msgParamViewerCount, string roomId, bool subscriber, string systemMsg, string systemMsgParsed, string tmiSentTs, bool turbo, UserType userType, string userId)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			OnRaidNotificationArgs args = new OnRaidNotificationArgs
			{
				Channel = channel,
				RaidNotification = new RaidNotification(badges, badgeInfo, color, displayName, emotes, id, login, moderator, msgId, msgParamDisplayName, msgParamLogin, msgParamViewerCount, roomId, subscriber, systemMsg, systemMsgParsed, tmiSentTs, turbo, userType, userId)
			};
			client.RaiseEvent("OnRaidNotification", args);
		}

		public static void InvokeReSubscriber(this TwitchClient client, List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, Color color, string displayName, string emoteSet, string id, string login, string systemMessage, string msgId, string msgParamCumulativeMonths, string msgParamStreakMonths, bool msgParamShouldShareStreak, string systemMessageParsed, string resubMessage, SubscriptionPlan subscriptionPlan, string subscriptionPlanName, string roomId, string userId, bool isModerator, bool isTurbo, bool isSubscriber, bool isPartner, string tmiSentTs, UserType userType, string rawIrc, string channel)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			OnReSubscriberArgs args = new OnReSubscriberArgs
			{
				ReSubscriber = new ReSubscriber(badges, badgeInfo, colorHex, color, displayName, emoteSet, id, login, systemMessage, msgId, msgParamCumulativeMonths, msgParamStreakMonths, msgParamShouldShareStreak, systemMessageParsed, resubMessage, subscriptionPlan, subscriptionPlanName, roomId, userId, isModerator, isTurbo, isSubscriber, isPartner, tmiSentTs, userType, rawIrc, channel, 0)
			};
			client.RaiseEvent("OnReSubscriber", args);
		}

		public static void InvokeSendReceiveData(this TwitchClient client, string data, SendReceiveDirection direction)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			OnSendReceiveDataArgs args = new OnSendReceiveDataArgs
			{
				Data = data,
				Direction = direction
			};
			client.RaiseEvent("OnSendReceiveData", args);
		}

		public static void InvokeUserBanned(this TwitchClient client, string channel, string username, string banReason, string roomId, string targetUserId)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			OnUserBannedArgs args = new OnUserBannedArgs
			{
				UserBan = new UserBan(channel, username, banReason, roomId, targetUserId)
			};
			client.RaiseEvent("OnUserBanned", args);
		}

		public static void InvokeUserJoined(this TwitchClient client, string channel, string username)
		{
			OnUserJoinedArgs args = new OnUserJoinedArgs
			{
				Channel = channel,
				Username = username
			};
			client.RaiseEvent("OnUserJoined", args);
		}

		public static void InvokeUserLeft(this TwitchClient client, string channel, string username)
		{
			OnUserLeftArgs args = new OnUserLeftArgs
			{
				Channel = channel,
				Username = username
			};
			client.RaiseEvent("OnUserLeft", args);
		}

		public static void InvokeUserStateChanged(this TwitchClient client, List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, string displayName, string emoteSet, string channel, string id, bool isSubscriber, bool isModerator, UserType userType)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			OnUserStateChangedArgs args = new OnUserStateChangedArgs
			{
				UserState = new UserState(badges, badgeInfo, colorHex, displayName, emoteSet, channel, id, isSubscriber, isModerator, userType)
			};
			client.RaiseEvent("OnUserStateChanged", args);
		}

		public static void InvokeUserTimedout(this TwitchClient client, string channel, string username, string targetUserId, int timeoutDuration, string timeoutReason)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			OnUserTimedoutArgs args = new OnUserTimedoutArgs
			{
				UserTimeout = new UserTimeout(channel, username, targetUserId, timeoutDuration, timeoutReason)
			};
			client.RaiseEvent("OnUserTimedout", args);
		}

		public static void InvokeWhisperCommandReceived(this TwitchClient client, List<KeyValuePair<string, string>> badges, string colorHex, Color color, string username, string displayName, EmoteSet emoteSet, string threadId, string messageId, string userId, bool isTurbo, string botUsername, string message, UserType userType, string commandText, string argumentsAsString, List<string> argumentsAsList, char commandIdentifier)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			WhisperMessage val = new WhisperMessage(badges, colorHex, color, username, displayName, emoteSet, threadId, messageId, userId, isTurbo, botUsername, message, userType);
			OnWhisperCommandReceivedArgs args = new OnWhisperCommandReceivedArgs
			{
				Command = new WhisperCommand(val, commandText, argumentsAsString, argumentsAsList, commandIdentifier)
			};
			client.RaiseEvent("OnWhisperCommandReceived", args);
		}

		public static void InvokeWhisperReceived(this TwitchClient client, List<KeyValuePair<string, string>> badges, string colorHex, Color color, string username, string displayName, EmoteSet emoteSet, string threadId, string messageId, string userId, bool isTurbo, string botUsername, string message, UserType userType)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			OnWhisperReceivedArgs args = new OnWhisperReceivedArgs
			{
				WhisperMessage = new WhisperMessage(badges, colorHex, color, username, displayName, emoteSet, threadId, messageId, userId, isTurbo, botUsername, message, userType)
			};
			client.RaiseEvent("OnWhisperReceived", args);
		}

		public static void InvokeWhisperSent(this TwitchClient client, string username, string receiver, string message)
		{
			OnWhisperSentArgs args = new OnWhisperSentArgs
			{
				Message = message,
				Receiver = receiver,
				Username = username
			};
			client.RaiseEvent("OnWhisperSent", args);
		}
	}
	public static class FollowersOnlyExt
	{
		private const int MaximumDurationAllowedDays = 90;

		public static void FollowersOnlyOn(this ITwitchClient client, JoinedChannel channel, TimeSpan requiredFollowTime)
		{
			if (requiredFollowTime > TimeSpan.FromDays(90.0))
			{
				throw new InvalidParameterException("The amount of time required to chat exceeded the maximum allowed by Twitch, which is 3 months.", client.TwitchUsername);
			}
			string text = $"{requiredFollowTime.Days}d {requiredFollowTime.Hours}h {requiredFollowTime.Minutes}m";
			client.SendMessage(channel, ".followers " + text);
		}

		public static void FollowersOnlyOn(this ITwitchClient client, string channel, TimeSpan requiredFollowTime)
		{
			if (requiredFollowTime > TimeSpan.FromDays(90.0))
			{
				throw new InvalidParameterException("The amount of time required to chat exceeded the maximum allowed by Twitch, which is 3 months.", client.TwitchUsername);
			}
			string text = $"{requiredFollowTime.Days}d {requiredFollowTime.Hours}h {requiredFollowTime.Minutes}m";
			client.SendMessage(channel, ".followers " + text);
		}

		public static void FollowersOnlyOff(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".followersoff");
		}

		public static void FollowersOnlyOff(this TwitchClient client, string channel)
		{
			client.SendMessage(channel, ".followersoff");
		}
	}
	public static class GetChannelModeratorsExt
	{
		public static void GetChannelModerators(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".mods");
		}

		public static void GetChannelModerators(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".mods");
		}
	}
	public static class MarkerExt
	{
		public static void Marker(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".marker");
		}

		public static void Marker(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".marker");
		}
	}
	public static class ModExt
	{
		public static void Mod(this ITwitchClient client, JoinedChannel channel, string viewerToMod)
		{
			client.SendMessage(channel, ".mod " + viewerToMod);
		}

		public static void Mod(this ITwitchClient client, string channel, string viewerToMod)
		{
			client.SendMessage(channel, ".mod " + viewerToMod);
		}

		public static void Unmod(this ITwitchClient client, JoinedChannel channel, string viewerToUnmod)
		{
			client.SendMessage(channel, ".unmod " + viewerToUnmod);
		}

		public static void Unmod(this ITwitchClient client, string channel, string viewerToUnmod)
		{
			client.SendMessage(channel, ".unmod " + viewerToUnmod);
		}
	}
	public static class RaidExt
	{
		public static void Raid(this ITwitchClient client, JoinedChannel channel, string channelToRaid)
		{
			client.SendMessage(channel, ".raid " + channelToRaid);
		}

		public static void Raid(this ITwitchClient client, string channel, string channelToRaid)
		{
			client.SendMessage(channel, ".raid " + channelToRaid);
		}
	}
	public static class ReplyWhisperExt
	{
		public static void ReplyToLastWhisper(this ITwitchClient client, string message = "", bool dryRun = false)
		{
			if (client.PreviousWhisper != null)
			{
				client.SendWhisper(((TwitchLibMessage)client.PreviousWhisper).Username, message, dryRun);
			}
		}
	}
	public static class SlowModeExt
	{
		public static void SlowModeOn(this ITwitchClient client, JoinedChannel channel, TimeSpan messageCooldown)
		{
			if (messageCooldown > TimeSpan.FromDays(1.0))
			{
				throw new InvalidParameterException("The message cooldown time supplied exceeded the maximum allowed by Twitch, which is 1 day.", client.TwitchUsername);
			}
			client.SendMessage(channel, $".slow {messageCooldown.TotalSeconds}");
		}

		public static void SlowModeOn(this ITwitchClient client, string channel, TimeSpan messageCooldown)
		{
			if (messageCooldown > TimeSpan.FromDays(1.0))
			{
				throw new InvalidParameterException("The message cooldown time supplied exceeded the maximum allowed by Twitch, which is 1 day.", client.TwitchUsername);
			}
			client.SendMessage(channel, $".slow {messageCooldown.TotalSeconds}");
		}

		public static void SlowModeOff(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".slowoff");
		}

		public static void SlowModeOff(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".slowoff");
		}
	}
	public static class SubscribersOnly
	{
		public static void SubscribersOnlyOn(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".subscribers");
		}

		public static void SubscribersOnlyOn(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".subscribers");
		}

		public static void SubscribersOnlyOff(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".subscribersoff");
		}

		public static void SubscribersOnlyOff(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".subscribersoff");
		}
	}
	public static class TimeoutUserExt
	{
		public static void TimeoutUser(this ITwitchClient client, JoinedChannel channel, string viewer, TimeSpan duration, string message = "", bool dryRun = false)
		{
			client.SendMessage(channel, $".timeout {viewer} {duration.TotalSeconds} {message}", dryRun);
		}

		public static void TimeoutUser(this ITwitchClient client, string channel, string viewer, TimeSpan duration, string message = "", bool dryRun = false)
		{
			JoinedChannel joinedChannel = client.GetJoinedChannel(channel);
			if (joinedChannel != null)
			{
				client.TimeoutUser(joinedChannel, viewer, duration, message, dryRun);
			}
		}
	}
	public static class UnbanUserExt
	{
		public static void UnbanUser(this ITwitchClient client, JoinedChannel channel, string viewer, bool dryRun = false)
		{
			client.SendMessage(channel, ".unban " + viewer, dryRun);
		}

		public static void UnbanUser(this ITwitchClient client, string channel, string viewer, bool dryRun = false)
		{
			JoinedChannel joinedChannel = client.GetJoinedChannel(channel);
			if (joinedChannel != null)
			{
				client.UnbanUser(joinedChannel, viewer, dryRun);
			}
		}
	}
	public static class VIPExt
	{
		public static void VIP(this ITwitchClient client, JoinedChannel channel, string viewerToVIP)
		{
			client.SendMessage(channel, ".vip " + viewerToVIP);
		}

		public static void VIP(this ITwitchClient client, string channel, string viewerToVIP)
		{
			client.SendMessage(channel, ".vip " + viewerToVIP);
		}

		public static void UnVIP(this ITwitchClient client, JoinedChannel channel, string viewerToUnVIP)
		{
			client.SendMessage(channel, ".unvip " + viewerToUnVIP);
		}

		public static void UnVIP(this ITwitchClient client, string channel, string viewerToUnVIP)
		{
			client.SendMessage(channel, ".unvip " + viewerToUnVIP);
		}

		public static void GetVIPs(this ITwitchClient client, JoinedChannel channel)
		{
			client.SendMessage(channel, ".vips");
		}

		public static void GetVIPs(this ITwitchClient client, string channel)
		{
			client.SendMessage(channel, ".vips");
		}
	}
}
namespace TwitchLib.Client.Exceptions
{
	public class BadListenException : Exception
	{
		public BadListenException(string eventName, string additionalDetails = "")
			: base(string.IsNullOrEmpty(additionalDetails) ? ("You are listening to event '" + eventName + "', which is not currently allowed. See details: " + additionalDetails) : ("You are listening to event '" + eventName + "', which is not currently allowed."))
		{
		}
	}
	public class BadStateException : Exception
	{
		public BadStateException(string details)
			: base(details)
		{
		}
	}
	public class ClientNotConnectedException : Exception
	{
		public ClientNotConnectedException(string description)
			: base(description)
		{
		}
	}
	public class ClientNotInitializedException : Exception
	{
		public ClientNotInitializedException(string description)
			: base(description)
		{
		}
	}
	public class ErrorLoggingInException : Exception
	{
		public string Username { get; protected set; }

		public ErrorLoggingInException(string ircData, string twitchUsername)
			: base(ircData)
		{
			Username = twitchUsername;
		}
	}
	public class EventNotHandled : Exception
	{
		public EventNotHandled(string eventName, string additionalDetails = "")
			: base(string.IsNullOrEmpty(additionalDetails) ? ("To use this call, you must handle/subscribe to event: " + eventName) : ("To use this call, you must handle/subscribe to event: " + eventName + ", additional details: " + additionalDetails))
		{
		}
	}
	public class FailureToReceiveJoinConfirmationException
	{
		public string Channel { get; protected set; }

		public string Details { get; protected set; }

		

plugins/TwitchLib/TwitchLib.Client.Enums.dll

Decompiled 6 months ago
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2021")]
[assembly: AssemblyDescription("Project containing all of the enums used in TwitchLib.Client.")]
[assembly: AssemblyFileVersion("3.3.1")]
[assembly: AssemblyInformationalVersion("3.3.1")]
[assembly: AssemblyProduct("TwitchLib.Client.Enums")]
[assembly: AssemblyTitle("TwitchLib.Client.Enums")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.Client")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.3.1.0")]
namespace TwitchLib.Client.Enums
{
	public enum BadgeColor
	{
		Red = 10000,
		Blue = 5000,
		Green = 1000,
		Purple = 100,
		Gray = 1
	}
	public enum ChatColorPresets
	{
		Blue,
		Coral,
		DodgerBlue,
		SpringGreen,
		YellowGreen,
		Green,
		OrangeRed,
		Red,
		GoldenRod,
		HotPink,
		CadetBlue,
		SeaGreen,
		Chocolate,
		BlueViolet,
		Firebrick
	}
	public enum ClientProtocol
	{
		TCP,
		WebSocket
	}
	public enum CommercialLength
	{
		Seconds30 = 30,
		Seconds60 = 60,
		Seconds90 = 90,
		Seconds120 = 120,
		Seconds150 = 150,
		Seconds180 = 180
	}
	public enum Noisy
	{
		NotSet,
		True,
		False
	}
	public enum SendReceiveDirection
	{
		Sent,
		Received
	}
	public abstract class StringEnum
	{
		public string Value { get; }

		protected StringEnum(string value)
		{
			Value = value;
		}

		public override string ToString()
		{
			return Value;
		}
	}
	public enum SubscriptionPlan
	{
		NotSet,
		Prime,
		Tier1,
		Tier2,
		Tier3
	}
	public enum ThrottleType
	{
		MessageTooShort,
		MessageTooLong
	}
	public enum UserType : byte
	{
		Viewer,
		Moderator,
		GlobalModerator,
		Broadcaster,
		Admin,
		Staff
	}
}
namespace TwitchLib.Client.Enums.Internal
{
	public enum IrcCommand
	{
		Unknown,
		PrivMsg,
		Notice,
		Ping,
		Pong,
		Join,
		Part,
		ClearChat,
		ClearMsg,
		UserState,
		GlobalUserState,
		Nick,
		Pass,
		Cap,
		RPL_001,
		RPL_002,
		RPL_003,
		RPL_004,
		RPL_353,
		RPL_366,
		RPL_372,
		RPL_375,
		RPL_376,
		Whisper,
		RoomState,
		Reconnect,
		ServerChange,
		UserNotice,
		Mode
	}
}

plugins/TwitchLib/TwitchLib.Client.Models.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using TwitchLib.Client.Enums;
using TwitchLib.Client.Enums.Internal;
using TwitchLib.Client.Models.Builders;
using TwitchLib.Client.Models.Common;
using TwitchLib.Client.Models.Extensions.NetCore;
using TwitchLib.Client.Models.Extractors;
using TwitchLib.Client.Models.Internal;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2021")]
[assembly: AssemblyDescription("Project contains all of the models used in TwitchLib.Client.")]
[assembly: AssemblyFileVersion("3.3.1")]
[assembly: AssemblyInformationalVersion("3.3.1")]
[assembly: AssemblyProduct("TwitchLib.Client.Models")]
[assembly: AssemblyTitle("TwitchLib.Client.Models")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.Client")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.3.1.0")]
namespace TwitchLib.Client.Models
{
	public class Announcement
	{
		public string Id { get; }

		public List<KeyValuePair<string, string>> Badges { get; }

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public string SystemMessage { get; }

		public string SystemMessageParsed { get; }

		public bool IsBroadcaster { get; }

		public bool IsModerator { get; }

		public bool IsPartner { get; }

		public bool IsSubscriber { get; }

		public bool IsStaff { get; }

		public bool IsTurbo { get; }

		public string Login { get; }

		public string UserId { get; }

		public string RoomId { get; }

		public UserType UserType { get; }

		public string TmiSentTs { get; }

		public string EmoteSet { get; }

		public string RawIrc { get; }

		public string MsgId { get; }

		public string MsgParamColor { get; }

		public string ColorHex { get; }

		public Color Color { get; }

		public string Message { get; }

		public Announcement(IrcMessage ircMessage)
		{
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			RawIrc = ircMessage.ToString();
			Message = ircMessage.Message;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
				{
					Badges = Helpers.ParseBadges(text);
					using (List<KeyValuePair<string, string>>.Enumerator enumerator2 = Badges.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							switch (enumerator2.Current.Key)
							{
							case "broadcaster":
								IsBroadcaster = true;
								break;
							case "turbo":
								IsTurbo = true;
								break;
							case "moderator":
								IsModerator = true;
								break;
							case "subscriber":
								IsSubscriber = true;
								break;
							case "admin":
								IsStaff = true;
								break;
							case "staff":
								IsStaff = true;
								break;
							case "partner":
								IsPartner = true;
								break;
							}
						}
					}
					break;
				}
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					ColorHex = text;
					if (!string.IsNullOrEmpty(ColorHex))
					{
						Color = TwitchLib.Client.Models.Extensions.NetCore.ColorTranslator.FromHtml(ColorHex);
					}
					break;
				case "msg-param-color":
					MsgParamColor = text;
					break;
				case "emotes":
					EmoteSet = text;
					break;
				case "id":
					Id = text;
					break;
				case "login":
					Login = text;
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "room-id":
					RoomId = text;
					break;
				case "system-msg":
					SystemMessage = text;
					SystemMessageParsed = text.Replace("\\s", " ");
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "user-id":
					UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				}
			}
		}
	}
	public class ChannelState
	{
		public string BroadcasterLanguage { get; }

		public string Channel { get; }

		public bool? EmoteOnly { get; }

		public TimeSpan? FollowersOnly { get; }

		public bool Mercury { get; }

		public bool? R9K { get; }

		public bool? Rituals { get; }

		public string RoomId { get; }

		public int? SlowMode { get; }

		public bool? SubOnly { get; }

		public ChannelState(IrcMessage ircMessage)
		{
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "broadcaster-lang":
					BroadcasterLanguage = text;
					break;
				case "emote-only":
					EmoteOnly = Helpers.ConvertToBool(text);
					break;
				case "r9k":
					R9K = Helpers.ConvertToBool(text);
					break;
				case "rituals":
					Rituals = Helpers.ConvertToBool(text);
					break;
				case "slow":
				{
					int result2;
					bool flag = int.TryParse(text, out result2);
					SlowMode = (flag ? new int?(result2) : null);
					break;
				}
				case "subs-only":
					SubOnly = Helpers.ConvertToBool(text);
					break;
				case "followers-only":
				{
					if (int.TryParse(text, out var result) && result > -1)
					{
						FollowersOnly = TimeSpan.FromMinutes(result);
					}
					break;
				}
				case "room-id":
					RoomId = text;
					break;
				case "mercury":
					Mercury = Helpers.ConvertToBool(text);
					break;
				default:
					Console.WriteLine("[TwitchLib][ChannelState] Unaccounted for: " + key);
					break;
				}
			}
			Channel = ircMessage.Channel;
		}

		public ChannelState(bool r9k, bool rituals, bool subonly, int slowMode, bool emoteOnly, string broadcasterLanguage, string channel, TimeSpan followersOnly, bool mercury, string roomId)
		{
			R9K = r9k;
			Rituals = rituals;
			SubOnly = subonly;
			SlowMode = slowMode;
			EmoteOnly = emoteOnly;
			BroadcasterLanguage = broadcasterLanguage;
			Channel = channel;
			FollowersOnly = followersOnly;
			Mercury = mercury;
			RoomId = roomId;
		}
	}
	public class ChatCommand
	{
		public List<string> ArgumentsAsList { get; }

		public string ArgumentsAsString { get; }

		public ChatMessage ChatMessage { get; }

		public char CommandIdentifier { get; }

		public string CommandText { get; }

		public ChatCommand(ChatMessage chatMessage)
		{
			ChatCommand chatCommand = this;
			ChatMessage = chatMessage;
			string[] array = chatMessage.Message.Split(new char[1] { ' ' });
			CommandText = ((array != null) ? array[0].Substring(1, chatMessage.Message.Split(new char[1] { ' ' })[0].Length - 1) : null) ?? chatMessage.Message.Substring(1, chatMessage.Message.Length - 1);
			object obj;
			if (!chatMessage.Message.Contains(" "))
			{
				obj = "";
			}
			else
			{
				string message = chatMessage.Message;
				string[] array2 = chatMessage.Message.Split(new char[1] { ' ' });
				obj = message.Replace(((array2 != null) ? array2[0] : null) + " ", "");
			}
			ArgumentsAsString = (string)obj;
			if (!chatMessage.Message.Contains("\"") || chatMessage.Message.Count((char x) => x == '"') % 2 == 1)
			{
				ArgumentsAsList = chatMessage.Message.Split(new char[1] { ' ' })?.Where((string arg) => arg != chatMessage.Message[0] + chatCommand.CommandText).ToList() ?? new List<string>();
			}
			else
			{
				ArgumentsAsList = Helpers.ParseQuotesAndNonQuotes(ArgumentsAsString);
			}
			CommandIdentifier = chatMessage.Message[0];
		}

		public ChatCommand(ChatMessage chatMessage, string commandText, string argumentsAsString, List<string> argumentsAsList, char commandIdentifier)
		{
			ChatMessage = chatMessage;
			CommandText = commandText;
			ArgumentsAsString = argumentsAsString;
			ArgumentsAsList = argumentsAsList;
			CommandIdentifier = commandIdentifier;
		}
	}
	public class ChatMessage : TwitchLibMessage
	{
		protected readonly MessageEmoteCollection _emoteCollection;

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public int Bits { get; }

		public double BitsInDollars { get; }

		public string Channel { get; }

		public CheerBadge CheerBadge { get; }

		public string CustomRewardId { get; }

		public string EmoteReplacedMessage { get; }

		public string Id { get; }

		public bool IsBroadcaster { get; }

		public bool IsFirstMessage { get; }

		public bool IsHighlighted { get; internal set; }

		public bool IsMe { get; }

		public bool IsModerator { get; }

		public bool IsSkippingSubMode { get; internal set; }

		public bool IsSubscriber { get; }

		public bool IsVip { get; }

		public bool IsStaff { get; }

		public bool IsPartner { get; }

		public string Message { get; }

		public Noisy Noisy { get; }

		public string RoomId { get; }

		public int SubscribedMonthCount { get; }

		public string TmiSentTs { get; }

		public ChatReply ChatReply { get; }

		public ChatMessage(string botUsername, IrcMessage ircMessage, ref MessageEmoteCollection emoteCollection, bool replaceEmotes = false)
		{
			//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
			base.BotUsername = botUsername;
			base.RawIrcMessage = ircMessage.ToString();
			Message = ircMessage.Message;
			if (Message.Length > 0 && (byte)Message[0] == 1 && (byte)Message[Message.Length - 1] == 1 && Message.StartsWith("\u0001ACTION ") && Message.EndsWith("\u0001"))
			{
				Message = Message.Trim(new char[1] { '\u0001' }).Substring(7);
				IsMe = true;
			}
			_emoteCollection = emoteCollection;
			base.Username = ircMessage.User;
			Channel = ircMessage.Channel;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					base.Badges = Helpers.ParseBadges(text);
					foreach (KeyValuePair<string, string> badge in base.Badges)
					{
						switch (badge.Key)
						{
						case "bits":
							CheerBadge = new CheerBadge(int.Parse(badge.Value));
							break;
						case "subscriber":
							if (SubscribedMonthCount == 0)
							{
								SubscribedMonthCount = int.Parse(badge.Value);
							}
							break;
						case "vip":
							IsVip = true;
							break;
						case "admin":
							IsStaff = true;
							break;
						case "staff":
							IsStaff = true;
							break;
						case "partner":
							IsPartner = true;
							break;
						}
					}
					break;
				case "badge-info":
				{
					BadgeInfo = Helpers.ParseBadges(text);
					KeyValuePair<string, string> keyValuePair = BadgeInfo.Find((KeyValuePair<string, string> b) => b.Key == "founder");
					if (!keyValuePair.Equals(default(KeyValuePair<string, string>)))
					{
						IsSubscriber = true;
						SubscribedMonthCount = int.Parse(keyValuePair.Value);
						break;
					}
					KeyValuePair<string, string> keyValuePair2 = BadgeInfo.Find((KeyValuePair<string, string> b) => b.Key == "subscriber");
					if (!keyValuePair2.Equals(default(KeyValuePair<string, string>)))
					{
						SubscribedMonthCount = int.Parse(keyValuePair2.Value);
					}
					break;
				}
				case "bits":
					Bits = int.Parse(text);
					BitsInDollars = ConvertBitsToUsd(Bits);
					break;
				case "color":
					base.ColorHex = text;
					if (!string.IsNullOrWhiteSpace(base.ColorHex))
					{
						base.Color = TwitchLib.Client.Models.Extensions.NetCore.ColorTranslator.FromHtml(base.ColorHex);
					}
					break;
				case "custom-reward-id":
					CustomRewardId = text;
					break;
				case "display-name":
					base.DisplayName = text;
					break;
				case "emotes":
					base.EmoteSet = new EmoteSet(text, Message);
					break;
				case "first-msg":
					IsFirstMessage = text == "1";
					break;
				case "id":
					Id = text;
					break;
				case "msg-id":
					handleMsgId(text);
					break;
				case "mod":
					IsModerator = Helpers.ConvertToBool(text);
					break;
				case "noisy":
					Noisy = (Noisy)(Helpers.ConvertToBool(text) ? 1 : 2);
					break;
				case "reply-parent-display-name":
					if (ChatReply == null)
					{
						ChatReply = new ChatReply();
					}
					ChatReply.ParentDisplayName = text;
					break;
				case "reply-parent-msg-body":
					if (ChatReply == null)
					{
						ChatReply = new ChatReply();
					}
					ChatReply.ParentMsgBody = text;
					break;
				case "reply-parent-msg-id":
					if (ChatReply == null)
					{
						ChatReply = new ChatReply();
					}
					ChatReply.ParentMsgId = text;
					break;
				case "reply-parent-user-id":
					if (ChatReply == null)
					{
						ChatReply = new ChatReply();
					}
					ChatReply.ParentUserId = text;
					break;
				case "reply-parent-user-login":
					if (ChatReply == null)
					{
						ChatReply = new ChatReply();
					}
					ChatReply.ParentUserLogin = text;
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					IsSubscriber = IsSubscriber || Helpers.ConvertToBool(text);
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "turbo":
					base.IsTurbo = Helpers.ConvertToBool(text);
					break;
				case "user-id":
					base.UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						base.UserType = (UserType)1;
						break;
					case "global_mod":
						base.UserType = (UserType)2;
						break;
					case "admin":
						base.UserType = (UserType)4;
						IsStaff = true;
						break;
					case "staff":
						base.UserType = (UserType)5;
						IsStaff = true;
						break;
					default:
						base.UserType = (UserType)0;
						break;
					}
					break;
				}
			}
			if (base.EmoteSet != null && Message != null && base.EmoteSet.Emotes.Count > 0)
			{
				string[] array = base.EmoteSet.RawEmoteSetString.Split(new char[1] { '/' });
				foreach (string text2 in array)
				{
					int num = text2.IndexOf(':');
					int num2 = text2.IndexOf(',');
					if (num2 == -1)
					{
						num2 = text2.Length;
					}
					int num3 = text2.IndexOf('-');
					if (num > 0 && num3 > num && num2 > num3 && int.TryParse(text2.Substring(num + 1, num3 - num - 1), out var result) && int.TryParse(text2.Substring(num3 + 1, num2 - num3 - 1), out var result2) && result >= 0 && result < result2 && result2 < Message.Length)
					{
						string id = text2.Substring(0, num);
						string text3 = Message.Substring(result, result2 - result + 1);
						_emoteCollection.Add(new MessageEmote(id, text3));
					}
				}
				if (replaceEmotes)
				{
					EmoteReplacedMessage = _emoteCollection.ReplaceEmotes(Message);
				}
			}
			if (base.EmoteSet == null)
			{
				base.EmoteSet = new EmoteSet((string)null, Message);
			}
			if (string.IsNullOrEmpty(base.DisplayName))
			{
				base.DisplayName = base.Username;
			}
			if (string.Equals(Channel, base.Username, StringComparison.InvariantCultureIgnoreCase))
			{
				base.UserType = (UserType)3;
				IsBroadcaster = true;
			}
			if (Channel.Split(new char[1] { ':' }).Length == 3 && string.Equals(Channel.Split(new char[1] { ':' })[1], base.UserId, StringComparison.InvariantCultureIgnoreCase))
			{
				base.UserType = (UserType)3;
				IsBroadcaster = true;
			}
		}

		public ChatMessage(string botUsername, string userId, string userName, string displayName, string colorHex, Color color, EmoteSet emoteSet, string message, UserType userType, string channel, string id, bool isSubscriber, int subscribedMonthCount, string roomId, bool isTurbo, bool isModerator, bool isMe, bool isBroadcaster, bool isVip, bool isPartner, bool isStaff, Noisy noisy, string rawIrcMessage, string emoteReplacedMessage, List<KeyValuePair<string, string>> badges, CheerBadge cheerBadge, int bits, double bitsInDollars)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			base.BotUsername = botUsername;
			base.UserId = userId;
			base.DisplayName = displayName;
			base.ColorHex = colorHex;
			base.Color = color;
			base.EmoteSet = emoteSet;
			Message = message;
			base.UserType = userType;
			Channel = channel;
			Id = id;
			IsSubscriber = isSubscriber;
			SubscribedMonthCount = subscribedMonthCount;
			RoomId = roomId;
			base.IsTurbo = isTurbo;
			IsModerator = isModerator;
			IsMe = isMe;
			IsBroadcaster = isBroadcaster;
			IsVip = isVip;
			IsPartner = isPartner;
			IsStaff = isStaff;
			Noisy = noisy;
			base.RawIrcMessage = rawIrcMessage;
			EmoteReplacedMessage = emoteReplacedMessage;
			base.Badges = badges;
			CheerBadge = cheerBadge;
			Bits = bits;
			BitsInDollars = bitsInDollars;
			base.Username = userName;
		}

		private void handleMsgId(string val)
		{
			if (!(val == "highlighted-message"))
			{
				if (val == "skip-subs-mode-message")
				{
					IsSkippingSubMode = true;
				}
			}
			else
			{
				IsHighlighted = true;
			}
		}

		private static double ConvertBitsToUsd(int bits)
		{
			if (bits < 1500)
			{
				return (double)bits / 100.0 * 1.4;
			}
			if (bits < 5000)
			{
				return (double)bits / 1500.0 * 19.95;
			}
			if (bits < 10000)
			{
				return (double)bits / 5000.0 * 64.4;
			}
			if (bits < 25000)
			{
				return (double)bits / 10000.0 * 126.0;
			}
			return (double)bits / 25000.0 * 308.0;
		}
	}
	public class ChatReply
	{
		public string ParentDisplayName { get; internal set; }

		public string ParentMsgBody { get; internal set; }

		public string ParentMsgId { get; internal set; }

		public string ParentUserId { get; internal set; }

		public string ParentUserLogin { get; internal set; }
	}
	public class CheerBadge
	{
		public int CheerAmount { get; }

		public BadgeColor Color { get; }

		public CheerBadge(int cheerAmount)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			CheerAmount = cheerAmount;
			Color = GetColor(cheerAmount);
		}

		private BadgeColor GetColor(int cheerAmount)
		{
			if (cheerAmount < 10000)
			{
				if (cheerAmount < 5000)
				{
					if (cheerAmount < 1000)
					{
						if (cheerAmount >= 100)
						{
							return (BadgeColor)100;
						}
						return (BadgeColor)1;
					}
					return (BadgeColor)1000;
				}
				return (BadgeColor)5000;
			}
			return (BadgeColor)10000;
		}
	}
	public class CommunitySubscription
	{
		private const string AnonymousGifterUserId = "274598607";

		public List<KeyValuePair<string, string>> Badges;

		public List<KeyValuePair<string, string>> BadgeInfo;

		public string Color;

		public string DisplayName;

		public string Emotes;

		public string Id;

		public string Login;

		public bool IsModerator;

		public bool IsAnonymous;

		public string MsgId;

		public int MsgParamMassGiftCount;

		public int MsgParamSenderCount;

		public SubscriptionPlan MsgParamSubPlan;

		public string RoomId;

		public bool IsSubscriber;

		public string SystemMsg;

		public string SystemMsgParsed;

		public string TmiSentTs;

		public bool IsTurbo;

		public string UserId;

		public UserType UserType;

		public string MsgParamMultiMonthGiftDuration;

		public CommunitySubscription(IrcMessage ircMessage)
		{
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					Badges = Helpers.ParseBadges(text);
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					Color = text;
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emotes":
					Emotes = text;
					break;
				case "id":
					Id = text;
					break;
				case "login":
					Login = text;
					break;
				case "mod":
					IsModerator = Helpers.ConvertToBool(text);
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "msg-param-sub-plan":
					switch (text)
					{
					case "prime":
						MsgParamSubPlan = (SubscriptionPlan)1;
						break;
					case "1000":
						MsgParamSubPlan = (SubscriptionPlan)2;
						break;
					case "2000":
						MsgParamSubPlan = (SubscriptionPlan)3;
						break;
					case "3000":
						MsgParamSubPlan = (SubscriptionPlan)4;
						break;
					default:
						throw new ArgumentOutOfRangeException("ToLower");
					}
					break;
				case "msg-param-mass-gift-count":
					MsgParamMassGiftCount = int.Parse(text);
					break;
				case "msg-param-sender-count":
					MsgParamSenderCount = int.Parse(text);
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					IsSubscriber = Helpers.ConvertToBool(text);
					break;
				case "system-msg":
					SystemMsg = text;
					SystemMsgParsed = text.Replace("\\s", " ").Replace("\\n", "");
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "turbo":
					IsTurbo = Helpers.ConvertToBool(text);
					break;
				case "user-id":
					UserId = text;
					if (UserId == "274598607")
					{
						IsAnonymous = true;
					}
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				case "msg-param-gift-months":
					MsgParamMultiMonthGiftDuration = text;
					break;
				}
			}
		}
	}
	public class ConnectionCredentials
	{
		public const string DefaultWebSocketUri = "wss://irc-ws.chat.twitch.tv:443";

		public string TwitchWebsocketURI { get; }

		public string TwitchOAuth { get; }

		public string TwitchUsername { get; }

		public Capabilities Capabilities { get; }

		public ConnectionCredentials(string twitchUsername, string twitchOAuth, string twitchWebsocketURI = "wss://irc-ws.chat.twitch.tv:443", bool disableUsernameCheck = false, Capabilities capabilities = null)
		{
			if (!disableUsernameCheck && !new Regex("^([a-zA-Z0-9][a-zA-Z0-9_]{3,25})$").Match(twitchUsername).Success)
			{
				throw new Exception("Twitch username does not appear to be valid. " + twitchUsername);
			}
			TwitchUsername = twitchUsername.ToLower();
			TwitchOAuth = twitchOAuth;
			if (!twitchOAuth.Contains(":"))
			{
				TwitchOAuth = "oauth:" + twitchOAuth.Replace("oauth", "");
			}
			TwitchWebsocketURI = twitchWebsocketURI;
			if (capabilities == null)
			{
				capabilities = new Capabilities();
			}
			Capabilities = capabilities;
		}
	}
	public class Capabilities
	{
		public bool Membership { get; }

		public bool Tags { get; }

		public bool Commands { get; }

		public Capabilities(bool membership = true, bool tags = true, bool commands = true)
		{
			Membership = membership;
			Tags = tags;
			Commands = commands;
		}
	}
	public class ContinuedGiftedSubscription
	{
		public List<KeyValuePair<string, string>> Badges { get; }

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public string Color { get; }

		public string DisplayName { get; }

		public string Emotes { get; }

		public string Flags { get; }

		public string Id { get; }

		public string Login { get; }

		public bool IsModerator { get; }

		public string MsgId { get; }

		public string MsgParamSenderLogin { get; }

		public string MsgParamSenderName { get; }

		public string RoomId { get; }

		public bool IsSubscriber { get; }

		public string SystemMsg { get; }

		public string TmiSentTs { get; }

		public string UserId { get; }

		public UserType UserType { get; }

		public ContinuedGiftedSubscription(IrcMessage ircMessage)
		{
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "system-msg":
					SystemMsg = text;
					break;
				case "flags":
					Flags = text;
					break;
				case "msg-param-sender-login":
					MsgParamSenderLogin = text;
					break;
				case "msg-param-sender-name":
					MsgParamSenderName = text;
					break;
				case "badges":
					Badges = Helpers.ParseBadges(text);
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					Color = text;
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emotes":
					Emotes = text;
					break;
				case "id":
					Id = text;
					break;
				case "login":
					Login = text;
					break;
				case "mod":
					IsModerator = Helpers.ConvertToBool(text);
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					IsSubscriber = Helpers.ConvertToBool(text);
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "user-id":
					UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				}
			}
		}
	}
	public class Emote
	{
		public string Id { get; }

		public string Name { get; }

		public int StartIndex { get; }

		public int EndIndex { get; }

		public string ImageUrl { get; }

		public Emote(string emoteId, string name, int emoteStartIndex, int emoteEndIndex)
		{
			Id = emoteId;
			Name = name;
			StartIndex = emoteStartIndex;
			EndIndex = emoteEndIndex;
			ImageUrl = "https://static-cdn.jtvnw.net/emoticons/v1/" + emoteId + "/1.0";
		}
	}
	public class EmoteSet
	{
		public List<Emote> Emotes { get; }

		public string RawEmoteSetString { get; }

		public EmoteSet(string rawEmoteSetString, string message)
		{
			RawEmoteSetString = rawEmoteSetString;
			EmoteExtractor emoteExtractor = new EmoteExtractor();
			Emotes = emoteExtractor.Extract(rawEmoteSetString, message).ToList();
		}

		public EmoteSet(IEnumerable<Emote> emotes, string emoteSetData)
		{
			RawEmoteSetString = emoteSetData;
			Emotes = emotes.ToList();
		}
	}
	public class ErrorEvent
	{
		public string Message { get; set; }
	}
	public class GiftedSubscription
	{
		private const string AnonymousGifterUserId = "274598607";

		public List<KeyValuePair<string, string>> Badges { get; }

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public string Color { get; }

		public string DisplayName { get; }

		public string Emotes { get; }

		public string Id { get; }

		public bool IsModerator { get; }

		public bool IsSubscriber { get; }

		public bool IsTurbo { get; }

		public bool IsAnonymous { get; }

		public string Login { get; }

		public string MsgId { get; }

		public string MsgParamMonths { get; }

		public string MsgParamRecipientDisplayName { get; }

		public string MsgParamRecipientId { get; }

		public string MsgParamRecipientUserName { get; }

		public string MsgParamSubPlanName { get; }

		public SubscriptionPlan MsgParamSubPlan { get; }

		public string RoomId { get; }

		public string SystemMsg { get; }

		public string SystemMsgParsed { get; }

		public string TmiSentTs { get; }

		public string UserId { get; }

		public UserType UserType { get; }

		public string MsgParamMultiMonthGiftDuration { get; }

		public GiftedSubscription(IrcMessage ircMessage)
		{
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_056e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Unknown result type (might be due to invalid IL or missing references)
			//IL_0580: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					Badges = Helpers.ParseBadges(text);
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					Color = text;
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emotes":
					Emotes = text;
					break;
				case "id":
					Id = text;
					break;
				case "login":
					Login = text;
					break;
				case "mod":
					IsModerator = Helpers.ConvertToBool(text);
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "msg-param-months":
					MsgParamMonths = text;
					break;
				case "msg-param-recipient-display-name":
					MsgParamRecipientDisplayName = text;
					break;
				case "msg-param-recipient-id":
					MsgParamRecipientId = text;
					break;
				case "msg-param-recipient-user-name":
					MsgParamRecipientUserName = text;
					break;
				case "msg-param-sub-plan-name":
					MsgParamSubPlanName = text;
					break;
				case "msg-param-sub-plan":
					switch (text)
					{
					case "prime":
						MsgParamSubPlan = (SubscriptionPlan)1;
						break;
					case "1000":
						MsgParamSubPlan = (SubscriptionPlan)2;
						break;
					case "2000":
						MsgParamSubPlan = (SubscriptionPlan)3;
						break;
					case "3000":
						MsgParamSubPlan = (SubscriptionPlan)4;
						break;
					default:
						throw new ArgumentOutOfRangeException("ToLower");
					}
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					IsSubscriber = Helpers.ConvertToBool(text);
					break;
				case "system-msg":
					SystemMsg = text;
					SystemMsgParsed = text.Replace("\\s", " ").Replace("\\n", "");
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "turbo":
					IsTurbo = Helpers.ConvertToBool(text);
					break;
				case "user-id":
					UserId = text;
					if (UserId == "274598607")
					{
						IsAnonymous = true;
					}
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				case "msg-param-gift-months":
					MsgParamMultiMonthGiftDuration = text;
					break;
				}
			}
		}

		public GiftedSubscription(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string color, string displayName, string emotes, string id, string login, bool isModerator, string msgId, string msgParamMonths, string msgParamRecipientDisplayName, string msgParamRecipientId, string msgParamRecipientUserName, string msgParamSubPlanName, string msgMultiMonthDuration, SubscriptionPlan msgParamSubPlan, string roomId, bool isSubscriber, string systemMsg, string systemMsgParsed, string tmiSentTs, bool isTurbo, UserType userType, string userId)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			Badges = badges;
			BadgeInfo = badgeInfo;
			Color = color;
			DisplayName = displayName;
			Emotes = emotes;
			Id = id;
			Login = login;
			IsModerator = isModerator;
			MsgId = msgId;
			MsgParamMonths = msgParamMonths;
			MsgParamRecipientDisplayName = msgParamRecipientDisplayName;
			MsgParamRecipientId = msgParamRecipientId;
			MsgParamRecipientUserName = msgParamRecipientUserName;
			MsgParamSubPlanName = msgParamSubPlanName;
			MsgParamSubPlan = msgParamSubPlan;
			MsgParamMultiMonthGiftDuration = msgMultiMonthDuration;
			RoomId = roomId;
			IsSubscriber = isSubscriber;
			SystemMsg = systemMsg;
			SystemMsgParsed = systemMsgParsed;
			TmiSentTs = tmiSentTs;
			IsTurbo = isTurbo;
			UserType = userType;
			UserId = userId;
		}
	}
	public class JoinedChannel
	{
		public string Channel { get; }

		public ChannelState ChannelState { get; protected set; }

		public ChatMessage PreviousMessage { get; protected set; }

		public JoinedChannel(string channel)
		{
			Channel = channel;
		}

		public void HandleMessage(ChatMessage message)
		{
			PreviousMessage = message;
		}
	}
	public class MessageEmote
	{
		public delegate string ReplaceEmoteDelegate(MessageEmote caller);

		public enum EmoteSource
		{
			Twitch,
			FrankerFaceZ,
			BetterTwitchTv
		}

		public enum EmoteSize
		{
			Small,
			Medium,
			Large
		}

		public static readonly ReadOnlyCollection<string> TwitchEmoteUrls = new ReadOnlyCollection<string>(new string[3] { "https://static-cdn.jtvnw.net/emoticons/v1/{0}/1.0", "https://static-cdn.jtvnw.net/emoticons/v1/{0}/2.0", "https://static-cdn.jtvnw.net/emoticons/v1/{0}/3.0" });

		public static readonly ReadOnlyCollection<string> FrankerFaceZEmoteUrls = new ReadOnlyCollection<string>(new string[3] { "//cdn.frankerfacez.com/emoticon/{0}/1", "//cdn.frankerfacez.com/emoticon/{0}/2", "//cdn.frankerfacez.com/emoticon/{0}/4" });

		public static readonly ReadOnlyCollection<string> BetterTwitchTvEmoteUrls = new ReadOnlyCollection<string>(new string[3] { "//cdn.betterttv.net/emote/{0}/1x", "//cdn.betterttv.net/emote/{0}/2x", "//cdn.betterttv.net/emote/{0}/3x" });

		private readonly string _id;

		private readonly string _text;

		private readonly string _escapedText;

		private readonly EmoteSource _source;

		private readonly EmoteSize _size;

		public string Id => _id;

		public string Text => _text;

		public EmoteSource Source => _source;

		public EmoteSize Size => _size;

		public string ReplacementString => ReplacementDelegate(this);

		public static ReplaceEmoteDelegate ReplacementDelegate { get; set; } = SourceMatchingReplacementText;


		public string EscapedText => _escapedText;

		public static string SourceMatchingReplacementText(MessageEmote caller)
		{
			int size = (int)caller.Size;
			return caller.Source switch
			{
				EmoteSource.BetterTwitchTv => string.Format(BetterTwitchTvEmoteUrls[size], caller.Id), 
				EmoteSource.FrankerFaceZ => string.Format(FrankerFaceZEmoteUrls[size], caller.Id), 
				EmoteSource.Twitch => string.Format(TwitchEmoteUrls[size], caller.Id), 
				_ => caller.Text, 
			};
		}

		public MessageEmote(string id, string text, EmoteSource source = EmoteSource.Twitch, EmoteSize size = EmoteSize.Small, ReplaceEmoteDelegate replacementDelegate = null)
		{
			_id = id;
			_text = text;
			_escapedText = Regex.Escape(text);
			_source = source;
			_size = size;
			if (replacementDelegate != null)
			{
				ReplacementDelegate = replacementDelegate;
			}
		}
	}
	public class MessageEmoteCollection
	{
		public delegate bool EmoteFilterDelegate(MessageEmote emote);

		private readonly SortedList<string, MessageEmote> _emoteList;

		private const string BasePattern = "(\\b{0}\\b)";

		private string _currentPattern;

		private Regex _regex;

		private readonly EmoteFilterDelegate _preferredFilter;

		private string CurrentPattern
		{
			get
			{
				return _currentPattern;
			}
			set
			{
				if (_currentPattern == null || !_currentPattern.Equals(value))
				{
					_currentPattern = value;
					PatternChanged = true;
				}
			}
		}

		private Regex CurrentRegex
		{
			get
			{
				if (PatternChanged)
				{
					if (CurrentPattern != null)
					{
						_regex = new Regex(string.Format(CurrentPattern, ""));
						PatternChanged = false;
					}
					else
					{
						_regex = null;
					}
				}
				return _regex;
			}
		}

		private bool PatternChanged { get; set; }

		private EmoteFilterDelegate CurrentEmoteFilter { get; set; } = AllInclusiveEmoteFilter;


		public MessageEmoteCollection()
		{
			_emoteList = new SortedList<string, MessageEmote>();
			_preferredFilter = AllInclusiveEmoteFilter;
		}

		public MessageEmoteCollection(EmoteFilterDelegate preferredFilter)
			: this()
		{
			_preferredFilter = preferredFilter;
		}

		public void Add(MessageEmote emote)
		{
			if (!_emoteList.TryGetValue(emote.Text, out var _))
			{
				_emoteList.Add(emote.Text, emote);
			}
			if (CurrentPattern == null)
			{
				CurrentPattern = $"(\\b{emote.EscapedText}\\b)";
			}
			else
			{
				CurrentPattern = CurrentPattern + "|" + $"(\\b{emote.EscapedText}\\b)";
			}
		}

		public void Merge(IEnumerable<MessageEmote> emotes)
		{
			IEnumerator<MessageEmote> enumerator = emotes.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Add(enumerator.Current);
			}
			enumerator.Dispose();
		}

		public void Remove(MessageEmote emote)
		{
			if (_emoteList.ContainsKey(emote.Text))
			{
				_emoteList.Remove(emote.Text);
				string text = "(^\\(\\\\b" + emote.EscapedText + "\\\\b\\)\\|?)";
				string text2 = "(\\|\\(\\\\b" + emote.EscapedText + "\\\\b\\))";
				string text3 = Regex.Replace(CurrentPattern, text + "|" + text2, "");
				CurrentPattern = (text3.Equals("") ? null : text3);
			}
		}

		public void RemoveAll()
		{
			_emoteList.Clear();
			CurrentPattern = null;
		}

		public string ReplaceEmotes(string originalMessage, EmoteFilterDelegate del = null)
		{
			if (CurrentRegex == null)
			{
				return originalMessage;
			}
			if (del != null && del != CurrentEmoteFilter)
			{
				CurrentEmoteFilter = del;
			}
			string result = CurrentRegex.Replace(originalMessage, GetReplacementString);
			CurrentEmoteFilter = _preferredFilter;
			return result;
		}

		public static bool AllInclusiveEmoteFilter(MessageEmote emote)
		{
			return true;
		}

		public static bool TwitchOnlyEmoteFilter(MessageEmote emote)
		{
			return emote.Source == MessageEmote.EmoteSource.Twitch;
		}

		private string GetReplacementString(Match m)
		{
			if (!_emoteList.ContainsKey(m.Value))
			{
				return m.Value;
			}
			MessageEmote messageEmote = _emoteList[m.Value];
			if (!CurrentEmoteFilter(messageEmote))
			{
				return m.Value;
			}
			return messageEmote.ReplacementString;
		}
	}
	public class OutboundChatMessage
	{
		public string Channel { get; set; }

		public string Message { get; set; }

		public string Username { get; set; }

		public string ReplyToId { get; set; }

		public override string ToString()
		{
			string text = Username.ToLower();
			string text2 = Channel.ToLower();
			if (ReplyToId == null)
			{
				return ":" + text + "!" + text + "@" + text + ".tmi.twitch.tv PRIVMSG #" + text2 + " :" + Message;
			}
			return "@reply-parent-msg-id=" + ReplyToId + " PRIVMSG #" + text2 + " :" + Message;
		}
	}
	public class OutboundWhisperMessage
	{
		public string Username { get; set; }

		public string Receiver { get; set; }

		public string Message { get; set; }

		public override string ToString()
		{
			return ":" + Username + "~" + Username + "@" + Username + ".tmi.twitch.tv PRIVMSG #jtv :/w " + Receiver + " " + Message;
		}
	}
	public class OutgoingMessage
	{
		public string Channel { get; set; }

		public string Message { get; set; }

		public int Nonce { get; set; }

		public string Sender { get; set; }

		public MessageState State { get; set; }
	}
	public enum MessageState : byte
	{
		Normal,
		Queued,
		Failed
	}
	public class PrimePaidSubscriber : SubscriberBase
	{
		public PrimePaidSubscriber(IrcMessage ircMessage)
			: base(ircMessage)
		{
		}

		public PrimePaidSubscriber(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, Color color, string displayName, string emoteSet, string id, string login, string systemMessage, string msgId, string msgParamCumulativeMonths, string msgParamStreakMonths, bool msgParamShouldShareStreak, string systemMessageParsed, string resubMessage, SubscriptionPlan subscriptionPlan, string subscriptionPlanName, string roomId, string userId, bool isModerator, bool isTurbo, bool isSubscriber, bool isPartner, string tmiSentTs, UserType userType, string rawIrc, string channel, int months = 0)
			: base(badges, badgeInfo, colorHex, color, displayName, emoteSet, id, login, systemMessage, msgId, msgParamCumulativeMonths, msgParamStreakMonths, msgParamShouldShareStreak, systemMessageParsed, resubMessage, subscriptionPlan, subscriptionPlanName, roomId, userId, isModerator, isTurbo, isSubscriber, isPartner, tmiSentTs, userType, rawIrc, channel, months)
		{
		}//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)

	}
	public class RaidNotification
	{
		public List<KeyValuePair<string, string>> Badges { get; }

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public string Color { get; }

		public string DisplayName { get; }

		public string Emotes { get; }

		public string Id { get; }

		public string Login { get; }

		public bool Moderator { get; }

		public string MsgId { get; }

		public string MsgParamDisplayName { get; }

		public string MsgParamLogin { get; }

		public string MsgParamViewerCount { get; }

		public string RoomId { get; }

		public bool Subscriber { get; }

		public string SystemMsg { get; }

		public string SystemMsgParsed { get; }

		public string TmiSentTs { get; }

		public bool Turbo { get; }

		public string UserId { get; }

		public UserType UserType { get; }

		public RaidNotification(IrcMessage ircMessage)
		{
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					Badges = Helpers.ParseBadges(text);
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					Color = text;
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emotes":
					Emotes = text;
					break;
				case "login":
					Login = text;
					break;
				case "mod":
					Moderator = Helpers.ConvertToBool(text);
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "msg-param-displayName":
					MsgParamDisplayName = text;
					break;
				case "msg-param-login":
					MsgParamLogin = text;
					break;
				case "msg-param-viewerCount":
					MsgParamViewerCount = text;
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					Subscriber = Helpers.ConvertToBool(text);
					break;
				case "system-msg":
					SystemMsg = text;
					SystemMsgParsed = text.Replace("\\s", " ").Replace("\\n", "");
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "turbo":
					Turbo = Helpers.ConvertToBool(text);
					break;
				case "user-id":
					UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				}
			}
		}

		public RaidNotification(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string color, string displayName, string emotes, string id, string login, bool moderator, string msgId, string msgParamDisplayName, string msgParamLogin, string msgParamViewerCount, string roomId, bool subscriber, string systemMsg, string systemMsgParsed, string tmiSentTs, bool turbo, UserType userType, string userId)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			Badges = badges;
			BadgeInfo = badgeInfo;
			Color = color;
			DisplayName = displayName;
			Emotes = emotes;
			Id = id;
			Login = login;
			Moderator = moderator;
			MsgId = msgId;
			MsgParamDisplayName = msgParamDisplayName;
			MsgParamLogin = msgParamLogin;
			MsgParamViewerCount = msgParamViewerCount;
			RoomId = roomId;
			Subscriber = subscriber;
			SystemMsg = systemMsg;
			SystemMsgParsed = systemMsgParsed;
			TmiSentTs = tmiSentTs;
			Turbo = turbo;
			UserType = userType;
			UserId = userId;
		}
	}
	public class ReSubscriber : SubscriberBase
	{
		public int Months => monthsInternal;

		public ReSubscriber(IrcMessage ircMessage)
			: base(ircMessage)
		{
		}

		public ReSubscriber(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, Color color, string displayName, string emoteSet, string id, string login, string systemMessage, string msgId, string msgParamCumulativeMonths, string msgParamStreakMonths, bool msgParamShouldShareStreak, string systemMessageParsed, string resubMessage, SubscriptionPlan subscriptionPlan, string subscriptionPlanName, string roomId, string userId, bool isModerator, bool isTurbo, bool isSubscriber, bool isPartner, string tmiSentTs, UserType userType, string rawIrc, string channel, int months = 0)
			: base(badges, badgeInfo, colorHex, color, displayName, emoteSet, id, login, systemMessage, msgId, msgParamCumulativeMonths, msgParamStreakMonths, msgParamShouldShareStreak, systemMessageParsed, resubMessage, subscriptionPlan, subscriptionPlanName, roomId, userId, isModerator, isTurbo, isSubscriber, isPartner, tmiSentTs, userType, rawIrc, channel, months)
		{
		}//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)

	}
	public class RitualNewChatter
	{
		public List<KeyValuePair<string, string>> Badges { get; }

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public string Color { get; }

		public string DisplayName { get; }

		public string Emotes { get; }

		public string Id { get; }

		public bool IsModerator { get; }

		public bool IsSubscriber { get; }

		public bool IsTurbo { get; }

		public string Login { get; }

		public string Message { get; }

		public string MsgId { get; }

		public string MsgParamRitualName { get; }

		public string RoomId { get; }

		public string SystemMsgParsed { get; }

		public string SystemMsg { get; }

		public string TmiSentTs { get; }

		public string UserId { get; }

		public UserType UserType { get; }

		public RitualNewChatter(IrcMessage ircMessage)
		{
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			Message = ircMessage.Message;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					Badges = Helpers.ParseBadges(text);
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					Color = text;
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emotes":
					Emotes = text;
					break;
				case "id":
					Id = text;
					break;
				case "login":
					Login = text;
					break;
				case "mod":
					IsModerator = Helpers.ConvertToBool(text);
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "msg-param-ritual-name":
					MsgParamRitualName = text;
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					IsSubscriber = Helpers.ConvertToBool(text);
					break;
				case "system-msg":
					SystemMsg = text;
					SystemMsgParsed = text.Replace("\\s", " ").Replace("\\n", "");
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "turbo":
					IsTurbo = Helpers.ConvertToBool(text);
					break;
				case "user-id":
					UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				}
			}
		}
	}
	public class SentMessage
	{
		public List<KeyValuePair<string, string>> Badges { get; }

		public string Channel { get; }

		public string ColorHex { get; }

		public string DisplayName { get; }

		public string EmoteSet { get; }

		public bool IsModerator { get; }

		public bool IsSubscriber { get; }

		public string Message { get; }

		public UserType UserType { get; }

		public SentMessage(UserState state, string message)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			Badges = state.Badges;
			Channel = state.Channel;
			ColorHex = state.ColorHex;
			DisplayName = state.DisplayName;
			EmoteSet = state.EmoteSet;
			IsModerator = state.IsModerator;
			IsSubscriber = state.IsSubscriber;
			UserType = state.UserType;
			Message = message;
		}

		public SentMessage(List<KeyValuePair<string, string>> badges, string channel, string colorHex, string displayName, string emoteSet, bool isModerator, bool isSubscriber, UserType userType, string message)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Badges = badges;
			Channel = channel;
			ColorHex = colorHex;
			DisplayName = displayName;
			EmoteSet = emoteSet;
			IsModerator = isModerator;
			IsSubscriber = isSubscriber;
			UserType = userType;
			Message = message;
		}
	}
	public class Subscriber : SubscriberBase
	{
		public Subscriber(IrcMessage ircMessage)
			: base(ircMessage)
		{
		}

		public Subscriber(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, Color color, string displayName, string emoteSet, string id, string login, string systemMessage, string msgId, string msgParamCumulativeMonths, string msgParamStreakMonths, bool msgParamShouldShareStreak, string systemMessageParsed, string resubMessage, SubscriptionPlan subscriptionPlan, string subscriptionPlanName, string roomId, string userId, bool isModerator, bool isTurbo, bool isSubscriber, bool isPartner, string tmiSentTs, UserType userType, string rawIrc, string channel)
			: base(badges, badgeInfo, colorHex, color, displayName, emoteSet, id, login, systemMessage, msgId, msgParamCumulativeMonths, msgParamStreakMonths, msgParamShouldShareStreak, systemMessageParsed, resubMessage, subscriptionPlan, subscriptionPlanName, roomId, userId, isModerator, isTurbo, isSubscriber, isPartner, tmiSentTs, userType, rawIrc, channel, 0)
		{
		}//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)

	}
	public class SubscriberBase
	{
		protected readonly int monthsInternal;

		public List<KeyValuePair<string, string>> Badges { get; }

		public List<KeyValuePair<string, string>> BadgeInfo { get; }

		public string ColorHex { get; }

		public Color Color { get; }

		public string DisplayName { get; }

		public string EmoteSet { get; }

		public string Id { get; }

		public bool IsModerator { get; }

		public bool IsPartner { get; }

		public bool IsSubscriber { get; }

		public bool IsTurbo { get; }

		public string Login { get; }

		public string MsgId { get; }

		public string MsgParamCumulativeMonths { get; }

		public bool MsgParamShouldShareStreak { get; }

		public string MsgParamStreakMonths { get; }

		public string RawIrc { get; }

		public string ResubMessage { get; }

		public string RoomId { get; }

		public SubscriptionPlan SubscriptionPlan { get; }

		public string SubscriptionPlanName { get; }

		public string SystemMessage { get; }

		public string SystemMessageParsed { get; }

		public string TmiSentTs { get; }

		public string UserId { get; }

		public UserType UserType { get; }

		public string Channel { get; }

		protected SubscriberBase(IrcMessage ircMessage)
		{
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_058d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0596: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b1: Unknown result type (might be due to invalid IL or missing references)
			RawIrc = ircMessage.ToString();
			ResubMessage = ircMessage.Message;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					Badges = Helpers.ParseBadges(text);
					foreach (KeyValuePair<string, string> badge in Badges)
					{
						if (badge.Key == "partner")
						{
							IsPartner = true;
						}
					}
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					ColorHex = text;
					if (!string.IsNullOrEmpty(ColorHex))
					{
						Color = TwitchLib.Client.Models.Extensions.NetCore.ColorTranslator.FromHtml(ColorHex);
					}
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emotes":
					EmoteSet = text;
					break;
				case "id":
					Id = text;
					break;
				case "login":
					Login = text;
					break;
				case "mod":
					IsModerator = ConvertToBool(text);
					break;
				case "msg-id":
					MsgId = text;
					break;
				case "msg-param-cumulative-months":
					MsgParamCumulativeMonths = text;
					break;
				case "msg-param-streak-months":
					MsgParamStreakMonths = text;
					break;
				case "msg-param-should-share-streak":
					MsgParamShouldShareStreak = Helpers.ConvertToBool(text);
					break;
				case "msg-param-sub-plan":
					switch (text.ToLower())
					{
					case "prime":
						SubscriptionPlan = (SubscriptionPlan)1;
						break;
					case "1000":
						SubscriptionPlan = (SubscriptionPlan)2;
						break;
					case "2000":
						SubscriptionPlan = (SubscriptionPlan)3;
						break;
					case "3000":
						SubscriptionPlan = (SubscriptionPlan)4;
						break;
					default:
						throw new ArgumentOutOfRangeException("ToLower");
					}
					break;
				case "msg-param-sub-plan-name":
					SubscriptionPlanName = text.Replace("\\s", " ");
					break;
				case "room-id":
					RoomId = text;
					break;
				case "subscriber":
					IsSubscriber = ConvertToBool(text);
					break;
				case "system-msg":
					SystemMessage = text;
					SystemMessageParsed = text.Replace("\\s", " ");
					break;
				case "tmi-sent-ts":
					TmiSentTs = text;
					break;
				case "turbo":
					IsTurbo = ConvertToBool(text);
					break;
				case "user-id":
					UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				}
			}
		}

		internal SubscriberBase(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, Color color, string displayName, string emoteSet, string id, string login, string systemMessage, string msgId, string msgParamCumulativeMonths, string msgParamStreakMonths, bool msgParamShouldShareStreak, string systemMessageParsed, string resubMessage, SubscriptionPlan subscriptionPlan, string subscriptionPlanName, string roomId, string userId, bool isModerator, bool isTurbo, bool isSubscriber, bool isPartner, string tmiSentTs, UserType userType, string rawIrc, string channel, int months)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Badges = badges;
			BadgeInfo = badgeInfo;
			ColorHex = colorHex;
			Color = color;
			DisplayName = displayName;
			EmoteSet = emoteSet;
			Id = id;
			Login = login;
			MsgId = msgId;
			MsgParamCumulativeMonths = msgParamCumulativeMonths;
			MsgParamStreakMonths = msgParamStreakMonths;
			MsgParamShouldShareStreak = msgParamShouldShareStreak;
			SystemMessage = systemMessage;
			SystemMessageParsed = systemMessageParsed;
			ResubMessage = resubMessage;
			SubscriptionPlan = subscriptionPlan;
			SubscriptionPlanName = subscriptionPlanName;
			RoomId = roomId;
			UserId = UserId;
			IsModerator = isModerator;
			IsTurbo = isTurbo;
			IsSubscriber = isSubscriber;
			IsPartner = isPartner;
			TmiSentTs = tmiSentTs;
			UserType = userType;
			RawIrc = rawIrc;
			monthsInternal = months;
			UserId = userId;
			Channel = channel;
		}

		private static bool ConvertToBool(string data)
		{
			return data == "1";
		}

		public override string ToString()
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			return $"Badges: {Badges.Count}, color hex: {ColorHex}, display name: {DisplayName}, emote set: {EmoteSet}, login: {Login}, system message: {SystemMessage}, msgId: {MsgId}, msgParamCumulativeMonths: {MsgParamCumulativeMonths}" + $"msgParamStreakMonths: {MsgParamStreakMonths}, msgParamShouldShareStreak: {MsgParamShouldShareStreak}, resub message: {ResubMessage}, months: {monthsInternal}, room id: {RoomId}, user id: {UserId}, mod: {IsModerator}, turbo: {IsTurbo}, sub: {IsSubscriber}, user type: {UserType}, raw irc: {RawIrc}";
		}
	}
	public abstract class TwitchLibMessage
	{
		public List<KeyValuePair<string, string>> Badges { get; protected set; }

		public string BotUsername { get; protected set; }

		public Color Color { get; protected set; }

		public string ColorHex { get; protected set; }

		public string DisplayName { get; protected set; }

		public EmoteSet EmoteSet { get; protected set; }

		public bool IsTurbo { get; protected set; }

		public string UserId { get; protected set; }

		public string Username { get; protected set; }

		public UserType UserType { get; protected set; }

		public string RawIrcMessage { get; protected set; }
	}
	public class UserBan
	{
		public string BanReason;

		public string Channel;

		public string Username;

		public string RoomId;

		public string TargetUserId;

		public UserBan(IrcMessage ircMessage)
		{
			Channel = ircMessage.Channel;
			Username = ircMessage.Message;
			if (ircMessage.Tags.TryGetValue("ban-reason", out var value))
			{
				BanReason = value;
			}
			if (ircMessage.Tags.TryGetValue("room-id", out var value2))
			{
				RoomId = value2;
			}
			if (ircMessage.Tags.TryGetValue("target-user-id", out var value3))
			{
				TargetUserId = value3;
			}
		}

		public UserBan(string channel, string username, string banReason, string roomId, string targetUserId)
		{
			Channel = channel;
			Username = username;
			BanReason = banReason;
			RoomId = roomId;
			TargetUserId = targetUserId;
		}
	}
	public class UserState
	{
		public List<KeyValuePair<string, string>> Badges { get; } = new List<KeyValuePair<string, string>>();


		public List<KeyValuePair<string, string>> BadgeInfo { get; } = new List<KeyValuePair<string, string>>();


		public string Channel { get; }

		public string ColorHex { get; }

		public string DisplayName { get; }

		public string EmoteSet { get; }

		public string Id { get; }

		public bool IsModerator { get; }

		public bool IsSubscriber { get; }

		public UserType UserType { get; }

		public UserState(IrcMessage ircMessage)
		{
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			Channel = ircMessage.Channel;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
					Badges = Helpers.ParseBadges(text);
					break;
				case "badge-info":
					BadgeInfo = Helpers.ParseBadges(text);
					break;
				case "color":
					ColorHex = text;
					break;
				case "display-name":
					DisplayName = text;
					break;
				case "emote-sets":
					EmoteSet = text;
					break;
				case "id":
					Id = text;
					break;
				case "mod":
					IsModerator = Helpers.ConvertToBool(text);
					break;
				case "subscriber":
					IsSubscriber = Helpers.ConvertToBool(text);
					break;
				case "user-type":
					switch (text)
					{
					case "mod":
						UserType = (UserType)1;
						break;
					case "global_mod":
						UserType = (UserType)2;
						break;
					case "admin":
						UserType = (UserType)4;
						break;
					case "staff":
						UserType = (UserType)5;
						break;
					default:
						UserType = (UserType)0;
						break;
					}
					break;
				default:
					Console.WriteLine("Unaccounted for [UserState]: " + key);
					break;
				}
			}
			if (string.Equals(ircMessage.User, Channel, StringComparison.InvariantCultureIgnoreCase))
			{
				UserType = (UserType)3;
			}
		}

		public UserState(List<KeyValuePair<string, string>> badges, List<KeyValuePair<string, string>> badgeInfo, string colorHex, string displayName, string emoteSet, string channel, string id, bool isSubscriber, bool isModerator, UserType userType)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			Badges = badges;
			BadgeInfo = badgeInfo;
			ColorHex = colorHex;
			DisplayName = displayName;
			EmoteSet = emoteSet;
			Channel = channel;
			Id = id;
			IsSubscriber = isSubscriber;
			IsModerator = isModerator;
			UserType = userType;
		}
	}
	public class UserTimeout
	{
		public string Channel;

		public int TimeoutDuration;

		public string TimeoutReason;

		public string Username;

		public string TargetUserId;

		public UserTimeout(IrcMessage ircMessage)
		{
			Channel = ircMessage.Channel;
			Username = ircMessage.Message;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "ban-duration":
					TimeoutDuration = int.Parse(text);
					break;
				case "ban-reason":
					TimeoutReason = text;
					break;
				case "target-user-id":
					TargetUserId = text;
					break;
				}
			}
		}

		public UserTimeout(string channel, string username, string targetuserId, int timeoutDuration, string timeoutReason)
		{
			Channel = channel;
			Username = username;
			TargetUserId = targetuserId;
			TimeoutDuration = timeoutDuration;
			TimeoutReason = timeoutReason;
		}
	}
	public class WhisperCommand
	{
		public List<string> ArgumentsAsList { get; }

		public string ArgumentsAsString { get; }

		public char CommandIdentifier { get; }

		public string CommandText { get; }

		public WhisperMessage WhisperMessage { get; }

		public WhisperCommand(WhisperMessage whisperMessage)
		{
			WhisperCommand whisperCommand = this;
			WhisperMessage = whisperMessage;
			string[] array = whisperMessage.Message.Split(new char[1] { ' ' });
			CommandText = ((array != null) ? array[0].Substring(1, whisperMessage.Message.Split(new char[1] { ' ' })[0].Length - 1) : null) ?? whisperMessage.Message.Substring(1, whisperMessage.Message.Length - 1);
			string message = whisperMessage.Message;
			string[] array2 = whisperMessage.Message.Split(new char[1] { ' ' });
			ArgumentsAsString = message.Replace(((array2 != null) ? array2[0] : null) + " ", "");
			ArgumentsAsList = whisperMessage.Message.Split(new char[1] { ' ' })?.Where((string arg) => arg != whisperMessage.Message[0] + whisperCommand.CommandText).ToList() ?? new List<string>();
			CommandIdentifier = whisperMessage.Message[0];
		}

		public WhisperCommand(WhisperMessage whisperMessage, string commandText, string argumentsAsString, List<string> argumentsAsList, char commandIdentifier)
		{
			WhisperMessage = whisperMessage;
			CommandText = commandText;
			ArgumentsAsString = argumentsAsString;
			ArgumentsAsList = argumentsAsList;
			CommandIdentifier = commandIdentifier;
		}
	}
	public class WhisperMessage : TwitchLibMessage
	{
		public string MessageId { get; }

		public string ThreadId { get; }

		public string Message { get; }

		public WhisperMessage(List<KeyValuePair<string, string>> badges, string colorHex, Color color, string username, string displayName, EmoteSet emoteSet, string threadId, string messageId, string userId, bool isTurbo, string botUsername, string message, UserType userType)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			base.Badges = badges;
			base.ColorHex = colorHex;
			base.Color = color;
			base.Username = username;
			base.DisplayName = displayName;
			base.EmoteSet = emoteSet;
			ThreadId = threadId;
			MessageId = messageId;
			base.UserId = userId;
			base.IsTurbo = isTurbo;
			base.BotUsername = botUsername;
			Message = message;
			base.UserType = userType;
		}

		public WhisperMessage(IrcMessage ircMessage, string botUsername)
		{
			base.Username = ircMessage.User;
			base.BotUsername = botUsername;
			base.RawIrcMessage = ircMessage.ToString();
			Message = ircMessage.Message;
			foreach (string key in ircMessage.Tags.Keys)
			{
				string text = ircMessage.Tags[key];
				switch (key)
				{
				case "badges":
				{
					base.Badges = new List<KeyValuePair<string, string>>();
					if (!Enumerable.Contains(text, '/'))
					{
						break;
					}
					if (!text.Contains(","))
					{
						base.Badges.Add(new KeyValuePair<string, string>(text.Split(new char[1] { '/' })[0], text.Split(new char[1] { '/' })[1]));
						break;
					}
					string[] array = text.Split(new char[1] { ',' });
					foreach (string text2 in array)
					{
						base.Badges.Add(new KeyValuePair<string, string>(text2.Split(new char[1] { '/' })[0], text2.Split(new char[1] { '/' })[1]));
					}
					break;
				}
				case "color":
					base.ColorHex = text;
					if (!string.IsNullOrEmpty(base.ColorHex))
					{
						base.Color = TwitchLib.Client.Models.Extensions.NetCore.ColorTranslator.FromHtml(base.ColorHex);
					}
					break;
				case "display-name":
					base.DisplayName = text;
					break;
				case "emotes":
					base.EmoteSet = new EmoteSet(text, Message);
					break;
				case "message-id":
					MessageId = text;
					break;
				case "thread-id":
					ThreadId = text;
					break;
				case "turbo":
					base.IsTurbo = Helpers.ConvertToBool(text);
					break;
				case "user-id":
					base.UserId = text;
					break;
				case "user-type":
					switch (text)
					{
					case "global_mod":
						base.UserType = (UserType)2;
						break;
					case "admin":
						base.UserType = (UserType)4;
						break;
					case "staff":
						base.UserType = (UserType)5;
						break;
					default:
						base.UserType = (UserType)0;
						break;
					}
					break;
				}
			}
			if (base.EmoteSet == null)
			{
				base.EmoteSet = new EmoteSet((string)null, Message);
			}
		}
	}
}
namespace TwitchLib.Client.Models.Internal
{
	public class IrcMessage
	{
		private readonly string[] _parameters;

		public readonly string User;

		public readonly string Hostmask;

		public readonly IrcCommand Command;

		public readonly Dictionary<string, string> Tags;

		public string Channel
		{
			get
			{
				if (!Params.StartsWith("#"))
				{
					return Params;
				}
				return Params.Remove(0, 1);
			}
		}

		public string Params
		{
			get
			{
				if (_parameters == null || _parameters.Length == 0)
				{
					return "";
				}
				return _parameters[0];
			}
		}

		public string Message => Trailing;

		public string Trailing
		{
			get
			{
				if (_parameters == null || _parameters.Length <= 1)
				{
					return "";
				}
				return _parameters[_parameters.Length - 1];
			}
		}

		public IrcMessage(string user)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			_parameters = null;
			User = user;
			Hostmask = null;
			Command = (IrcCommand)0;
			Tags = null;
		}

		public IrcMessage(IrcCommand command, string[] parameters, string hostmask, Dictionary<string, string> tags = null)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			int num = hostmask.IndexOf('!');
			User = ((num != -1) ? hostmask.Substring(0, num) : hostmask);
			Hostmask = hostmask;
			_parameters = parameters;
			Command = command;
			Tags = tags;
			if ((int)command == 18 && Params.Length > 0 && Params.Contains("#"))
			{
				_parameters[0] = "#" + _parameters[0].Split(new char[1] { '#' })[1];
			}
		}

		public new string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder(32);
			if (Tags != null)
			{
				string[] array = new string[Tags.Count];
				int num = 0;
				foreach (KeyValuePair<string, string> tag in Tags)
				{
					array[num] = tag.Key + "=" + tag.Value;
					num++;
				}
				if (array.Length != 0)
				{
					stringBuilder.Append("@").Append(string.Join(";", array)).Append(" ");
				}
			}
			if (!string.IsNullOrEmpty(Hostmask))
			{
				stringBuilder.Append(":").Append(Hostmask).Append(" ");
			}
			stringBuilder.Append(((object)(IrcCommand)(ref Command)).ToString().ToUpper().Replace("RPL_", ""));
			if (_parameters.Length == 0)
			{
				return stringBuilder.ToString();
			}
			if (_parameters[0] != null && _parameters[0].Length > 0)
			{
				stringBuilder.Append(" ").Append(_parameters[0]);
			}
			if (_parameters.Length > 1 && _parameters[1] != null && _parameters[1].Length > 0)
			{
				stringBuilder.Append(" :").Append(_parameters[1]);
			}
			return stringBuilder.ToString();
		}
	}
	public static class MsgIds
	{
		public const string AlreadyBanned = "already_banned";

		public const string AlreadyEmotesOff = "already_emotes_off";

		public const string AlreadyEmotesOn = "already_emotes_on";

		public const string AlreadyR9KOff = "already_r9k_off";

		public const string AlreadyR9KOn = "already_r9k_on";

		public const string AlreadySubsOff = "already_subs_off";

		public const string AlreadySubsOn = "already_subs_on";

		public const string Announcement = "announcement";

		public const string BadUnbanNoBan = "bad_unban_no_ban";

		public const string BanSuccess = "ban_success";

		public const string ColorChanged = "color_changed";

		public const string EmoteOnlyOff = "emote_only_off";

		public const string EmoteOnlyOn = "emote_only_on";

		public const string HighlightedMessage = "highlighted-message";

		public const string ModeratorsReceived = "room_mods";

		public const string NoMods = "no_mods";

		public const string NoVIPs = "no_vips";

		public const string MsgBannedEmailAlias = "msg_banned_email_alias";

		public const string MsgChannelSuspended = "msg_channel_suspended";

		public const string MsgRequiresVerifiedPhoneNumber = "msg_requires_verified_phone_number";

		public const string MsgVerifiedEmail = "msg_verified_email";

		public const string MsgRateLimit = "msg_ratelimit";

		public const string MsgDuplicate = "msg_duplicate";

		public const string MsgR9k = "msg_r9k";

		public const string MsgFollowersOnly = "msg_followersonly";

		public const string MsgSubsOnly = "msg_subsonly";

		public const string MsgEmoteOnly = "msg_emoteonly";

		public const string MsgSuspended = "msg_suspended";

		public const string MsgBanned = "msg_banned";

		public const string MsgSlowMode = "msg_slowmode";

		public const string NoPermission = "no_permission";

		public const string PrimePaidUprade = "primepaidupgrade";

		public const string Raid = "raid";

		public const string RaidErrorSelf = "raid_error_self";

		public const string RaidNoticeMature = "raid_notice_mature";

		public const string ReSubscription = "resub";

		public const string R9KOff = "r9k_off";

		public const string R9KOn = "r9k_on";

		public const string SubGift = "subgift";

		public const string CommunitySubscription = "submysterygift";

		public const string ContinuedGiftedSubscription = "giftpaidupgrade";

		public const string Subscription = "sub";

		public const string SubsOff = "subs_off";

		public const string SubsOn = "subs_on";

		public const string TimeoutSuccess = "timeout_success";

		public const string UnbanSuccess = "unban_success";

		public const string UnrecognizedCmd = "unrecognized_cmd";

		public const string UserIntro = "user-intro";

		public const string VIPsSuccess = "vips_success";

		public const string SkipSubsModeMessage = "skip-subs-mode-message";
	}
	public static class Tags
	{
		public const string Badges = "badges";

		public const string BadgeInfo = "badge-info";

		public const string BanDuration = "ban-duration";

		public const string BanReason = "ban-reason";

		public const string BroadcasterLang = "broadcaster-lang";

		public const string Bits = "bits";

		public const string Color = "color";

		public const string CustomRewardId = "custom-reward-id";

		public const string DisplayName = "display-name";

		public const string Emotes = "emotes";

		public const string EmoteOnly = "emote-only";

		public const string EmotesSets = "emote-sets";

		public const string FirstMessage = "first-msg";

		public const string Flags = "flags";

		public const string FollowersOnly = "followers-only";

		public const string Id = "id";

		public const string Login = "login";

		public const string Mercury = "mercury";

		public const string MessageId = "message-id";

		public const string Mod = "mod";

		public const string MsgId = "msg-id";

		public const string MsgParamColor = "msg-param-color";

		public const string MsgParamDisplayname = "msg-param-displayName";

		public const string MsgParamLogin = "msg-param-login";

		public const string MsgParamCumulativeMonths = "msg-param-cumulative-months";

		public const string MsgParamMonths = "msg-param-months";

		public const string MsgParamPromoGiftTotal = "msg-param-promo-gift-total";

		public const string MsgParamPromoName = "msg-param-promo-name";

		public const string MsgParamShouldShareStreak = "msg-param-should-share-streak";

		public const string MsgParamStreakMonths = "msg-param-streak-months";

		public const string MsgParamSubPlan = "msg-param-sub-plan";

		public const string MsgParamSubPlanName = "msg-param-sub-plan-name";

		public const string MsgParamViewerCount = "msg-param-viewerCount";

		public const string MsgParamRecipientDisplayname = "msg-param-recipient-display-name";

		public const string MsgParamRecipientId = "msg-param-recipient-id";

		public const string MsgParamRecipientUsername = "msg-param-recipient-user-name";

		public const string MsgParamRitualName = "msg-param-ritual-name";

		public const string MsgParamMassGiftCount = "msg-param-mass-gift-count";

		public const string MsgParamSenderCount = "msg-param-sender-count";

		public const string MsgParamSenderLogin = "msg-param-sender-login";

		public const string MsgParamSenderName = "msg-param-sender-name";

		public const string MsgParamThreshold = "msg-param-threshold";

		public const string Noisy = "noisy";

		public const string ReplyParentDisplayName = "reply-parent-display-name";

		public const string ReplyParentMsgBody = "reply-parent-msg-body";

		public const string ReplyParentMsgId = "reply-parent-msg-id";

		public const string ReplyParentUserId = "reply-parent-user-id";

		public const string ReplyParentUserLogin = "reply-parent-user-login";

		public const string Rituals = "rituals";

		public const string RoomId = "room-id";

		public const string R9K = "r9k";

		public const string Slow = "slow";

		public const string Subscriber = "subscriber";

		public const string SubsOnly = "subs-only";

		public const string SystemMsg = "system-msg";

		public const string ThreadId = "thread-id";

		public const string TmiSentTs = "tmi-sent-ts";

		public const string Turbo = "turbo";

		public const string UserId = "user-id";

		public const string UserType = "user-type";

		public const string MsgParamMultiMonthGiftDuration = "msg-param-gift-months";

		public const string TargetUserId = "target-user-id";
	}
}
namespace TwitchLib.Client.Models.Extractors
{
	public class EmoteExtractor
	{
		public IEnumerable<Emote> Extract(string rawEmoteSetString, string message)
		{
			if (string.IsNullOrEmpty(rawEmoteSetString) || string.IsNullOrEmpty(message))
			{
				yield break;
			}
			string emoteId2;
			if (rawEmoteSetString.Contains("/"))
			{
				string[] array = rawEmoteSetString.Split(new char[1] { '/' });
				foreach (string text in array)
				{
					emoteId2 = text.Split(new char[1] { ':' })[0];
					if (text.Contains(","))
					{
						string[] array2 = text.Replace(emoteId2 + ":", "").Split(new char[1] { ',' });
						foreach (string emoteData in array2)
						{
							yield return GetEmote(emoteData, emoteId2, message);
						}
					}
					else
					{
						yield return GetEmote(text, emoteId2, message, single: true);
					}
				}
				yield break;
			}
			emoteId2 = rawEmoteSetString.Split(new char[1] { ':' })[0];
			if (rawEmoteSetString.Contains(","))
			{
				string[] array = rawEmoteSetString.Replace(emoteId2 + ":", "").Split(new char[1] { ',' });
				foreach (string emoteData2 in array)
				{
					yield return GetEmote(emoteData2, emoteId2, message);
				}
			}
			else
			{
				yield return GetEmote(rawEmoteSetString, emoteId2, message, single: true);
			}
		}

		private Emote GetEmote(string emoteData, string emoteId, string message, bool single = false)
		{
			int num = -1;
			int num2 = -1;
			if (single)
			{
				num = int.Parse(emoteData.Split(new char[1] { ':' })[1].Split(new char[1] { '-' })[0]);
				num2 = int.Parse(emoteData.Split(new char[1] { ':' })[1].Split(new char[1] { '-' })[1]);
			}
			else
			{
				num = int.Parse(emoteData.Split(new char[1] { '-' })[0]);
				num2 = int.Parse(emoteData.Split(new char[1] { '-' })[1]);
			}
			string name = message.Substring(num, num2 - num + 1);
			return EmoteBuilder.Create().WithId(emoteId).WithName(name)
				.WithStartIndex(num)
				.WithEndIndex(num2)
				.Build();
		}
	}
	public interface IExtractor<TResult>
	{
		TResult Extract(IrcMessage ircMessage);
	}
}
namespace TwitchLib.Client.Models.Extensions.NetCore
{
	public static class ColorTranslator
	{
		public static Color FromHtml(string hexColor)
		{
			hexColor += 0;
			return Color.FromArgb(int.Parse(hexColor.Replace("#", ""), NumberStyles.HexNumber));
		}
	}
}
namespace TwitchLib.Client.Models.Common
{
	public static class Helpers
	{
		public static List<string> ParseQuotesAndNonQuotes(string message)
		{
			List<string> list = new List<string>();
			if (message == "")
			{
				return new List<string>();
			}
			bool flag = message[0] != '"';
			string[] array = message.Split(new char[1] { '"' });
			foreach (string text in array)
			{
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				if (!flag)
				{
					list.Add(text);
					flag = true;
				}
				else
				{
					if (!text.Contains(" "))
					{
						continue;
					}
					string[] array2 = text.Split(new char[1] { ' ' });
					foreach (string text2 in array2)
					{
						if (!string.IsNullOrWhiteSpace(text2))
						{
							list.Add(text2);
							flag = false;
						}
					}
				}
			}
			return list;
		}

		public static List<KeyValuePair<string, string>> ParseBadges(string badgesStr)
		{
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			if (Enumerable.Contains(badgesStr, '/'))
			{
				if (!badgesStr.Contains(","))
				{
					list.Add(new KeyValuePair<string, string>(badgesStr.Split(new char[1] { '/' })[0], badgesStr.Split(new char[1] { '/' })[1]));
				}
				else
				{
					string[] array = badgesStr.Split(new char[1] { ',' });
					foreach (string text in array)
					{
						list.Add(new KeyValuePair<string, string>(text.Split(new char[1] { '/' })[0], text.Split(new char[1] { '/' })[1]));
					}
				}
			}
			return list;
		}

		public static string ParseToken(string token, string message)
		{
			string result = string.Empty;
			for (int num = message.IndexOf(token, StringComparison.InvariantCultureIgnoreCase); num > -1; num = message.IndexOf(token, num + token.Length, StringComparison.InvariantCultureIgnoreCase))
			{
				result = new string(message.Substring(num).TakeWhile((char x) => x != ';' && x != ' ').ToArray()).Split(new char[1] { '=' }).LastOrDefault();
			}
			return result;
		}

		public static bool ConvertToBool(string data)
		{
			return data == "1";
		}
	}
}
namespace TwitchLib.Client.Models.Builders
{
	public sealed class ChannelStateBuilder : IBuilder<ChannelState>, IFromIrcMessageBuilder<ChannelState>
	{
		private string _broadcasterLanguage;

		private string _channel;

		private bool _emoteOnly;

		private TimeSpan _followersOnly;

		private bool _mercury;

		private bool _r9K;

		private bool _rituals;

		private string _roomId;

		private int _slowMode;

		private bool _subOnly;

		private ChannelStateBuilder()
		{
		}

		public ChannelStateBuilder WithBroadcasterLanguage(string broadcasterLanguage)
		{
			_broadcasterLanguage = broadcasterLanguage;
			return this;
		}

		public ChannelStateBuilder WithChannel(string channel)
		{
			_channel = channel;
			return this;
		}

		public ChannelStateBuilder WithEmoteOnly(bool emoteOnly)
		{
			_emoteOnly = emoteOnly;
			return this;
		}

		public ChannelStateBuilder WIthFollowersOnly(TimeSpan followersOnly)
		{
			_followersOnly = followersOnly;
			return this;
		}

		public ChannelStateBuilder WithMercury(bool mercury)
		{
			_mercury = mercury;
			return this;
		}

		public ChannelStateBuilder WithR9K(bool r9k)
		{
			_r9K = r9k;
			return this;
		}

		public ChannelStateBuilder WithRituals(bool rituals)
		{
			_rituals = rituals;
			return this;
		}

		public ChannelStateBuilder WithRoomId(string roomId)
		{
			_roomId = roomId;
			return this;
		}

		public ChannelStateBuilder WithSlowMode(int slowMode)
		{
			_slowMode = slowMode;
			return this;
		}

		public ChannelStateBuilder WithSubOnly(bool subOnly)
		{
			_subOnly = subOnly;
			return this;
		}

		public static ChannelStateBuilder Create()
		{
			return new ChannelStateBuilder();
		}

		public ChannelState Build()
		{
			return new ChannelState(_r9K, _rituals, _subOnly, _slowMode, _emoteOnly, _broadcasterLanguage, _channel, _followersOnly, _mercury, _roomId);
		}

		public ChannelState BuildFromIrcMessage(FromIrcMessageBuilderDataObject fromIrcMessageBuilderDataObject)
		{
			return new ChannelState(fromIrcMessageBuilderDataObject.Message);
		}
	}
	public sealed class ChatCommandBuilder : IBuilder<ChatCommand>
	{
		private readonly List<string> _argumentsAsList = new List<string>();

		private string _argumentsAsString;

		private ChatMessage _chatMessage;

		private char _commandIdentifier;

		private string _commandText;

		private ChatCommandBuilder()
		{
		}

		public ChatCommandBuilder WithArgumentsAsList(params string[] argumentsList)
		{
			_argumentsAsList.AddRange(argumentsList);
			return this;
		}

		public ChatCommandBuilder WithArgumentsAsString(string argumentsAsString)
		{
			_argumentsAsString = argumentsAsString;
			return this;
		}

		public ChatCommandBuilder WithChatMessage(ChatMessage chatMessage)
		{
			_chatMessage = chatMessage;
			return this;
		}

		public ChatCommandBuilder WithCommandIdentifier(char commandIdentifier)
		{
			_commandIdentifier = commandIdentifier;
			return this;
		}

		public ChatCommandBuilder WithCommandText(string commandText)
		{
			_commandText = commandText;
			return this;
		}

		public static ChatCommandBuilder Create()
		{
			return new ChatCommandBuilder();
		}

		public ChatCommand Build()
		{
			return new ChatCommand(_chatMessage, _commandText, _argumentsAsString, _argumentsAsList, _commandIdentifier);
		}

		public ChatCommand BuildFromChatMessage(ChatMessage chatMessage)
		{
			return new ChatCommand(chatMessage);
		}
	}
	public sealed class ChatMessageBuilder : IBuilder<ChatMessage>
	{
		private TwitchLibMessage _twitchLibMessage;

		private readonly List<KeyValuePair<string, string>> BadgeInfo = new List<KeyValuePair<string, string>>();

		private int _bits;

		private double _bitsInDollars;

		private string _channel;

		private CheerBadge _cheerBadge;

		private string _emoteReplacedMessage;

		private string _id;

		private bool _isBroadcaster;

		private bool _isMe;

		private bool _isModerator;

		private bool _isSubscriber;

		private bool _isVip;

		private bool _isStaff;

		private bool _isPartner;

		private string _message;

		private Noisy _noisy;

		private string _rawIrcMessage;

		private string _roomId;

		private int _subscribedMonthCount;

		private ChatMessageBuilder()
		{
			_twitchLibMessage = TwitchLibMessageBuilder.Create().Build();
		}

		public ChatMessageBuilder WithTwitchLibMessage(TwitchLibMessage twitchLibMessage)
		{
			_twitchLibMessage = twitchLibMessage;
			return this;
		}

		public ChatMessageBuilder WithBadgeInfos(params KeyValuePair<string, string>[] badgeInfos)
		{
			BadgeInfo.AddRange(badgeInfos);
			return this;
		}

		public ChatMessageBuilder WithBits(int bits)
		{
			_bits = bits;
			return this;
		}

		public ChatMessageBuilder WithBitsInDollars(double bitsInDollars)
		{
			_bitsInDollars = bitsInDollars;
			return this;
		}

		public ChatMessageBuilder WithChannel(string channel)
		{
			_channel = channel;
			return this;
		}

		public ChatMessageBuilder WithCheerBadge(CheerBadge cheerBadge)
		{
			_cheerBadge = cheerBadge;
			return this;
		}

		public ChatMessageBuilder WithEmoteReplaceMessage(string emoteReplaceMessage)
		{
			_emoteReplacedMessage = emoteReplaceMessage;
			return this;
		}

		public ChatMessageBuilder WithId(string id)
		{
			_id = id;
			return this;
		}

		public ChatMessageBuilder WithIsBroadcaster(bool isBroadcaster)
		{
			_isBroadcaster = isBroadcaster;
			return this;
		}

		public ChatMessageBuilder WithIsMe(bool isMe)
		{
			_isMe = isMe;
			return this;
		}

		public ChatMessageBuilder WithIsModerator(bool isModerator)
		{
			_isModerator = isModerator;
			return this;
		}

		public ChatMessageBuilder WithIsSubscriber(bool isSubscriber)
		{
			_isSubscriber = isSubscriber;
			return this;
		}

		public ChatMessageBuilder WithIsVip(bool isVip)
		{
			_isVip = isVip;
			return this;
		}

		public ChatMessageBuilder WithIsStaff(bool isStaff)
		{
			_isStaff = isStaff;
			return this;
		}

		public ChatMessageBuilder WithIsPartner(bool isPartner)
		{
			_isPartner = isPartner;
			return this;
		}

		public ChatMessageBuilder WithMessage(string message)
		{
			_message = message;
			return this;
		}

		public ChatMessageBuilder WithNoisy(Noisy noisy)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_noisy = noisy;
			return this;
		}

		public ChatMessageBuilder WithRawIrcMessage(string rawIrcMessage)
		{
			_rawIrcMessage = rawIrcMessage;
			return this;
		}

		public ChatMessageBuilder WithRoomId(string roomId)
		{
			_roomId = roomId;
			return this;
		}

		public ChatMessageBuilder WithSubscribedMonthCount(int subscribedMonthCount)
		{
			_subscribedMonthCount = subscribedMonthCount;
			return this;
		}

		public static ChatMessageBuilder Create()
		{
			return new ChatMessageBuilder();
		}

		public ChatMessage Build()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			return new ChatMessage(_twitchLibMessage.BotUsername, _twitchLibMessage.UserId, _twitchLibMessage.Username, _twitchLibMessage.DisplayName, _twitchLibMessage.ColorHex, _twitchLibMessage.Color, _twitchLibMessage.EmoteSet, _message, _twitchLibMessage.UserType, _channel, _id, _isSubscriber, _subscribedMonthCount, _roomId, _twitchLibMessage.IsTurbo, _isModerator, _isMe, _isBroadcaster, _isVip, _isPartner, _isStaff, _noisy, _rawIrcMessage, _emoteReplacedMessage, _twitchLibMessage.Badges, _cheerBadge, _bits, _bitsInDollars);
		}
	}
	public sealed class CheerBadgeBuilder : IBuilder<CheerBadge>
	{
		private int _cheerAmount;

		public CheerBadgeBuilder WithCheerAmount(int cheerAmount)
		{
			_cheerAmount = cheerAmount;
			return this;
		}

		public CheerBadge Build()
		{
			return new CheerBadge(_cheerAmount);
		}
	}
	public sealed class CommunitySubscriptionBuilder : IFromIrcMessageBuilder<CommunitySubscription>
	{
		private CommunitySubscriptionBuilder()
		{
		}

		public static CommunitySubscriptionBuilder Create()
		{
			return new CommunitySubscriptionBuilder();
		}

		public CommunitySubscription BuildFromIrcMessage(FromIrcMessageBuilderDataObject fromIrcMessageBuilderDataObject)
		{
			return new CommunitySubscription(fromIrcMessageBuilderDataObject.Message);
		}
	}
	public sealed class ConnectionCredentialsBuilder : IBuilder<ConnectionCredentials>
	{
		private string _twitchUsername;

		private string _twitchOAuth;

		private string _twitchWebsocketURI = "wss://irc-ws.chat.twitch.tv:443";

		private bool _disableUsernameCheck;

		private ConnectionCredentialsBuilder()
		{
		}

		public ConnectionCredentialsBuilder WithTwitchUsername(string twitchUsername)
		{
			_twitchUsername = twitchUsername;
			return this;
		}

		public ConnectionCredentialsBuilder WithTwitchOAuth(string twitchOAuth)
		{
			_twitchOAuth = twitchOAuth;
			return this;
		}

		public ConnectionCredentialsBuilder WithTwitchWebSocketUri(string twitchWebSocketUri)
		{
			_twitchWebsocketURI = twitchWebSocketUri;
			return this;
		}

		public ConnectionCredentialsBuilder WithDisableUsernameCheck(bool disableUsernameCheck)
		{
			_disableUsernameCheck = disableUsernameCheck;
			return this;
		}

		public static ConnectionCredentialsBuilder Create()
		{
			return new ConnectionCredentialsBuilder();
		}

		public ConnectionCredentials Build()
		{
			return new ConnectionCredentials(_twitchUsername, _twitchOAuth, _twitchWebsocketURI, _disableUsernameCheck);
		}
	}
	public sealed class EmoteBuilder : IBuilder<Emote>
	{
		private string _id;

		private string _name;

		private int _startIndex;

		private int _endIndex;

		private EmoteBuilder()
		{
		}

		public static EmoteBuilder Create()
		{
			return new EmoteBuilder();
		}

		public EmoteBuilder WithId(string id)
		{
			_id = id;
			return this;
		}

		public EmoteBuilder WithName(string name)
		{
			_name = name;
			return this;
		}

		public EmoteBuilder WithStartIndex(int startIndex)
		{
			_startIndex = startIndex;
			return this;
		}

		public EmoteBuilder WithEndIndex(int endIndex)
		{
			_endIndex = endIndex;
			return this;
		}

		public Emote Build()
		{
			return new Emote(_id, _name, _startIndex, _endIndex);
		}
	}
	public sealed class ErrorEventBuilder : IBuilder<ErrorEvent>
	{
		private string _message;

		private ErrorEventBuilder()
		{
		}

		public ErrorEventBuilder WithMessage(string message)
		{
			_message = message;
			return this;
		}

		public static ErrorEventBuilder Create()
		{
			return new ErrorEventBuilder();
		}

		public ErrorEvent Build()
		{
			return new ErrorEvent
			{
				Message = _message
			};
		}
	}
	public class FromIrcMessageBuilderDataObject
	{
		public IrcMessage Message { get; set; }

		public object AditionalData { get; set; }
	}
	public sealed class GiftedSubscriptionBuilder : IBuilder<GiftedSubscription>, IFromIrcMessageBuilder<GiftedSubscription>
	{
		private readonly List<KeyValuePair<string, string>> _badges = new List<KeyValuePair<string, string>>();

		private readonly List<KeyValuePair<string, string>> _badgeInfo = new List<KeyValuePair<string, string>>();

		private string _color;

		private string _displayName;

		private string _emotes;

		private string _id;

		private bool _isModerator;

		private bool _isSubscriber;

		private bool _isTurbo;

		private string _login;

		private string _msgId;

		private string _msgParamMonths;

		private string _msgParamRecipientDisplayName;

		private string _msgParamRecipientId;

		private string _msgParamRecipientUserName;

		private string _msgParamSubPlanName;

		private string _msgParamMultiMonthGiftDuration;

		private SubscriptionPlan _msgParamSubPlan;

		private string _roomId;

		private string _systemMsg;

		private string _systemMsgParsed;

		private string _tmiSentTs;

		private string _userId;

		private UserType _userType;

		private GiftedSubscriptionBuilder()
		{
		}

		public GiftedSubscriptionBuilder WithBadges(params KeyValuePair<string, string>[] badges)
		{
			_badges.AddRange(badges);
			return this;
		}

		public GiftedSubscriptionBuilder WithBadgeInfos(params KeyValuePair<string, string>[] badgeInfos)
		{
			_badgeInfo.AddRange(badgeInfos);
			return this;
		}

		public GiftedSubscriptionBuilder WithColor(string color)
		{
			_color = color;
			return this;
		}

		public GiftedSubscriptionBuilder WithDisplayName(string displayName)
		{
			_displayName = displayName;
			return this;
		}

		public GiftedSubscriptionBuilder WithEmotes(string emotes)
		{
			_emotes = emotes;
			return this;
		}

		public GiftedSubscriptionBuilder WithId(string id)
		{
			_id = id;
			return this;
		}

		public GiftedSubscriptionBuilder WithIsModerator(bool isModerator)
		{
			_isModerator = isModerator;
			return this;
		}

		public GiftedSubscriptionBuilder WithIsSubscriber(bool isSubscriber)
		{
			_isSubscriber = isSubscriber;
			return this;
		}

		public GiftedSubscriptionBuilder WithIsTurbo(bool isTurbo)
		{
			_isTurbo = isTurbo;
			return this;
		}

		public GiftedSubscriptionBuilder WithLogin(string login)
		{
			_login = login;
			return this;
		}

		public GiftedSubscriptionBuilder WithMessageId(string msgId)
		{
			_msgId = msgId;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamCumulativeMonths(string msgParamMonths)
		{
			_msgParamMonths = msgParamMonths;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamRecipientDisplayName(string msgParamRecipientDisplayName)
		{
			_msgParamRecipientDisplayName = msgParamRecipientDisplayName;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamRecipientId(string msgParamRecipientId)
		{
			_msgParamRecipientId = msgParamRecipientId;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamRecipientUserName(string msgParamRecipientUserName)
		{
			_msgParamRecipientUserName = msgParamRecipientUserName;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamSubPlanName(string msgParamSubPlanName)
		{
			_msgParamSubPlanName = msgParamSubPlanName;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamMultiMonthGiftDuration(string msgParamMultiMonthGiftDuration)
		{
			_msgParamMultiMonthGiftDuration = msgParamMultiMonthGiftDuration;
			return this;
		}

		public GiftedSubscriptionBuilder WithMsgParamSubPlan(SubscriptionPlan msgParamSubPlan)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_msgParamSubPlan = msgParamSubPlan;
			return this;
		}

		public GiftedSubscriptionBuilder WithRoomId(string roomId)
		{
			_roomId = roomId;
			return this;
		}

		public GiftedSubscriptionBuilder WithSystemMsg(string systemMsg)
		{
			_systemMsg = systemMsg;
			return this;
		}

		public GiftedSubscriptionBuilder WithSystemMsgParsed(string systemMsgParsed)
		{
			_systemMsgParsed = systemMsgParsed;
			return this;
		}

		public GiftedSubscriptionBuilder WithTmiSentTs(string tmiSentTs)
		{
			_tmiSentTs = tmiSentTs;
			return this;
		}

		public GiftedSubscriptionBuilder WithUserId(string userId)
		{
			_userId = userId;
			return this;
		}

		public GiftedSubscriptionBuilder WithUserType(UserType userType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_userType = userType;
			return this;
		}

		public static GiftedSubscriptionBuilder Create()
		{
			return new GiftedSubscriptionBuilder();
		}

		public GiftedSubscription Build()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			return new GiftedSubscription(_badges, _badgeInfo, _color, _displayName, _emotes, _id, _login, _isModerator, _msgId, _msgParamMonths, _msgParamRecipientDisplayName, _msgParamRecipientId, _msgParamRecipientUserName, _msgParamSubPlanName, _msgParamMultiMonthGiftDuration, _msgParamSubPlan, _roomId, _isSubscriber, _systemMsg, _systemMsgParsed, _tmiSentTs, _isTurbo, _userType, _userId);
		}

		public GiftedSubscription BuildFromIrcMessage(FromIrcMessageBuilderDataObject fromIrcMessageBuilderDataObject)
		{
			return new GiftedSubscription(fromIrcMessageBuilderDataObject.Message);
		}
	}
	public interface IBuilder<T>
	{
		T Build();
	}
	public interface IFromIrcMessageBuilder<T>
	{
		T BuildFromIrcMessage(FromIrcMessageBuilderDataObject fromIrcMessageBuilderDataObject);
	}
	public sealed class IrcMessageBuilder : IBuilder<IrcMessage>
	{
		private IrcCommand _ircCommand;

		private readonly List<string> _parameters = new List<string>();

		private string _hostmask;

		private Dictionary<string, string> _tags;

		public static IrcMessageBuilder Create()
		{
			return new IrcMessageBuilder();
		}

		private IrcMessageBuilder()
		{
		}

		public IrcMessageBuilder WithCommand(IrcCommand ircCommand)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_ircCommand = ircCommand;
			return Builder();
		}

		public IrcMessageBuilder WithParameter(params string[] parameters)
		{
			_parameters.AddRange(parameters);
			return Builder();
		}

		private IrcMessageBuilder Builder()
		{
			return this;
		}

		public IrcMessage BuildWithUserOnly(string user)
		{
			return new IrcMessage(user);
		}

		public IrcMessageBuilder WithHostMask(string hostMask)
		{
			_hostmask = hostMask;
			return Builder();
		}

		public IrcMessageBuilder WithTags(Dictionary<string, string> tags)
		{
			_tags = tags;
			return Builder();
		}

		public IrcMessage Build()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return new IrcMessage(_ircCom

plugins/TwitchLib/TwitchLib.Communication.dll

Decompiled 6 months ago
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TwitchLib.Communication.Clients;
using TwitchLib.Communication.Enums;
using TwitchLib.Communication.Events;
using TwitchLib.Communication.Interfaces;
using TwitchLib.Communication.Models;
using TwitchLib.Communication.Services;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Connection library used throughout TwitchLib to replace third party depedencies.")]
[assembly: AssemblyFileVersion("1.0.4")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("TwitchLib.Communication")]
[assembly: AssemblyTitle("TwitchLib.Communication")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.Communication")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("1.0.4.0")]
namespace TwitchLib.Communication.Services
{
	public class Throttlers
	{
		public readonly BlockingCollection<Tuple<DateTime, string>> SendQueue = new BlockingCollection<Tuple<DateTime, string>>();

		public readonly BlockingCollection<Tuple<DateTime, string>> WhisperQueue = new BlockingCollection<Tuple<DateTime, string>>();

		public bool ResetThrottlerRunning;

		public bool ResetWhisperThrottlerRunning;

		public int SentCount;

		public int WhispersSent;

		public Task ResetThrottler;

		public Task ResetWhisperThrottler;

		private readonly TimeSpan _throttlingPeriod;

		private readonly TimeSpan _whisperThrottlingPeriod;

		private readonly IClient _client;

		public bool Reconnecting { get; set; }

		public bool ShouldDispose { get; set; }

		public CancellationTokenSource TokenSource { get; set; }

		public Throttlers(IClient client, TimeSpan throttlingPeriod, TimeSpan whisperThrottlingPeriod)
		{
			_throttlingPeriod = throttlingPeriod;
			_whisperThrottlingPeriod = whisperThrottlingPeriod;
			_client = client;
		}

		public void StartThrottlingWindowReset()
		{
			ResetThrottler = Task.Run(async delegate
			{
				ResetThrottlerRunning = true;
				while (!ShouldDispose && !Reconnecting)
				{
					Interlocked.Exchange(ref SentCount, 0);
					await Task.Delay(_throttlingPeriod, TokenSource.Token);
				}
				ResetThrottlerRunning = false;
				return Task.CompletedTask;
			});
		}

		public void StartWhisperThrottlingWindowReset()
		{
			ResetWhisperThrottler = Task.Run(async delegate
			{
				ResetWhisperThrottlerRunning = true;
				while (!ShouldDispose && !Reconnecting)
				{
					Interlocked.Exchange(ref WhispersSent, 0);
					await Task.Delay(_whisperThrottlingPeriod, TokenSource.Token);
				}
				ResetWhisperThrottlerRunning = false;
				return Task.CompletedTask;
			});
		}

		public void IncrementSentCount()
		{
			Interlocked.Increment(ref SentCount);
		}

		public void IncrementWhisperCount()
		{
			Interlocked.Increment(ref WhispersSent);
		}

		public Task StartSenderTask()
		{
			StartThrottlingWindowReset();
			return Task.Run(async delegate
			{
				_ = 2;
				try
				{
					while (!ShouldDispose)
					{
						await Task.Delay(_client.Options.SendDelay);
						if (SentCount == _client.Options.MessagesAllowedInPeriod)
						{
							_client.MessageThrottled(new OnMessageThrottledEventArgs
							{
								Message = "Message Throttle Occured. Too Many Messages within the period specified in WebsocketClientOptions.",
								AllowedInPeriod = _client.Options.MessagesAllowedInPeriod,
								Period = _client.Options.ThrottlingPeriod,
								SentMessageCount = Interlocked.CompareExchange(ref SentCount, 0, 0)
							});
						}
						else if (_client.IsConnected && !ShouldDispose)
						{
							Tuple<DateTime, string> msg = SendQueue.Take(TokenSource.Token);
							if (!(msg.Item1.Add(_client.Options.SendCacheItemTimeout) < DateTime.UtcNow))
							{
								try
								{
									IClient client = _client;
									if (client is WebSocketClient webSocketClient)
									{
										await webSocketClient.SendAsync(Encoding.UTF8.GetBytes(msg.Item2));
									}
									else if (client is TwitchLib.Communication.Clients.TcpClient tcpClient)
									{
										await tcpClient.SendAsync(msg.Item2);
									}
									IncrementSentCount();
								}
								catch (Exception exception)
								{
									_client.SendFailed(new OnSendFailedEventArgs
									{
										Data = msg.Item2,
										Exception = exception
									});
									break;
								}
							}
						}
					}
				}
				catch (Exception exception2)
				{
					_client.SendFailed(new OnSendFailedEventArgs
					{
						Data = "",
						Exception = exception2
					});
					_client.Error(new OnErrorEventArgs
					{
						Exception = exception2
					});
				}
			});
		}

		public Task StartWhisperSenderTask()
		{
			StartWhisperThrottlingWindowReset();
			return Task.Run(async delegate
			{
				_ = 2;
				try
				{
					while (!ShouldDispose)
					{
						await Task.Delay(_client.Options.SendDelay);
						if (WhispersSent == _client.Options.WhispersAllowedInPeriod)
						{
							_client.WhisperThrottled(new OnWhisperThrottledEventArgs
							{
								Message = "Whisper Throttle Occured. Too Many Whispers within the period specified in ClientOptions.",
								AllowedInPeriod = _client.Options.WhispersAllowedInPeriod,
								Period = _client.Options.WhisperThrottlingPeriod,
								SentWhisperCount = Interlocked.CompareExchange(ref WhispersSent, 0, 0)
							});
						}
						else if (_client.IsConnected && !ShouldDispose)
						{
							Tuple<DateTime, string> msg = WhisperQueue.Take(TokenSource.Token);
							if (!(msg.Item1.Add(_client.Options.SendCacheItemTimeout) < DateTime.UtcNow))
							{
								try
								{
									IClient client = _client;
									if (client is WebSocketClient webSocketClient)
									{
										await webSocketClient.SendAsync(Encoding.UTF8.GetBytes(msg.Item2));
									}
									else if (client is TwitchLib.Communication.Clients.TcpClient tcpClient)
									{
										await tcpClient.SendAsync(msg.Item2);
									}
									IncrementWhisperCount();
								}
								catch (Exception exception)
								{
									_client.SendFailed(new OnSendFailedEventArgs
									{
										Data = msg.Item2,
										Exception = exception
									});
									break;
								}
							}
						}
					}
				}
				catch (Exception exception2)
				{
					_client.SendFailed(new OnSendFailedEventArgs
					{
						Data = "",
						Exception = exception2
					});
					_client.Error(new OnErrorEventArgs
					{
						Exception = exception2
					});
				}
			});
		}
	}
}
namespace TwitchLib.Communication.Models
{
	public class ClientOptions : IClientOptions
	{
		public int SendQueueCapacity { get; set; } = 10000;


		public TimeSpan SendCacheItemTimeout { get; set; } = TimeSpan.FromMinutes(30.0);


		public ushort SendDelay { get; set; } = 50;


		public ReconnectionPolicy ReconnectionPolicy { get; set; } = new ReconnectionPolicy(3000, (int?)10);


		public bool UseSsl { get; set; } = true;


		public int DisconnectWait { get; set; } = 20000;


		public ClientType ClientType { get; set; }

		public TimeSpan ThrottlingPeriod { get; set; } = TimeSpan.FromSeconds(30.0);


		public int MessagesAllowedInPeriod { get; set; } = 100;


		public TimeSpan WhisperThrottlingPeriod { get; set; } = TimeSpan.FromSeconds(60.0);


		public int WhispersAllowedInPeriod { get; set; } = 100;


		public int WhisperQueueCapacity { get; set; } = 10000;

	}
	public class ReconnectionPolicy
	{
		private readonly int _reconnectStepInterval;

		private readonly int? _initMaxAttempts;

		private int _minReconnectInterval;

		private readonly int _maxReconnectInterval;

		private int? _maxAttempts;

		private int _attemptsMade;

		public ReconnectionPolicy()
		{
			_reconnectStepInterval = 3000;
			_minReconnectInterval = 3000;
			_maxReconnectInterval = 30000;
			_maxAttempts = null;
			_initMaxAttempts = null;
			_attemptsMade = 0;
		}

		public void SetMaxAttempts(int attempts)
		{
			_maxAttempts = attempts;
		}

		public void Reset()
		{
			_attemptsMade = 0;
			_minReconnectInterval = _reconnectStepInterval;
			_maxAttempts = _initMaxAttempts;
		}

		public void SetAttemptsMade(int count)
		{
			_attemptsMade = count;
		}

		public ReconnectionPolicy(int minReconnectInterval, int maxReconnectInterval, int? maxAttempts)
		{
			_reconnectStepInterval = minReconnectInterval;
			_minReconnectInterval = ((minReconnectInterval > maxReconnectInterval) ? maxReconnectInterval : minReconnectInterval);
			_maxReconnectInterval = maxReconnectInterval;
			_maxAttempts = maxAttempts;
			_initMaxAttempts = maxAttempts;
			_attemptsMade = 0;
		}

		public ReconnectionPolicy(int minReconnectInterval, int maxReconnectInterval)
		{
			_reconnectStepInterval = minReconnectInterval;
			_minReconnectInterval = ((minReconnectInterval > maxReconnectInterval) ? maxReconnectInterval : minReconnectInterval);
			_maxReconnectInterval = maxReconnectInterval;
			_maxAttempts = null;
			_initMaxAttempts = null;
			_attemptsMade = 0;
		}

		public ReconnectionPolicy(int reconnectInterval)
		{
			_reconnectStepInterval = reconnectInterval;
			_minReconnectInterval = reconnectInterval;
			_maxReconnectInterval = reconnectInterval;
			_maxAttempts = null;
			_initMaxAttempts = null;
			_attemptsMade = 0;
		}

		public ReconnectionPolicy(int reconnectInterval, int? maxAttempts)
		{
			_reconnectStepInterval = reconnectInterval;
			_minReconnectInterval = reconnectInterval;
			_maxReconnectInterval = reconnectInterval;
			_maxAttempts = maxAttempts;
			_initMaxAttempts = maxAttempts;
			_attemptsMade = 0;
		}

		internal void ProcessValues()
		{
			_attemptsMade++;
			if (_minReconnectInterval < _maxReconnectInterval)
			{
				_minReconnectInterval += _reconnectStepInterval;
			}
			if (_minReconnectInterval > _maxReconnectInterval)
			{
				_minReconnectInterval = _maxReconnectInterval;
			}
		}

		public int GetReconnectInterval()
		{
			return _minReconnectInterval;
		}

		public bool AreAttemptsComplete()
		{
			return _attemptsMade == _maxAttempts;
		}
	}
}
namespace TwitchLib.Communication.Interfaces
{
	public interface IClient
	{
		TimeSpan DefaultKeepAliveInterval { get; set; }

		int SendQueueLength { get; }

		int WhisperQueueLength { get; }

		bool IsConnected { get; }

		IClientOptions Options { get; }

		event EventHandler<OnConnectedEventArgs> OnConnected;

		event EventHandler<OnDataEventArgs> OnData;

		event EventHandler<OnDisconnectedEventArgs> OnDisconnected;

		event EventHandler<OnErrorEventArgs> OnError;

		event EventHandler<OnFatalErrorEventArgs> OnFatality;

		event EventHandler<OnMessageEventArgs> OnMessage;

		event EventHandler<OnMessageThrottledEventArgs> OnMessageThrottled;

		event EventHandler<OnWhisperThrottledEventArgs> OnWhisperThrottled;

		event EventHandler<OnSendFailedEventArgs> OnSendFailed;

		event EventHandler<OnStateChangedEventArgs> OnStateChanged;

		event EventHandler<OnReconnectedEventArgs> OnReconnected;

		void Close(bool callDisconnect = true);

		void Dispose();

		bool Open();

		bool Send(string message);

		bool SendWhisper(string message);

		void Reconnect();

		void MessageThrottled(OnMessageThrottledEventArgs eventArgs);

		void SendFailed(OnSendFailedEventArgs eventArgs);

		void Error(OnErrorEventArgs eventArgs);

		void WhisperThrottled(OnWhisperThrottledEventArgs eventArgs);
	}
	public interface IClientOptions
	{
		ClientType ClientType { get; set; }

		int DisconnectWait { get; set; }

		int MessagesAllowedInPeriod { get; set; }

		ReconnectionPolicy ReconnectionPolicy { get; set; }

		TimeSpan SendCacheItemTimeout { get; set; }

		ushort SendDelay { get; set; }

		int SendQueueCapacity { get; set; }

		TimeSpan ThrottlingPeriod { get; set; }

		bool UseSsl { get; set; }

		TimeSpan WhisperThrottlingPeriod { get; set; }

		int WhispersAllowedInPeriod { get; set; }

		int WhisperQueueCapacity { get; set; }
	}
}
namespace TwitchLib.Communication.Events
{
	public class OnConnectedEventArgs : EventArgs
	{
	}
	public class OnDataEventArgs : EventArgs
	{
		public byte[] Data;
	}
	public class OnDisconnectedEventArgs : EventArgs
	{
	}
	public class OnErrorEventArgs : EventArgs
	{
		public Exception Exception { get; set; }
	}
	public class OnFatalErrorEventArgs : EventArgs
	{
		public string Reason;
	}
	public class OnMessageEventArgs : EventArgs
	{
		public string Message;
	}
	public class OnMessageThrottledEventArgs : EventArgs
	{
		public string Message { get; set; }

		public int SentMessageCount { get; set; }

		public TimeSpan Period { get; set; }

		public int AllowedInPeriod { get; set; }
	}
	public class OnReconnectedEventArgs : EventArgs
	{
	}
	public class OnSendFailedEventArgs : EventArgs
	{
		public string Data;

		public Exception Exception;
	}
	public class OnStateChangedEventArgs : EventArgs
	{
		public bool IsConnected;

		public bool WasConnected;
	}
	public class OnWhisperThrottledEventArgs : EventArgs
	{
		public string Message { get; set; }

		public int SentWhisperCount { get; set; }

		public TimeSpan Period { get; set; }

		public int AllowedInPeriod { get; set; }
	}
}
namespace TwitchLib.Communication.Enums
{
	public enum ClientType
	{
		Chat,
		PubSub
	}
}
namespace TwitchLib.Communication.Clients
{
	public class TcpClient : IClient
	{
		private int NotConnectedCounter;

		private readonly string _server = "irc.chat.twitch.tv";

		private StreamReader _reader;

		private StreamWriter _writer;

		private readonly Throttlers _throttlers;

		private CancellationTokenSource _tokenSource = new CancellationTokenSource();

		private bool _stopServices;

		private bool _networkServicesRunning;

		private Task[] _networkTasks;

		private Task _monitorTask;

		public TimeSpan DefaultKeepAliveInterval { get; set; }

		public int SendQueueLength => _throttlers.SendQueue.Count;

		public int WhisperQueueLength => _throttlers.WhisperQueue.Count;

		public bool IsConnected => Client?.Connected ?? false;

		public IClientOptions Options { get; }

		private int Port
		{
			get
			{
				if (Options == null)
				{
					return 0;
				}
				if (!Options.UseSsl)
				{
					return 80;
				}
				return 443;
			}
		}

		public System.Net.Sockets.TcpClient Client { get; private set; }

		public event EventHandler<OnConnectedEventArgs> OnConnected;

		public event EventHandler<OnDataEventArgs> OnData;

		public event EventHandler<OnDisconnectedEventArgs> OnDisconnected;

		public event EventHandler<OnErrorEventArgs> OnError;

		public event EventHandler<OnFatalErrorEventArgs> OnFatality;

		public event EventHandler<OnMessageEventArgs> OnMessage;

		public event EventHandler<OnMessageThrottledEventArgs> OnMessageThrottled;

		public event EventHandler<OnWhisperThrottledEventArgs> OnWhisperThrottled;

		public event EventHandler<OnSendFailedEventArgs> OnSendFailed;

		public event EventHandler<OnStateChangedEventArgs> OnStateChanged;

		public event EventHandler<OnReconnectedEventArgs> OnReconnected;

		public TcpClient(IClientOptions options = null)
		{
			Options = options ?? new ClientOptions();
			_throttlers = new Throttlers(this, Options.ThrottlingPeriod, Options.WhisperThrottlingPeriod)
			{
				TokenSource = _tokenSource
			};
			InitializeClient();
		}

		private void InitializeClient()
		{
			Client = new System.Net.Sockets.TcpClient();
			if (_monitorTask == null)
			{
				_monitorTask = StartMonitorTask();
			}
			else if (_monitorTask.IsCompleted)
			{
				_monitorTask = StartMonitorTask();
			}
		}

		public bool Open()
		{
			try
			{
				if (IsConnected)
				{
					return true;
				}
				Task.Run(delegate
				{
					InitializeClient();
					Client.Connect(_server, Port);
					if (Options.UseSsl)
					{
						SslStream sslStream = new SslStream(Client.GetStream(), leaveInnerStreamOpen: false);
						sslStream.AuthenticateAsClient(_server);
						_reader = new StreamReader(sslStream);
						_writer = new StreamWriter(sslStream);
					}
					else
					{
						_reader = new StreamReader(Client.GetStream());
						_writer = new StreamWriter(Client.GetStream());
					}
				}).Wait(10000);
				if (!IsConnected)
				{
					return Open();
				}
				StartNetworkServices();
				return true;
			}
			catch (Exception)
			{
				InitializeClient();
				return false;
			}
		}

		public void Close(bool callDisconnect = true)
		{
			_reader?.Dispose();
			_writer?.Dispose();
			Client?.Close();
			_stopServices = callDisconnect;
			CleanupServices();
			InitializeClient();
			this.OnDisconnected?.Invoke(this, new OnDisconnectedEventArgs());
		}

		public void Reconnect()
		{
			Task.Run(delegate
			{
				Task.Delay(20).Wait();
				Close();
				if (Open())
				{
					this.OnReconnected?.Invoke(this, new OnReconnectedEventArgs());
				}
			});
		}

		public bool Send(string message)
		{
			try
			{
				if (!IsConnected || SendQueueLength >= Options.SendQueueCapacity)
				{
					return false;
				}
				_throttlers.SendQueue.Add(new Tuple<DateTime, string>(DateTime.UtcNow, message));
				return true;
			}
			catch (Exception exception)
			{
				this.OnError?.Invoke(this, new OnErrorEventArgs
				{
					Exception = exception
				});
				throw;
			}
		}

		public bool SendWhisper(string message)
		{
			try
			{
				if (!IsConnected || WhisperQueueLength >= Options.WhisperQueueCapacity)
				{
					return false;
				}
				_throttlers.WhisperQueue.Add(new Tuple<DateTime, string>(DateTime.UtcNow, message));
				return true;
			}
			catch (Exception exception)
			{
				this.OnError?.Invoke(this, new OnErrorEventArgs
				{
					Exception = exception
				});
				throw;
			}
		}

		private void StartNetworkServices()
		{
			_networkServicesRunning = true;
			_networkTasks = new Task[3]
			{
				StartListenerTask(),
				_throttlers.StartSenderTask(),
				_throttlers.StartWhisperSenderTask()
			}.ToArray();
			if (_networkTasks.Any((Task c) => c.IsFaulted))
			{
				_networkServicesRunning = false;
				CleanupServices();
			}
		}

		public Task SendAsync(string message)
		{
			return Task.Run(async delegate
			{
				await _writer.WriteLineAsync(message);
				await _writer.FlushAsync();
			});
		}

		private Task StartListenerTask()
		{
			return Task.Run(async delegate
			{
				while (IsConnected && _networkServicesRunning)
				{
					try
					{
						string text = await _reader.ReadLineAsync();
						if (text == null && IsConnected)
						{
							Send("PING");
							Task.Delay(500).Wait();
						}
						this.OnMessage?.Invoke(this, new OnMessageEventArgs
						{
							Message = text
						});
					}
					catch (Exception exception)
					{
						this.OnError?.Invoke(this, new OnErrorEventArgs
						{
							Exception = exception
						});
					}
				}
			});
		}

		private Task StartMonitorTask()
		{
			return Task.Run(delegate
			{
				bool flag = false;
				int num = 0;
				try
				{
					bool isConnected = IsConnected;
					while (!_tokenSource.IsCancellationRequested)
					{
						if (isConnected == IsConnected)
						{
							Thread.Sleep(200);
							if (!IsConnected)
							{
								NotConnectedCounter++;
							}
							else
							{
								num++;
							}
							if (num >= 300)
							{
								Send("PING");
								num = 0;
							}
							switch (NotConnectedCounter)
							{
							case 25:
							case 75:
							case 150:
							case 300:
							case 600:
								Reconnect();
								break;
							default:
								if (NotConnectedCounter >= 1200 && NotConnectedCounter % 600 == 0)
								{
									Reconnect();
								}
								break;
							}
							if (NotConnectedCounter != 0 && IsConnected)
							{
								NotConnectedCounter = 0;
							}
						}
						else
						{
							this.OnStateChanged?.Invoke(this, new OnStateChangedEventArgs
							{
								IsConnected = IsConnected,
								WasConnected = isConnected
							});
							if (IsConnected)
							{
								this.OnConnected?.Invoke(this, new OnConnectedEventArgs());
							}
							if (!IsConnected && !_stopServices)
							{
								if (isConnected && Options.ReconnectionPolicy != null && !Options.ReconnectionPolicy.AreAttemptsComplete())
								{
									flag = true;
									break;
								}
								this.OnDisconnected?.Invoke(this, new OnDisconnectedEventArgs());
							}
							isConnected = IsConnected;
						}
					}
				}
				catch (Exception exception)
				{
					this.OnError?.Invoke(this, new OnErrorEventArgs
					{
						Exception = exception
					});
				}
				if (flag && !_stopServices)
				{
					Reconnect();
				}
			}, _tokenSource.Token);
		}

		private void CleanupServices()
		{
			_tokenSource.Cancel();
			_tokenSource = new CancellationTokenSource();
			_throttlers.TokenSource = _tokenSource;
			if (_stopServices)
			{
				Task[] networkTasks = _networkTasks;
				if (networkTasks != null && networkTasks.Length != 0 && !Task.WaitAll(_networkTasks, 15000))
				{
					this.OnFatality?.Invoke(this, new OnFatalErrorEventArgs
					{
						Reason = "Fatal network error. Network services fail to shut down."
					});
					_stopServices = false;
					_throttlers.Reconnecting = false;
					_networkServicesRunning = false;
				}
			}
		}

		public void WhisperThrottled(OnWhisperThrottledEventArgs eventArgs)
		{
			this.OnWhisperThrottled?.Invoke(this, eventArgs);
		}

		public void MessageThrottled(OnMessageThrottledEventArgs eventArgs)
		{
			this.OnMessageThrottled?.Invoke(this, eventArgs);
		}

		public void SendFailed(OnSendFailedEventArgs eventArgs)
		{
			this.OnSendFailed?.Invoke(this, eventArgs);
		}

		public void Error(OnErrorEventArgs eventArgs)
		{
			this.OnError?.Invoke(this, eventArgs);
		}

		public void Dispose()
		{
			Close();
			_throttlers.ShouldDispose = true;
			_tokenSource.Cancel();
			Thread.Sleep(500);
			_tokenSource.Dispose();
			Client?.Dispose();
			GC.Collect();
		}
	}
	public class WebSocketClient : IClient
	{
		private int NotConnectedCounter;

		private readonly Throttlers _throttlers;

		private CancellationTokenSource _tokenSource = new CancellationTokenSource();

		private bool _stopServices;

		private bool _networkServicesRunning;

		private Task[] _networkTasks;

		private Task _monitorTask;

		public TimeSpan DefaultKeepAliveInterval { get; set; }

		public int SendQueueLength => _throttlers.SendQueue.Count;

		public int WhisperQueueLength => _throttlers.WhisperQueue.Count;

		public bool IsConnected
		{
			get
			{
				ClientWebSocket client = Client;
				if (client == null)
				{
					return false;
				}
				return client.State == WebSocketState.Open;
			}
		}

		public IClientOptions Options { get; }

		public ClientWebSocket Client { get; private set; }

		private string Url { get; }

		public event EventHandler<OnConnectedEventArgs> OnConnected;

		public event EventHandler<OnDataEventArgs> OnData;

		public event EventHandler<OnDisconnectedEventArgs> OnDisconnected;

		public event EventHandler<OnErrorEventArgs> OnError;

		public event EventHandler<OnFatalErrorEventArgs> OnFatality;

		public event EventHandler<OnMessageEventArgs> OnMessage;

		public event EventHandler<OnMessageThrottledEventArgs> OnMessageThrottled;

		public event EventHandler<OnWhisperThrottledEventArgs> OnWhisperThrottled;

		public event EventHandler<OnSendFailedEventArgs> OnSendFailed;

		public event EventHandler<OnStateChangedEventArgs> OnStateChanged;

		public event EventHandler<OnReconnectedEventArgs> OnReconnected;

		public WebSocketClient(IClientOptions options = null)
		{
			Options = options ?? new ClientOptions();
			switch (Options.ClientType)
			{
			case ClientType.Chat:
				Url = (Options.UseSsl ? "wss://irc-ws.chat.twitch.tv:443" : "ws://irc-ws.chat.twitch.tv:80");
				break;
			case ClientType.PubSub:
				Url = (Options.UseSsl ? "wss://pubsub-edge.twitch.tv:443" : "ws://pubsub-edge.twitch.tv:80");
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
			_throttlers = new Throttlers(this, Options.ThrottlingPeriod, Options.WhisperThrottlingPeriod)
			{
				TokenSource = _tokenSource
			};
		}

		private void InitializeClient()
		{
			Client?.Abort();
			Client = new ClientWebSocket();
			if (_monitorTask == null)
			{
				_monitorTask = StartMonitorTask();
			}
			else if (_monitorTask.IsCompleted)
			{
				_monitorTask = StartMonitorTask();
			}
		}

		public bool Open()
		{
			try
			{
				if (IsConnected)
				{
					return true;
				}
				InitializeClient();
				Client.ConnectAsync(new Uri(Url), _tokenSource.Token).Wait(10000);
				if (!IsConnected)
				{
					return Open();
				}
				StartNetworkServices();
				return true;
			}
			catch (WebSocketException)
			{
				InitializeClient();
				return false;
			}
		}

		public void Close(bool callDisconnect = true)
		{
			Client?.Abort();
			_stopServices = callDisconnect;
			CleanupServices();
			InitializeClient();
			this.OnDisconnected?.Invoke(this, new OnDisconnectedEventArgs());
		}

		public void Reconnect()
		{
			Task.Run(delegate
			{
				Task.Delay(20).Wait();
				Close();
				if (Open())
				{
					this.OnReconnected?.Invoke(this, new OnReconnectedEventArgs());
				}
			});
		}

		public bool Send(string message)
		{
			try
			{
				if (!IsConnected || SendQueueLength >= Options.SendQueueCapacity)
				{
					return false;
				}
				_throttlers.SendQueue.Add(new Tuple<DateTime, string>(DateTime.UtcNow, message));
				return true;
			}
			catch (Exception exception)
			{
				this.OnError?.Invoke(this, new OnErrorEventArgs
				{
					Exception = exception
				});
				throw;
			}
		}

		public bool SendWhisper(string message)
		{
			try
			{
				if (!IsConnected || WhisperQueueLength >= Options.WhisperQueueCapacity)
				{
					return false;
				}
				_throttlers.WhisperQueue.Add(new Tuple<DateTime, string>(DateTime.UtcNow, message));
				return true;
			}
			catch (Exception exception)
			{
				this.OnError?.Invoke(this, new OnErrorEventArgs
				{
					Exception = exception
				});
				throw;
			}
		}

		private void StartNetworkServices()
		{
			_networkServicesRunning = true;
			_networkTasks = new Task[3]
			{
				StartListenerTask(),
				_throttlers.StartSenderTask(),
				_throttlers.StartWhisperSenderTask()
			}.ToArray();
			if (_networkTasks.Any((Task c) => c.IsFaulted))
			{
				_networkServicesRunning = false;
				CleanupServices();
			}
		}

		public Task SendAsync(byte[] message)
		{
			return Client.SendAsync(new ArraySegment<byte>(message), WebSocketMessageType.Text, endOfMessage: true, _tokenSource.Token);
		}

		private Task StartListenerTask()
		{
			return Task.Run(async delegate
			{
				string message = "";
				while (IsConnected && _networkServicesRunning)
				{
					byte[] buffer = new byte[1024];
					WebSocketReceiveResult webSocketReceiveResult;
					try
					{
						webSocketReceiveResult = await Client.ReceiveAsync(new ArraySegment<byte>(buffer), _tokenSource.Token);
					}
					catch
					{
						InitializeClient();
						break;
					}
					if (webSocketReceiveResult != null)
					{
						switch (webSocketReceiveResult.MessageType)
						{
						case WebSocketMessageType.Close:
							Close();
							break;
						case WebSocketMessageType.Text:
							if (!webSocketReceiveResult.EndOfMessage)
							{
								message += Encoding.UTF8.GetString(buffer).TrimEnd(new char[1]);
								continue;
							}
							message += Encoding.UTF8.GetString(buffer).TrimEnd(new char[1]);
							this.OnMessage?.Invoke(this, new OnMessageEventArgs
							{
								Message = message
							});
							break;
						default:
							throw new ArgumentOutOfRangeException();
						case WebSocketMessageType.Binary:
							break;
						}
						message = "";
					}
				}
			});
		}

		private Task StartMonitorTask()
		{
			return Task.Run(delegate
			{
				bool flag = false;
				int num = 0;
				try
				{
					bool isConnected = IsConnected;
					while (!_tokenSource.IsCancellationRequested)
					{
						if (isConnected == IsConnected)
						{
							Thread.Sleep(200);
							if (!IsConnected)
							{
								NotConnectedCounter++;
							}
							else
							{
								num++;
							}
							if (num >= 300)
							{
								Send("PING");
								num = 0;
							}
							switch (NotConnectedCounter)
							{
							case 25:
							case 75:
							case 150:
							case 300:
							case 600:
								Reconnect();
								break;
							default:
								if (NotConnectedCounter >= 1200 && NotConnectedCounter % 600 == 0)
								{
									Reconnect();
								}
								break;
							}
							if (NotConnectedCounter != 0 && IsConnected)
							{
								NotConnectedCounter = 0;
							}
						}
						else
						{
							this.OnStateChanged?.Invoke(this, new OnStateChangedEventArgs
							{
								IsConnected = (Client.State == WebSocketState.Open),
								WasConnected = isConnected
							});
							if (IsConnected)
							{
								this.OnConnected?.Invoke(this, new OnConnectedEventArgs());
							}
							if (!IsConnected && !_stopServices)
							{
								if (isConnected && Options.ReconnectionPolicy != null && !Options.ReconnectionPolicy.AreAttemptsComplete())
								{
									flag = true;
									break;
								}
								this.OnDisconnected?.Invoke(this, new OnDisconnectedEventArgs());
								if (Client.CloseStatus.HasValue && Client.CloseStatus != WebSocketCloseStatus.NormalClosure)
								{
									this.OnError?.Invoke(this, new OnErrorEventArgs
									{
										Exception = new Exception(Client.CloseStatus.ToString() + " " + Client.CloseStatusDescription)
									});
								}
							}
							isConnected = IsConnected;
						}
					}
				}
				catch (Exception exception)
				{
					this.OnError?.Invoke(this, new OnErrorEventArgs
					{
						Exception = exception
					});
				}
				if (flag && !_stopServices)
				{
					Reconnect();
				}
			}, _tokenSource.Token);
		}

		private void CleanupServices()
		{
			_tokenSource.Cancel();
			_tokenSource = new CancellationTokenSource();
			_throttlers.TokenSource = _tokenSource;
			if (_stopServices)
			{
				Task[] networkTasks = _networkTasks;
				if (networkTasks != null && networkTasks.Length != 0 && !Task.WaitAll(_networkTasks, 15000))
				{
					this.OnFatality?.Invoke(this, new OnFatalErrorEventArgs
					{
						Reason = "Fatal network error. Network services fail to shut down."
					});
					_stopServices = false;
					_throttlers.Reconnecting = false;
					_networkServicesRunning = false;
				}
			}
		}

		public void WhisperThrottled(OnWhisperThrottledEventArgs eventArgs)
		{
			this.OnWhisperThrottled?.Invoke(this, eventArgs);
		}

		public void MessageThrottled(OnMessageThrottledEventArgs eventArgs)
		{
			this.OnMessageThrottled?.Invoke(this, eventArgs);
		}

		public void SendFailed(OnSendFailedEventArgs eventArgs)
		{
			this.OnSendFailed?.Invoke(this, eventArgs);
		}

		public void Error(OnErrorEventArgs eventArgs)
		{
			this.OnError?.Invoke(this, eventArgs);
		}

		public void Dispose()
		{
			Close();
			_throttlers.ShouldDispose = true;
			_tokenSource.Cancel();
			Thread.Sleep(500);
			_tokenSource.Dispose();
			Client?.Dispose();
			GC.Collect();
		}
	}
}

plugins/TwitchLib/TwitchLib.EventSub.Core.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using TwitchLib.EventSub.Core.Models.ChannelGoals;
using TwitchLib.EventSub.Core.Models.ChannelPoints;
using TwitchLib.EventSub.Core.Models.Charity;
using TwitchLib.EventSub.Core.Models.Extensions;
using TwitchLib.EventSub.Core.Models.HypeTrain;
using TwitchLib.EventSub.Core.Models.Polls;
using TwitchLib.EventSub.Core.Models.Predictions;
using TwitchLib.EventSub.Core.Models.Subscriptions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("Contains Subscription Types and Models for Twitch's EventSub system")]
[assembly: AssemblyFileVersion("2.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("TwitchLib.EventSub.Core")]
[assembly: AssemblyTitle("TwitchLib.EventSub.Core")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.EventSub.Websockets")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("2.0.0.0")]
namespace TwitchLib.EventSub.Core.SubscriptionTypes.User
{
	public class UserAuthorizationGrant
	{
		public string ClientId { get; set; } = string.Empty;


		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;

	}
	public class UserAuthorizationRevoke
	{
		public string ClientId { get; set; } = string.Empty;


		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; }

		public string UserLogin { get; set; }
	}
	public class UserUpdate
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string Email { get; set; } = string.Empty;


		public bool EmailVerified { get; set; }

		public string Description { get; set; } = string.Empty;

	}
}
namespace TwitchLib.EventSub.Core.SubscriptionTypes.Stream
{
	public class StreamOffline
	{
		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;

	}
	public class StreamOnline
	{
		public string Id { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string Type { get; set; } = string.Empty;


		public DateTimeOffset StartedAt { get; set; } = DateTimeOffset.MinValue;

	}
}
namespace TwitchLib.EventSub.Core.SubscriptionTypes.Extension
{
	public class ExtensionBitsTransactionCreate
	{
		public string Id { get; set; } = string.Empty;


		public string ExtensionClientId { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string UserId { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public BitsProduct Product { get; set; } = new BitsProduct();

	}
}
namespace TwitchLib.EventSub.Core.SubscriptionTypes.Drop
{
	public class DropEntitlementGrant
	{
		public string OrganizationId { get; set; } = string.Empty;


		public string CategoryId { get; set; } = string.Empty;


		public string CategoryName { get; set; } = string.Empty;


		public string CampaignId { get; set; } = string.Empty;


		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string EntitlementId { get; set; } = string.Empty;


		public string BenefitId { get; set; } = string.Empty;


		public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.MinValue;

	}
}
namespace TwitchLib.EventSub.Core.SubscriptionTypes.Channel
{
	public class ChannelBan
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string ModeratorUserId { get; set; } = string.Empty;


		public string ModeratorUserName { get; set; } = string.Empty;


		public string ModeratorUserLogin { get; set; } = string.Empty;


		public string Reason { get; set; } = string.Empty;


		public DateTimeOffset BannedAt { get; set; } = DateTimeOffset.MinValue;


		public DateTimeOffset? EndsAt { get; set; }

		public bool IsPermanent { get; set; }
	}
	public class ChannelCharityCampaignDonate
	{
		public string CampaignId { get; set; } = string.Empty;


		public string BroadcasterId { get; set; } = string.Empty;


		public string BroadcasterLogin { get; set; } = string.Empty;


		public string BroadcasterName { get; set; } = string.Empty;


		public string UserId { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public CharityAmount Amount { get; set; } = new CharityAmount();


		public string Currency { get; set; } = string.Empty;

	}
	public class ChannelCheer
	{
		public bool IsAnonymous { get; set; }

		public string UserId { get; set; }

		public string UserName { get; set; }

		public string UserLogin { get; set; }

		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string Message { get; set; } = string.Empty;


		public int Bits { get; set; }
	}
	public class ChannelFollow
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public DateTimeOffset FollowedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelGoalBegin : ChannelGoalBase
	{
	}
	public class ChannelGoalEnd : ChannelGoalBase
	{
		public DateTimeOffset EndedAt { get; set; } = DateTimeOffset.MinValue;


		public bool IsAchieved { get; set; }
	}
	public class ChannelGoalProgress : ChannelGoalBase
	{
	}
	public class ChannelModerator
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;

	}
	public class ChannelPointsCustomReward
	{
		public string Id { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public bool IsEnabled { get; set; }

		public bool IsPaused { get; set; }

		public bool IsInStock { get; set; }

		public string Title { get; set; } = string.Empty;


		public int Cost { get; set; }

		public string Prompt { get; set; } = string.Empty;


		public bool IsUserInputRequired { get; set; }

		public bool ShouldRedemptionsSkipRequestQueue { get; set; }

		public DateTimeOffset? CooldownExpiresAt { get; set; }

		public int? RedemptionsRedeemedCurrentStream { get; set; }

		public MaxAmountSettings MaxPerStream { get; set; } = new MaxAmountSettings();


		public MaxAmountSettings MaxPerUserPerStream { get; set; } = new MaxAmountSettings();


		public GlobalCooldownSettings GlobalCooldown { get; set; } = new GlobalCooldownSettings();


		public string BackgroundColor { get; set; } = string.Empty;


		public Dictionary<string, string> Image { get; set; }

		public Dictionary<string, string> DefaultImage { get; set; } = new Dictionary<string, string>();

	}
	public class ChannelPointsCustomRewardRedemption
	{
		public string Id { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string UserInput { get; set; } = string.Empty;


		public string Status { get; set; } = string.Empty;


		public RedemptionReward Reward { get; set; } = new RedemptionReward();


		public DateTimeOffset RedeemedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPollBegin : ChannelPollBase
	{
		public DateTimeOffset EndsAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPollEnd : ChannelPollBase
	{
		public string Status { get; set; } = string.Empty;


		public DateTimeOffset EndedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPollProgress : ChannelPollBase
	{
		public DateTimeOffset EndsAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPredictionBegin : ChannelPredictionBase
	{
		public DateTimeOffset LocksAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPredictionEnd : ChannelPredictionBase
	{
		public string Status { get; set; } = string.Empty;


		public DateTimeOffset EndedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPredictionLock : ChannelPredictionBase
	{
		public DateTimeOffset LockedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelPredictionProgress : ChannelPredictionBase
	{
		public DateTimeOffset LocksAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class ChannelRaid
	{
		public string FromBroadcasterUserId { get; set; } = string.Empty;


		public string FromBroadcasterUserName { get; set; } = string.Empty;


		public string FromBroadcasterUserLogin { get; set; } = string.Empty;


		public string ToBroadcasterUserId { get; set; } = string.Empty;


		public string ToBroadcasterUserName { get; set; } = string.Empty;


		public string ToBroadcasterUserLogin { get; set; } = string.Empty;


		public int Viewers { get; set; }
	}
	public class ChannelSubscribe
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string Tier { get; set; } = string.Empty;


		public bool IsGift { get; set; }
	}
	public class ChannelSubscriptionEnd
	{
		public string UserId { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string Tier { get; set; } = string.Empty;


		public bool IsGift { get; set; }
	}
	public class ChannelSubscriptionGift
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public int Total { get; set; }

		public string Tier { get; set; } = string.Empty;


		public int? CumulativeTotal { get; set; }

		public bool IsAnonymous { get; set; }
	}
	public class ChannelSubscriptionMessage
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string Tier { get; set; } = string.Empty;


		public SubscriptionMessage Message { get; set; } = new SubscriptionMessage();


		public int CumulativeTotal { get; set; }

		public int? StreakMonths { get; set; }

		public int DurationMonths { get; set; }
	}
	public class ChannelUnban
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string ModeratorUserId { get; set; } = string.Empty;


		public string ModeratorUserName { get; set; } = string.Empty;


		public string ModeratorUserLogin { get; set; } = string.Empty;

	}
	public class ChannelUpdate
	{
		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string Title { get; set; } = string.Empty;


		public string Language { get; set; } = string.Empty;


		public string CategoryId { get; set; } = string.Empty;


		public string CategoryName { get; set; } = string.Empty;


		public bool IsMature { get; set; }
	}
	public class HypeTrainBegin : HypeTrainBase
	{
		public int Progress { get; set; }

		public int Goal { get; set; }

		public HypeTrainContribution LastContribution { get; set; } = new HypeTrainContribution();


		public DateTimeOffset ExpiresAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class HypeTrainEnd : HypeTrainBase
	{
		public DateTimeOffset CooldownEndsAt { get; set; } = DateTimeOffset.MinValue;


		public DateTimeOffset EndedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class HypeTrainProgress : HypeTrainBase
	{
		public int Progress { get; set; }

		public int Goal { get; set; }

		public HypeTrainContribution[] LastContribution { get; set; } = Array.Empty<HypeTrainContribution>();


		public DateTimeOffset ExpiresAt { get; set; } = DateTimeOffset.MinValue;

	}
}
namespace TwitchLib.EventSub.Core.Models.Subscriptions
{
	public class SubscriptionMessage
	{
		public string Text { get; set; } = string.Empty;


		public SubscriptionMessageEmote[] Emotes { get; set; } = Array.Empty<SubscriptionMessageEmote>();

	}
	public class SubscriptionMessageEmote
	{
		public int Begin { get; set; }

		public int End { get; set; }

		public string Id { get; set; } = string.Empty;

	}
}
namespace TwitchLib.EventSub.Core.Models.Predictions
{
	public class ChannelPredictionBase
	{
		public string Id { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string Title { get; set; } = string.Empty;


		public PredictionOutcomes[] Outcomes { get; set; } = Array.Empty<PredictionOutcomes>();


		public DateTimeOffset StartedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class PredictionOutcomes
	{
		public string Id { get; set; } = string.Empty;


		public string Title { get; set; } = string.Empty;


		public string Color { get; set; } = string.Empty;


		public int? Users { get; set; }

		public int? ChannelPoints { get; set; }

		public Predictor[] TopPredictors { get; set; } = Array.Empty<Predictor>();

	}
	public class Predictor
	{
		public string UserId { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public int? ChannelPointsWon { get; set; }

		public int ChannelPointsUsed { get; set; }
	}
}
namespace TwitchLib.EventSub.Core.Models.Polls
{
	public class ChannelPollBase
	{
		public string Id { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string Title { get; set; } = string.Empty;


		public PollChoice[] Choices { get; set; } = Array.Empty<PollChoice>();


		public PollVotingSettings BitsVoting { get; set; } = new PollVotingSettings();


		public PollVotingSettings ChannelPointsVoting { get; set; } = new PollVotingSettings();


		public DateTimeOffset StartedAt { get; set; } = DateTimeOffset.MinValue;

	}
	public class PollChoice
	{
		public string Id { get; set; } = string.Empty;


		public string Title { get; set; } = string.Empty;


		public int? BitsVotes { get; set; }

		public int? ChannelPointsVotes { get; set; }

		public int? Votes { get; set; }
	}
	public class PollVotingSettings
	{
		public bool IsEnabled { get; set; }

		public int AmountPerVote { get; set; }
	}
}
namespace TwitchLib.EventSub.Core.Models.HypeTrain
{
	public class HypeTrainBase
	{
		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public int Total { get; set; }

		public HypeTrainContribution[] TopContributions { get; set; } = Array.Empty<HypeTrainContribution>();


		public DateTimeOffset StartedAt { get; set; } = DateTimeOffset.MinValue;


		public int Level { get; set; }
	}
	public class HypeTrainContribution
	{
		public string UserId { get; set; } = string.Empty;


		public string UserName { get; set; } = string.Empty;


		public string UserLogin { get; set; } = string.Empty;


		public string Type { get; set; } = string.Empty;


		public int Total { get; set; }
	}
}
namespace TwitchLib.EventSub.Core.Models.Extensions
{
	public class BitsProduct
	{
		public string Name { get; set; } = string.Empty;


		public string Sku { get; set; } = string.Empty;


		public int Bits { get; set; }

		public bool InDevelopment { get; set; }
	}
}
namespace TwitchLib.EventSub.Core.Models.Charity
{
	public class CharityAmount
	{
		public int Value { get; set; }

		public int DecimalPlaces { get; set; }
	}
}
namespace TwitchLib.EventSub.Core.Models.ChannelPoints
{
	public class GlobalCooldownSettings
	{
		public bool IsEnabled { get; set; }

		public int Seconds { get; set; }
	}
	public class MaxAmountSettings
	{
		public bool IsEnabled { get; set; }

		public int Value { get; set; }
	}
	public class RedemptionReward
	{
		public string Id { get; set; } = string.Empty;


		public string Title { get; set; } = string.Empty;


		public int Cost { get; set; }

		public string Prompt { get; set; } = string.Empty;

	}
}
namespace TwitchLib.EventSub.Core.Models.ChannelGoals
{
	public abstract class ChannelGoalBase
	{
		public string Id { get; set; } = string.Empty;


		public string BroadcasterUserId { get; set; } = string.Empty;


		public string BroadcasterUserName { get; set; } = string.Empty;


		public string BroadcasterUserLogin { get; set; } = string.Empty;


		public string Type { get; set; } = string.Empty;


		public string Description { get; set; } = string.Empty;


		public int CurrentAmount { get; set; }

		public int TargetAmount { get; set; }

		public DateTimeOffset StartedAt { get; set; } = DateTimeOffset.MinValue;

	}
}

plugins/TwitchLib/TwitchLib.EventSub.Websockets.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using TwitchLib.EventSub.Core.SubscriptionTypes.Channel;
using TwitchLib.EventSub.Core.SubscriptionTypes.Stream;
using TwitchLib.EventSub.Core.SubscriptionTypes.User;
using TwitchLib.EventSub.Websockets.Client;
using TwitchLib.EventSub.Websockets.Core.EventArgs;
using TwitchLib.EventSub.Websockets.Core.EventArgs.Channel;
using TwitchLib.EventSub.Websockets.Core.EventArgs.Stream;
using TwitchLib.EventSub.Websockets.Core.EventArgs.User;
using TwitchLib.EventSub.Websockets.Core.Handler;
using TwitchLib.EventSub.Websockets.Core.Models;
using TwitchLib.EventSub.Websockets.Core.NamingPolicies;
using TwitchLib.EventSub.Websockets.Extensions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("swiftyspiffy, Prom3theu5, Syzuna, LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("EventSub Websockets (also known as EventSockets) Client Library")]
[assembly: AssemblyFileVersion("0.0.3")]
[assembly: AssemblyInformationalVersion("0.0.3")]
[assembly: AssemblyProduct("TwitchLib.EventSub.Websockets")]
[assembly: AssemblyTitle("TwitchLib.EventSub.Websockets")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.EventSub.Websockets")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("0.0.3.0")]
namespace TwitchLib.EventSub.Websockets
{
	public class EventSubWebsocketClient
	{
		private CancellationTokenSource _cts;

		private DateTimeOffset _lastReceived = DateTimeOffset.MinValue;

		private TimeSpan _keepAliveTimeout = TimeSpan.Zero;

		private bool _reconnectRequested;

		private bool _reconnectComplete;

		private WebsocketClient _websocketClient;

		private Dictionary<string, Action<EventSubWebsocketClient, string, JsonSerializerOptions>> _handlers;

		private readonly ILogger<EventSubWebsocketClient> _logger;

		private readonly IServiceProvider _serviceProvider;

		private readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions
		{
			PropertyNameCaseInsensitive = true,
			PropertyNamingPolicy = new SnakeCaseNamingPolicy(),
			DictionaryKeyPolicy = new SnakeCaseNamingPolicy()
		};

		private const string WEBSOCKET_URL = "wss://eventsub-beta.wss.twitch.tv/ws";

		public string SessionId { get; private set; }

		public event EventHandler<WebsocketConnectedArgs> WebsocketConnected;

		public event EventHandler WebsocketDisconnected;

		public event EventHandler<ErrorOccuredArgs> ErrorOccurred;

		public event EventHandler WebsocketReconnected;

		public event EventHandler<ChannelBanArgs> ChannelBan;

		public event EventHandler<ChannelCharityCampaignDonateArgs> ChannelCharityCampaignDonate;

		public event EventHandler<ChannelCheerArgs> ChannelCheer;

		public event EventHandler<ChannelFollowArgs> ChannelFollow;

		public event EventHandler<ChannelGoalBeginArgs> ChannelGoalBegin;

		public event EventHandler<ChannelGoalEndArgs> ChannelGoalEnd;

		public event EventHandler<ChannelGoalProgressArgs> ChannelGoalProgress;

		public event EventHandler<ChannelHypeTrainBeginArgs> ChannelHypeTrainBegin;

		public event EventHandler<ChannelHypeTrainEndArgs> ChannelHypeTrainEnd;

		public event EventHandler<ChannelHypeTrainProgressArgs> ChannelHypeTrainProgress;

		public event EventHandler<ChannelModeratorArgs> ChannelModeratorAdd;

		public event EventHandler<ChannelModeratorArgs> ChannelModeratorRemove;

		public event EventHandler<ChannelPointsCustomRewardArgs> ChannelPointsCustomRewardAdd;

		public event EventHandler<ChannelPointsCustomRewardArgs> ChannelPointsCustomRewardRemove;

		public event EventHandler<ChannelPointsCustomRewardArgs> ChannelPointsCustomRewardUpdate;

		public event EventHandler<ChannelPointsCustomRewardRedemptionArgs> ChannelPointsCustomRewardRedemptionAdd;

		public event EventHandler<ChannelPointsCustomRewardRedemptionArgs> ChannelPointsCustomRewardRedemptionUpdate;

		public event EventHandler<ChannelPollBeginArgs> ChannelPollBegin;

		public event EventHandler<ChannelPollEndArgs> ChannelPollEnd;

		public event EventHandler<ChannelPollProgressArgs> ChannelPollProgress;

		public event EventHandler<ChannelPredictionBeginArgs> ChannelPredictionBegin;

		public event EventHandler<ChannelPredictionEndArgs> ChannelPredictionEnd;

		public event EventHandler<ChannelPredictionLockArgs> ChannelPredictionLock;

		public event EventHandler<ChannelPredictionProgressArgs> ChannelPredictionProgress;

		public event EventHandler<ChannelRaidArgs> ChannelRaid;

		public event EventHandler<ChannelSubscribeArgs> ChannelSubscribe;

		public event EventHandler<ChannelSubscriptionEndArgs> ChannelSubscriptionEnd;

		public event EventHandler<ChannelSubscriptionGiftArgs> ChannelSubscriptionGift;

		public event EventHandler<ChannelSubscriptionMessageArgs> ChannelSubscriptionMessage;

		public event EventHandler<ChannelUnbanArgs> ChannelUnban;

		public event EventHandler<ChannelUpdateArgs> ChannelUpdate;

		public event EventHandler<StreamOfflineArgs> StreamOffline;

		public event EventHandler<StreamOnlineArgs> StreamOnline;

		public event EventHandler<UserUpdateArgs> UserUpdate;

		public EventSubWebsocketClient(ILogger<EventSubWebsocketClient> logger, IEnumerable<INotificationHandler> handlers, IServiceProvider serviceProvider, WebsocketClient websocketClient)
		{
			_logger = logger ?? throw new ArgumentNullException("logger");
			_serviceProvider = serviceProvider ?? throw new ArgumentNullException("serviceProvider");
			_websocketClient = websocketClient ?? throw new ArgumentNullException("websocketClient");
			_websocketClient.OnDataReceived += OnDataReceived;
			_websocketClient.OnErrorOccurred += OnErrorOccurred;
			PrepareHandlers(handlers);
			_reconnectComplete = false;
			_reconnectRequested = false;
		}

		public async Task<bool> ConnectAsync(Uri url = null)
		{
			url = url ?? new Uri("wss://eventsub-beta.wss.twitch.tv/ws");
			_lastReceived = DateTimeOffset.MinValue;
			if (!(await _websocketClient.ConnectAsync(url)))
			{
				return false;
			}
			_cts = new CancellationTokenSource();
			Task.Factory.StartNew((Func<Task>)ConnectionCheckAsync, _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
			return true;
		}

		public async Task<bool> DisconnectAsync()
		{
			_cts?.Cancel();
			return await _websocketClient.DisconnectAsync();
		}

		public Task<bool> ReconnectAsync()
		{
			return ReconnectAsync(new Uri("wss://eventsub-beta.wss.twitch.tv/ws"));
		}

		private async Task<bool> ReconnectAsync(Uri url)
		{
			url = url ?? new Uri("wss://eventsub-beta.wss.twitch.tv/ws");
			if (_reconnectRequested)
			{
				WebsocketClient reconnectClient = ((_serviceProvider != null) ? _serviceProvider.GetRequiredService<WebsocketClient>() : new WebsocketClient());
				reconnectClient.OnDataReceived += OnDataReceived;
				reconnectClient.OnErrorOccurred += OnErrorOccurred;
				if (!(await reconnectClient.ConnectAsync(url)))
				{
					return false;
				}
				for (int i = 0; i < 200; i++)
				{
					if (_cts == null)
					{
						break;
					}
					if (_cts.IsCancellationRequested)
					{
						break;
					}
					if (_reconnectComplete)
					{
						WebsocketClient oldRunningClient = _websocketClient;
						_websocketClient = reconnectClient;
						if (oldRunningClient.IsConnected)
						{
							await oldRunningClient.DisconnectAsync();
						}
						oldRunningClient.Dispose();
						this.WebsocketReconnected?.Invoke(this, EventArgs.Empty);
						_reconnectRequested = false;
						_reconnectComplete = false;
						return true;
					}
					await Task.Delay(100);
				}
				_logger?.LogError("Websocket reconnect for " + SessionId + " failed!");
				return false;
			}
			if (_websocketClient.IsConnected)
			{
				await DisconnectAsync();
			}
			_websocketClient.Dispose();
			_websocketClient = ((_serviceProvider != null) ? _serviceProvider.GetRequiredService<WebsocketClient>() : new WebsocketClient());
			_websocketClient.OnDataReceived += OnDataReceived;
			_websocketClient.OnErrorOccurred += OnErrorOccurred;
			if (!(await ConnectAsync()))
			{
				return false;
			}
			this.WebsocketReconnected?.Invoke(this, EventArgs.Empty);
			return true;
		}

		private void PrepareHandlers(IEnumerable<INotificationHandler> handlers)
		{
			_handlers = _handlers ?? new Dictionary<string, Action<EventSubWebsocketClient, string, JsonSerializerOptions>>();
			foreach (INotificationHandler handler in handlers)
			{
				if (!_handlers.ContainsKey(handler.SubscriptionType))
				{
					_handlers.Add(handler.SubscriptionType, handler.Handle);
				}
			}
		}

		private async Task ConnectionCheckAsync()
		{
			while (_cts != null && _websocketClient.IsConnected && !_cts.IsCancellationRequested && (!(_lastReceived != DateTimeOffset.MinValue) || !(_keepAliveTimeout != TimeSpan.Zero) || !(_lastReceived.Add(_keepAliveTimeout) < DateTimeOffset.Now)))
			{
				await Task.Delay(TimeSpan.FromSeconds(1.0), _cts.Token);
			}
			await DisconnectAsync();
			this.WebsocketDisconnected?.Invoke(this, EventArgs.Empty);
		}

		private void OnDataReceived(object sender, DataReceivedArgs e)
		{
			_lastReceived = DateTimeOffset.Now;
			JsonDocument jsonDocument = JsonDocument.Parse(e.Message);
			string @string = jsonDocument.RootElement.GetProperty("metadata").GetProperty("message_type").GetString();
			switch (@string)
			{
			case "session_welcome":
				HandleWelcome(e.Message);
				break;
			case "session_disconnect":
				HandleDisconnect(e.Message);
				break;
			case "session_reconnect":
				HandleReconnect(e.Message);
				break;
			case "session_keepalive":
				HandleKeepAlive(e.Message);
				break;
			case "notification":
			{
				string string2 = jsonDocument.RootElement.GetProperty("metadata").GetProperty("subscription_type").GetString();
				if (string.IsNullOrWhiteSpace(string2))
				{
					this.ErrorOccurred?.Invoke(this, new ErrorOccuredArgs
					{
						Exception = new ArgumentNullException("subscriptionType"),
						Message = "Unable to determine subscription type!"
					});
				}
				else
				{
					HandleNotification(e.Message, string2);
				}
				break;
			}
			case "revocation":
				HandleRevocation(e.Message);
				break;
			default:
				_logger?.LogWarning("Unknown message type: " + @string);
				_logger?.LogDebug(e.Message);
				break;
			}
		}

		private void OnErrorOccurred(object sender, ErrorOccuredArgs e)
		{
			this.ErrorOccurred?.Invoke(this, e);
		}

		private void HandleReconnect(string message)
		{
			_logger?.LogWarning("Reconnect for " + SessionId + " requested!");
			EventSubWebsocketSessionInfoMessage data = JsonSerializer.Deserialize<EventSubWebsocketSessionInfoMessage>(message, _jsonSerializerOptions);
			_reconnectRequested = true;
			Task.Run(async () => await ReconnectAsync(new Uri(data?.Payload.Session.ReconnectUrl ?? "wss://eventsub-beta.wss.twitch.tv/ws")));
			_logger?.LogDebug(message);
		}

		private void HandleWelcome(string message)
		{
			EventSubWebsocketSessionInfoMessage eventSubWebsocketSessionInfoMessage = JsonSerializer.Deserialize<EventSubWebsocketSessionInfoMessage>(message, _jsonSerializerOptions);
			if (eventSubWebsocketSessionInfoMessage != null)
			{
				if (_reconnectRequested)
				{
					_reconnectComplete = true;
				}
				SessionId = eventSubWebsocketSessionInfoMessage.Payload.Session.Id;
				double? num = (double?)eventSubWebsocketSessionInfoMessage.Payload.Session.KeepaliveTimeoutSeconds + (double?)eventSubWebsocketSessionInfoMessage.Payload.Session.KeepaliveTimeoutSeconds * 0.2;
				_keepAliveTimeout = (num.HasValue ? TimeSpan.FromSeconds(num.Value) : TimeSpan.FromSeconds(10.0));
				this.WebsocketConnected?.Invoke(this, new WebsocketConnectedArgs
				{
					IsRequestedReconnect = _reconnectRequested
				});
				_logger?.LogDebug(message);
			}
		}

		private void HandleDisconnect(string message)
		{
			EventSubWebsocketSessionInfoMessage eventSubWebsocketSessionInfoMessage = JsonSerializer.Deserialize<EventSubWebsocketSessionInfoMessage>(message);
			if (eventSubWebsocketSessionInfoMessage != null)
			{
				_logger?.LogCritical($"Websocket {eventSubWebsocketSessionInfoMessage.Payload.Session.Id} disconnected at {eventSubWebsocketSessionInfoMessage.Payload.Session.DisconnectedAt}. Reason: {eventSubWebsocketSessionInfoMessage.Payload.Session.DisconnectReason}");
			}
			this.WebsocketDisconnected?.Invoke(this, EventArgs.Empty);
		}

		private void HandleKeepAlive(string message)
		{
			_logger?.LogDebug(message);
		}

		private void HandleNotification(string message, string subscriptionType)
		{
			if (_handlers != null && _handlers.TryGetValue(subscriptionType, out var value))
			{
				value(this, message, _jsonSerializerOptions);
			}
			_logger?.LogDebug(message);
		}

		private void HandleRevocation(string message)
		{
			if (_handlers != null && _handlers.TryGetValue("revocation", out var value))
			{
				value(this, message, _jsonSerializerOptions);
			}
			_logger?.LogDebug(message);
		}

		internal void RaiseEvent(string eventName, object args = null)
		{
			if (GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(this) is MulticastDelegate multicastDelegate)
			{
				Delegate[] invocationList = multicastDelegate.GetInvocationList();
				foreach (Delegate @delegate in invocationList)
				{
					@delegate.Method.Invoke(@delegate.Target, (args == null) ? new object[2]
					{
						this,
						EventArgs.Empty
					} : new object[2] { this, args });
				}
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler
{
	public class RevocationHandler : INotificationHandler
	{
		public string SubscriptionType => "revocation";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			EventSubNotification<object> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<object>>(jsonString.AsSpan(), serializerOptions);
			if (eventSubNotification == null)
			{
				throw new InvalidOperationException("Parsed JSON cannot be null!");
			}
			client.RaiseEvent("Revocation", new RevocationArgs
			{
				Notification = eventSubNotification
			});
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.User
{
	public class UserUpdateHandler : INotificationHandler
	{
		public string SubscriptionType => "user.update";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<UserUpdate> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<UserUpdate>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("UserUpdate", new UserUpdateArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Stream
{
	public class StreamOfflineHandler : INotificationHandler
	{
		public string SubscriptionType => "stream.offline";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<StreamOffline> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<StreamOffline>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("StreamOffline", new StreamOfflineArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class StreamOnlineHandler : INotificationHandler
	{
		public string SubscriptionType => "stream.online";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<StreamOnline> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<StreamOnline>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("StreamOnline", new StreamOnlineArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel
{
	public class ChannelUpdateHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.update";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelUpdate> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelUpdate>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelUpdate", new ChannelUpdateArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Subscription
{
	public class ChannelSubscribeHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.subscribe";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelSubscribe> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelSubscribe>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelSubscribe", new ChannelSubscribeArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelSubscriptionEndHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.subscription.end";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelSubscriptionEnd> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelSubscriptionEnd>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelSubscriptionEnd", new ChannelSubscriptionEndArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelSubscriptionGiftHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.subscription.gift";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelSubscriptionGift> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelSubscriptionGift>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelSubscriptionGift", new ChannelSubscriptionGiftArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelSubscriptionMessageHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.subscription.message";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelSubscriptionMessage> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelSubscriptionMessage>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelSubscriptionMessage", new ChannelSubscriptionMessageArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Raids
{
	public class ChannelRaidHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.raid";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelRaid> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelRaid>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelRaid", new ChannelRaidArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Predictions
{
	public class ChannelPredictionBeginHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.prediction.begin";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPredictionBegin> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPredictionBegin>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPredictionBegin", new ChannelPredictionBeginArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPredictionEndHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.prediction.end";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPredictionEnd> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPredictionEnd>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPredictionEnd", new ChannelPredictionEndArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPredictionLockBeginHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.prediction.lock";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPredictionLock> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPredictionLock>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPredictionLock", new ChannelPredictionLockArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPredictionProgressHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.prediction.progress";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPredictionProgress> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPredictionProgress>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPredictionProgress", new ChannelPredictionProgressArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Polls
{
	public class ChannelPollBeginHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.poll.begin";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPollBegin> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPollBegin>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPollBegin", new ChannelPollBeginArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPollEndHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.poll.end";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPollEnd> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPollEnd>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPollEnd", new ChannelPollEndArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPollProgressHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.poll.progress";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPollProgress> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPollProgress>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPollProgress", new ChannelPollProgressArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Moderators
{
	public class ChannelModeratorAddHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.moderator.add";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelModerator> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelModerator>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelModeratorAdd", new ChannelModeratorArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelModeratorRemoveHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.moderator.remove";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelModerator> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelModerator>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelModeratorRemove", new ChannelModeratorArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Moderation
{
	public class ChannelBanHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.ban";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelBan> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelBan>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelBan", new ChannelBanArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelUnbanHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.unban";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelUnban> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelUnban>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelUnban", new ChannelUnbanArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.HypeTrains
{
	public class ChannelHypeTrainBeginHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.hype_train.begin";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<HypeTrainBegin> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<HypeTrainBegin>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelHypeTrainBegin", new ChannelHypeTrainBeginArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelHypeTrainEndHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.hype_train.end";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<HypeTrainEnd> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<HypeTrainEnd>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelHypeTrainEnd", new ChannelHypeTrainEndArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelHypeTrainProgressHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.hype_train.progress";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<HypeTrainProgress> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<HypeTrainProgress>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelHypeTrainProgress", new ChannelHypeTrainProgressArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Goals
{
	public class ChannelGoalBeginHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.goal.begin";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelGoalBegin> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelGoalBegin>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelGoalBegin", new ChannelGoalBeginArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelGoalEndHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.goal.end";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelGoalEnd> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelGoalEnd>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelGoalEnd", new ChannelGoalEndArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelGoalProgressHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.goal.progress";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelGoalProgress> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelGoalProgress>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelGoalProgress", new ChannelGoalProgressArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Follows
{
	public class ChannelFollowHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.follow";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelFollow> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelFollow>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelFollow", new ChannelFollowArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle channel.follow notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Cheers
{
	public class ChannelCheerHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.cheer";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelCheer> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelCheer>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelCheer", new ChannelCheerArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.Charity
{
	public class ChannelCharityCampaignDonateHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.charity_campaign.donate";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelCharityCampaignDonate> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelCharityCampaignDonate>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelCharityCampaignDonate", new ChannelCharityCampaignDonateArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.ChannelPoints.Redemptions
{
	public class ChannelPointsCustomRewardRedemptionAddHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.channel_points_custom_reward_redemption.add";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPointsCustomRewardRedemption> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPointsCustomRewardRedemption>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPointsCustomRewardRedemptionAdd", new ChannelPointsCustomRewardRedemptionArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPointsCustomRewardRedemptionUpdate : INotificationHandler
	{
		public string SubscriptionType => "channel.channel_points_custom_reward_redemption.update";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPointsCustomRewardRedemption> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPointsCustomRewardRedemption>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPointsCustomRewardRedemptionUpdate", new ChannelPointsCustomRewardRedemptionArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Handler.Channel.ChannelPoints.CustomReward
{
	public class ChannelPointsCustomRewardAddHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.channel_points_custom_reward.add";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPointsCustomReward> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPointsCustomReward>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPointsCustomRewardAdd", new ChannelPointsCustomRewardArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPointsCustomRewardRemoveHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.channel_points_custom_reward.remove";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPointsCustomReward> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPointsCustomReward>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPointsCustomRewardRemove", new ChannelPointsCustomRewardArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
	public class ChannelPointsCustomRewardUpdateHandler : INotificationHandler
	{
		public string SubscriptionType => "channel.channel_points_custom_reward.update";

		public void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions)
		{
			try
			{
				EventSubNotification<ChannelPointsCustomReward> eventSubNotification = JsonSerializer.Deserialize<EventSubNotification<ChannelPointsCustomReward>>(jsonString.AsSpan(), serializerOptions);
				if (eventSubNotification == null)
				{
					throw new InvalidOperationException("Parsed JSON cannot be null!");
				}
				client.RaiseEvent("ChannelPointsCustomRewardUpdate", new ChannelPointsCustomRewardArgs
				{
					Notification = eventSubNotification
				});
			}
			catch (Exception exception)
			{
				client.RaiseEvent("ErrorOccurred", new ErrorOccuredArgs
				{
					Exception = exception,
					Message = "Error encountered while trying to handle " + SubscriptionType + " notification! Raw Json: " + jsonString
				});
			}
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Extensions
{
	public static class ServiceCollectionExtensions
	{
		private static IServiceCollection AddNotificationHandlers(this IServiceCollection services, params Type[] scanMarkers)
		{
			for (int i = 0; i < scanMarkers.Length; i++)
			{
				foreach (TypeInfo item in scanMarkers[i].Assembly.DefinedTypes.Where((TypeInfo x) => typeof(INotificationHandler).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract).ToList())
				{
					services.AddSingleton(typeof(INotificationHandler), item);
				}
			}
			return services;
		}

		public static IServiceCollection AddTwitchLibEventSubWebsockets(this IServiceCollection services)
		{
			services.TryAddTransient<WebsocketClient>();
			services.TryAddSingleton<EventSubWebsocketClient>();
			services.AddNotificationHandlers(typeof(INotificationHandler));
			return services;
		}
	}
	public static class StringExtensions
	{
		public static string ToSnakeCase(this string input)
		{
			if (string.IsNullOrWhiteSpace(input))
			{
				return string.Empty;
			}
			input = input.Trim();
			int num = input.Where((char c, int i) => c >= 'A' && c <= 'Z' && i != 0).Count();
			Span<char> span = stackalloc char[input.Length + num];
			int num2 = 0;
			int num3 = 0;
			while (num2 < span.Length)
			{
				if (num3 > 0 && input[num3] >= 'A' && input[num3] <= 'Z')
				{
					span[num2] = '_';
					span[num2 + 1] = input[num3];
					num2 += 2;
					num3++;
				}
				else
				{
					span[num2] = input[num3];
					num2++;
					num3++;
				}
			}
			return new string(span.ToArray()).ToLower();
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Core.NamingPolicies
{
	public class SnakeCaseNamingPolicy : JsonNamingPolicy
	{
		public override string ConvertName(string name)
		{
			return name.ToSnakeCase();
		}
	}
}
namespace TwitchLib.EventSub.Websockets.Core.Models
{
	public class EventSubMetadata
	{
		public string MessageId { get; set; }

		public string MessageType { get; set; }

		public DateTime MessageTimestamp { get; set; }

		public string SubscriptionType { get; set; }

		public string SubscriptionVersion { get; set; }
	}
	public class EventSubNotification<T>
	{
		public EventSubMetadata Metadata { get; set; }

		public EventSubNotificationPayload<T> Payload { get; set; }
	}
	public class EventSubNotificationPayload<T>
	{
		public EventSubTransport Transport { get; set; }

		public T Event { get; set; }
	}
	public class EventSubTransport
	{
		public string Method { get; set; }

		public string WebsocketId { get; set; }
	}
	public class EventSubWebsocketSessionInfo
	{
		public string Id { get; set; }

		public string Status { get; set; }

		public string DisconnectReason { get; set; }

		public int? KeepaliveTimeoutSeconds { get; set; }

		public string ReconnectUrl { get; set; }

		public DateTime ConnectedAt { get; set; }

		public DateTime? DisconnectedAt { get; set; }

		public DateTime? ReconnectingAt { get; set; }
	}
	public class EventSubWebsocketSessionInfoMessage
	{
		public EventSubMetadata Metadata { get; set; }

		public EventSubWebsocketSessionInfoPayload Payload { get; set; }
	}
	public class EventSubWebsocketSessionInfoPayload
	{
		public EventSubWebsocketSessionInfo Session { get; set; }
	}
}
namespace TwitchLib.EventSub.Websockets.Core.Handler
{
	public interface INotificationHandler
	{
		string SubscriptionType { get; }

		void Handle(EventSubWebsocketClient client, string jsonString, JsonSerializerOptions serializerOptions);
	}
}
namespace TwitchLib.EventSub.Websockets.Core.EventArgs
{
	internal class DataReceivedArgs : System.EventArgs
	{
		public string Message { get; internal set; }
	}
	public class ErrorOccuredArgs : System.EventArgs
	{
		public Exception Exception { get; internal set; }

		public string Message { get; internal set; }
	}
	public class RevocationArgs : TwitchLibEventSubEventArgs<EventSubNotification<object>>
	{
	}
	public abstract class TwitchLibEventSubEventArgs<T> : System.EventArgs where T : new()
	{
		public T Notification { get; set; } = new T();

	}
	public class WebsocketConnectedArgs : System.EventArgs
	{
		public bool IsRequestedReconnect { get; set; }
	}
	public class WebsocketDisconnectedArgs : System.EventArgs
	{
		public WebSocketCloseStatus CloseStatus { get; set; }

		public string CloseStatusDescription { get; set; }
	}
}
namespace TwitchLib.EventSub.Websockets.Core.EventArgs.User
{
	public class UserUpdateArgs : TwitchLibEventSubEventArgs<EventSubNotification<UserUpdate>>
	{
	}
}
namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Stream
{
	public class StreamOfflineArgs : TwitchLibEventSubEventArgs<EventSubNotification<StreamOffline>>
	{
	}
	public class StreamOnlineArgs : TwitchLibEventSubEventArgs<EventSubNotification<StreamOnline>>
	{
	}
}
namespace TwitchLib.EventSub.Websockets.Core.EventArgs.Channel
{
	public class ChannelBanArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelBan>>
	{
	}
	public class ChannelCharityCampaignDonateArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelCharityCampaignDonate>>
	{
	}
	public class ChannelCheerArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelCheer>>
	{
	}
	public class ChannelFollowArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelFollow>>
	{
	}
	public class ChannelGoalBeginArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelGoalBegin>>
	{
	}
	public class ChannelGoalEndArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelGoalEnd>>
	{
	}
	public class ChannelGoalProgressArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelGoalProgress>>
	{
	}
	public class ChannelHypeTrainBeginArgs : TwitchLibEventSubEventArgs<EventSubNotification<HypeTrainBegin>>
	{
	}
	public class ChannelHypeTrainEndArgs : TwitchLibEventSubEventArgs<EventSubNotification<HypeTrainEnd>>
	{
	}
	public class ChannelHypeTrainProgressArgs : TwitchLibEventSubEventArgs<EventSubNotification<HypeTrainProgress>>
	{
	}
	public class ChannelModeratorArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelModerator>>
	{
	}
	public class ChannelPointsCustomRewardArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPointsCustomReward>>
	{
	}
	public class ChannelPointsCustomRewardRedemptionArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPointsCustomRewardRedemption>>
	{
	}
	public class ChannelPollBeginArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPollBegin>>
	{
	}
	public class ChannelPollEndArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPollEnd>>
	{
	}
	public class ChannelPollProgressArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPollProgress>>
	{
	}
	public class ChannelPredictionBeginArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPredictionBegin>>
	{
	}
	public class ChannelPredictionEndArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPredictionEnd>>
	{
	}
	public class ChannelPredictionLockArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPredictionLock>>
	{
	}
	public class ChannelPredictionProgressArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelPredictionProgress>>
	{
	}
	public class ChannelRaidArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelRaid>>
	{
	}
	public class ChannelSubscribeArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelSubscribe>>
	{
	}
	public class ChannelSubscriptionEndArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelSubscriptionEnd>>
	{
	}
	public class ChannelSubscriptionGiftArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelSubscriptionGift>>
	{
	}
	public class ChannelSubscriptionMessageArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelSubscriptionMessage>>
	{
	}
	public class ChannelUnbanArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelUnban>>
	{
	}
	public class ChannelUpdateArgs : TwitchLibEventSubEventArgs<EventSubNotification<ChannelUpdate>>
	{
	}
}
namespace TwitchLib.EventSub.Websockets.Client
{
	public class WebsocketClient : IDisposable
	{
		private readonly ClientWebSocket _webSocket;

		private readonly ILogger<WebsocketClient> _logger;

		public bool IsConnected => _webSocket.State == WebSocketState.Open;

		public bool IsFaulted
		{
			get
			{
				if (_webSocket.CloseStatus != WebSocketCloseStatus.Empty)
				{
					return _webSocket.CloseStatus != WebSocketCloseStatus.NormalClosure;
				}
				return false;
			}
		}

		internal event EventHandler<DataReceivedArgs> OnDataReceived;

		internal event EventHandler<ErrorOccuredArgs> OnErrorOccurred;

		public WebsocketClient(ILogger<WebsocketClient> logger = null)
		{
			_webSocket = new ClientWebSocket();
			_logger = logger;
		}

		public async Task<bool> ConnectAsync(Uri url)
		{
			try
			{
				if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
				{
					return true;
				}
				await _webSocket.ConnectAsync(url, CancellationToken.None);
				Task.Run(async delegate
				{
					await ProcessDataAsync();
				});
				return IsConnected;
			}
			catch (Exception exception)
			{
				this.OnErrorOccurred?.Invoke(this, new ErrorOccuredArgs
				{
					Exception = exception
				});
				return false;
			}
		}

		public async Task<bool> DisconnectAsync()
		{
			try
			{
				if (_webSocket.State == WebSocketState.Open || _webSocket.State == WebSocketState.Connecting)
				{
					await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
				}
				return true;
			}
			catch (Exception exception)
			{
				this.OnErrorOccurred?.Invoke(this, new ErrorOccuredArgs
				{
					Exception = exception
				});
				return false;
			}
		}

		private async Task ProcessDataAsync()
		{
			ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[8192]);
			int payloadSize = 0;
			while (IsConnected)
			{
				try
				{
					MemoryStream memory = new MemoryStream();
					WebSocketReceiveResult webSocketReceiveResult;
					do
					{
						webSocketReceiveResult = await _webSocket.ReceiveAsync(buffer, CancellationToken.None);
						if (buffer.Array != null)
						{
							memory.Write(buffer.Array, buffer.Offset, webSocketReceiveResult.Count);
							payloadSize += webSocketReceiveResult.Count;
						}
					}
					while (!webSocketReceiveResult.EndOfMessage);
					switch (webSocketReceiveResult.MessageType)
					{
					case WebSocketMessageType.Text:
						if (payloadSize != 0)
						{
							memory.Seek(0L, SeekOrigin.Begin);
							StreamReader reader = new StreamReader(memory, Encoding.UTF8);
							EventHandler<DataReceivedArgs> onDataReceived = this.OnDataReceived;
							if (onDataReceived != null)
							{
								object sender = this;
								DataReceivedArgs dataReceivedArgs = new DataReceivedArgs();
								DataReceivedArgs dataReceivedArgs2 = dataReceivedArgs;
								dataReceivedArgs2.Message = await reader.ReadToEndAsync();
								onDataReceived(sender, dataReceivedArgs);
							}
							memory.Dispose();
							reader.Dispose();
						}
						break;
					case WebSocketMessageType.Close:
						if (_webSocket.CloseStatus.HasValue)
						{
							_logger?.LogCritical($"{_webSocket.CloseStatus.Value} - {_webSocket.CloseStatusDescription}");
						}
						break;
					default:
						throw new ArgumentOutOfRangeException();
					case WebSocketMessageType.Binary:
						break;
					}
				}
				catch (Exception exception)
				{
					this.OnErrorOccurred?.Invoke(this, new ErrorOccuredArgs
					{
						Exception = exception
					});
					break;
				}
			}
		}

		public void Dispose()
		{
			GC.SuppressFinalize(this);
			_webSocket.Dispose();
		}
	}
}

plugins/TwitchLib/TwitchLib.PubSub.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Timers;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TwitchLib.Communication.Clients;
using TwitchLib.Communication.Enums;
using TwitchLib.Communication.Events;
using TwitchLib.Communication.Interfaces;
using TwitchLib.Communication.Models;
using TwitchLib.PubSub.Common;
using TwitchLib.PubSub.Enums;
using TwitchLib.PubSub.Events;
using TwitchLib.PubSub.Extensions;
using TwitchLib.PubSub.Interfaces;
using TwitchLib.PubSub.Models;
using TwitchLib.PubSub.Models.Responses;
using TwitchLib.PubSub.Models.Responses.Messages;
using TwitchLib.PubSub.Models.Responses.Messages.AutomodCaughtMessage;
using TwitchLib.PubSub.Models.Responses.Messages.Redemption;
using TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotifications;
using TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotificationsTypes;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("swiftyspiffy,Prom3theu5,Syzuna,LuckyNoS7evin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2022")]
[assembly: AssemblyDescription("PubSub component of TwitchLib. This component allows you to access Twitch's PubSub event system and subscribe/unsubscribe from topics.")]
[assembly: AssemblyFileVersion("3.2.6")]
[assembly: AssemblyInformationalVersion("3.2.6")]
[assembly: AssemblyProduct("TwitchLib.PubSub")]
[assembly: AssemblyTitle("TwitchLib.PubSub")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/TwitchLib/TwitchLib.PubSub")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("3.2.6.0")]
namespace TwitchLib.PubSub
{
	public class TwitchPubSub : ITwitchPubSub
	{
		private readonly WebSocketClient _socket;

		private readonly List<PreviousRequest> _previousRequests = new List<PreviousRequest>();

		private readonly Semaphore _previousRequestsSemaphore = new Semaphore(1, 1);

		private readonly ILogger<TwitchPubSub> _logger;

		private readonly System.Timers.Timer _pingTimer = new System.Timers.Timer();

		private readonly System.Timers.Timer _pongTimer = new System.Timers.Timer();

		private bool _pongReceived;

		private readonly List<string> _topicList = new List<string>();

		private readonly Dictionary<string, string> _topicToChannelId = new Dictionary<string, string>();

		private static readonly Random Random = new Random();

		public event EventHandler OnPubSubServiceConnected;

		public event EventHandler<OnPubSubServiceErrorArgs> OnPubSubServiceError;

		public event EventHandler OnPubSubServiceClosed;

		public event EventHandler<OnListenResponseArgs> OnListenResponse;

		public event EventHandler<OnTimeoutArgs> OnTimeout;

		public event EventHandler<OnBanArgs> OnBan;

		public event EventHandler<OnMessageDeletedArgs> OnMessageDeleted;

		public event EventHandler<OnUnbanArgs> OnUnban;

		public event EventHandler<OnUntimeoutArgs> OnUntimeout;

		public event EventHandler<OnHostArgs> OnHost;

		public event EventHandler<OnSubscribersOnlyArgs> OnSubscribersOnly;

		public event EventHandler<OnSubscribersOnlyOffArgs> OnSubscribersOnlyOff;

		public event EventHandler<OnClearArgs> OnClear;

		public event EventHandler<OnEmoteOnlyArgs> OnEmoteOnly;

		public event EventHandler<OnEmoteOnlyOffArgs> OnEmoteOnlyOff;

		public event EventHandler<OnR9kBetaArgs> OnR9kBeta;

		public event EventHandler<OnR9kBetaOffArgs> OnR9kBetaOff;

		public event EventHandler<OnBitsReceivedArgs> OnBitsReceived;

		public event EventHandler<OnBitsReceivedV2Args> OnBitsReceivedV2;

		public event EventHandler<OnStreamUpArgs> OnStreamUp;

		public event EventHandler<OnStreamDownArgs> OnStreamDown;

		public event EventHandler<OnViewCountArgs> OnViewCount;

		public event EventHandler<OnWhisperArgs> OnWhisper;

		public event EventHandler<OnChannelSubscriptionArgs> OnChannelSubscription;

		public event EventHandler<OnChannelExtensionBroadcastArgs> OnChannelExtensionBroadcast;

		public event EventHandler<OnFollowArgs> OnFollow;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		public event EventHandler<OnCustomRewardCreatedArgs> OnCustomRewardCreated;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		public event EventHandler<OnCustomRewardUpdatedArgs> OnCustomRewardUpdated;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		public event EventHandler<OnCustomRewardDeletedArgs> OnCustomRewardDeleted;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic. Consider using OnChannelPointsRewardRedeemed", false)]
		public event EventHandler<OnRewardRedeemedArgs> OnRewardRedeemed;

		public event EventHandler<OnChannelPointsRewardRedeemedArgs> OnChannelPointsRewardRedeemed;

		public event EventHandler<OnLeaderboardEventArgs> OnLeaderboardSubs;

		public event EventHandler<OnLeaderboardEventArgs> OnLeaderboardBits;

		public event EventHandler<OnRaidUpdateArgs> OnRaidUpdate;

		public event EventHandler<OnRaidUpdateV2Args> OnRaidUpdateV2;

		public event EventHandler<OnRaidGoArgs> OnRaidGo;

		public event EventHandler<OnLogArgs> OnLog;

		public event EventHandler<OnCommercialArgs> OnCommercial;

		public event EventHandler<OnPredictionArgs> OnPrediction;

		public event EventHandler<OnAutomodCaughtMessageArgs> OnAutomodCaughtMessage;

		public event EventHandler<OnAutomodCaughtUserMessage> OnAutomodCaughtUserMessage;

		public TwitchPubSub(ILogger<TwitchPubSub> logger = null)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			_logger = logger;
			ClientOptions val = new ClientOptions
			{
				ClientType = (ClientType)1
			};
			_socket = new WebSocketClient((IClientOptions)(object)val);
			_socket.OnConnected += Socket_OnConnected;
			_socket.OnError += OnError;
			_socket.OnMessage += OnMessage;
			_socket.OnDisconnected += Socket_OnDisconnected;
			_pongTimer.Interval = 15000.0;
			_pongTimer.Elapsed += PongTimerTick;
		}

		private void OnError(object sender, OnErrorEventArgs e)
		{
			_logger?.LogError($"OnError in PubSub Websocket connection occured! Exception: {e.Exception}");
			this.OnPubSubServiceError?.Invoke(this, new OnPubSubServiceErrorArgs
			{
				Exception = e.Exception
			});
		}

		private void OnMessage(object sender, OnMessageEventArgs e)
		{
			_logger?.LogDebug("Received Websocket OnMessage: " + e.Message);
			this.OnLog?.Invoke(this, new OnLogArgs
			{
				Data = e.Message
			});
			ParseMessage(e.Message);
		}

		private void Socket_OnDisconnected(object sender, EventArgs e)
		{
			_logger?.LogWarning("PubSub Websocket connection closed");
			_pingTimer.Stop();
			_pongTimer.Stop();
			this.OnPubSubServiceClosed?.Invoke(this, null);
		}

		private void Socket_OnConnected(object sender, EventArgs e)
		{
			_logger?.LogInformation("PubSub Websocket connection established");
			_pingTimer.Interval = 180000.0;
			_pingTimer.Elapsed += PingTimerTick;
			_pingTimer.Start();
			this.OnPubSubServiceConnected?.Invoke(this, null);
		}

		private void PingTimerTick(object sender, ElapsedEventArgs e)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			_pongReceived = false;
			JObject val = new JObject((object)new JProperty("type", (object)"PING"));
			_socket.Send(((object)val).ToString());
			_pongTimer.Start();
		}

		private void PongTimerTick(object sender, ElapsedEventArgs e)
		{
			_pongTimer.Stop();
			if (_pongReceived)
			{
				_pongReceived = false;
			}
			else
			{
				_socket.Close(true);
			}
		}

		private void ParseMessage(string message)
		{
			switch ((((object)((JToken)JObject.Parse(message)).SelectToken("type"))?.ToString())?.ToLower())
			{
			case "response":
			{
				Response response = new Response(message);
				if (_previousRequests.Count == 0)
				{
					break;
				}
				bool flag = false;
				_previousRequestsSemaphore.WaitOne();
				try
				{
					int num = 0;
					while (num < _previousRequests.Count)
					{
						PreviousRequest previousRequest = _previousRequests[num];
						if (string.Equals(previousRequest.Nonce, response.Nonce, StringComparison.CurrentCulture))
						{
							_previousRequests.RemoveAt(num);
							_topicToChannelId.TryGetValue(previousRequest.Topic, out var value2);
							this.OnListenResponse?.Invoke(this, new OnListenResponseArgs
							{
								Response = response,
								Topic = previousRequest.Topic,
								Successful = response.Successful,
								ChannelId = value2
							});
							flag = true;
						}
						else
						{
							num++;
						}
					}
				}
				finally
				{
					_previousRequestsSemaphore.Release();
				}
				if (flag)
				{
					return;
				}
				break;
			}
			case "message":
			{
				TwitchLib.PubSub.Models.Responses.Message message2 = new TwitchLib.PubSub.Models.Responses.Message(message);
				_topicToChannelId.TryGetValue(message2.Topic, out var value);
				value = value ?? "";
				switch (message2.Topic.Split(new char[1] { '.' })[0])
				{
				case "user-moderation-notifications":
				{
					UserModerationNotifications userModerationNotifications = message2.MessageData as UserModerationNotifications;
					if (userModerationNotifications.Type != 0)
					{
						_ = 1;
						return;
					}
					TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotificationsTypes.AutomodCaughtMessage automodCaughtMessage = userModerationNotifications.Data as TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotificationsTypes.AutomodCaughtMessage;
					this.OnAutomodCaughtUserMessage?.Invoke(this, new OnAutomodCaughtUserMessage
					{
						ChannelId = value,
						UserId = message2.Topic.Split(new char[1] { '.' })[2],
						AutomodCaughtMessage = automodCaughtMessage
					});
					return;
				}
				case "automod-queue":
				{
					AutomodQueue automodQueue = message2.MessageData as AutomodQueue;
					switch (automodQueue.Type)
					{
					case AutomodQueueType.CaughtMessage:
					{
						TwitchLib.PubSub.Models.Responses.Messages.AutomodCaughtMessage.AutomodCaughtMessage automodCaughtMessage2 = automodQueue.Data as TwitchLib.PubSub.Models.Responses.Messages.AutomodCaughtMessage.AutomodCaughtMessage;
						this.OnAutomodCaughtMessage?.Invoke(this, new OnAutomodCaughtMessageArgs
						{
							ChannelId = value,
							AutomodCaughtMessage = automodCaughtMessage2
						});
						break;
					}
					case AutomodQueueType.Unknown:
						UnaccountedFor("Unknown automod queue type. Msg: " + automodQueue.RawData);
						break;
					}
					return;
				}
				case "channel-subscribe-events-v1":
				{
					ChannelSubscription subscription = message2.MessageData as ChannelSubscription;
					this.OnChannelSubscription?.Invoke(this, new OnChannelSubscriptionArgs
					{
						Subscription = subscription,
						ChannelId = value
					});
					return;
				}
				case "whispers":
				{
					Whisper whisper = (Whisper)message2.MessageData;
					this.OnWhisper?.Invoke(this, new OnWhisperArgs
					{
						Whisper = whisper,
						ChannelId = value
					});
					return;
				}
				case "chat_moderator_actions":
				{
					ChatModeratorActions chatModeratorActions = message2.MessageData as ChatModeratorActions;
					string text = "";
					switch (chatModeratorActions?.ModerationAction.ToLower())
					{
					case "timeout":
						if (chatModeratorActions.Args.Count > 2)
						{
							text = chatModeratorActions.Args[2];
						}
						this.OnTimeout?.Invoke(this, new OnTimeoutArgs
						{
							TimedoutBy = chatModeratorActions.CreatedBy,
							TimedoutById = chatModeratorActions.CreatedByUserId,
							TimedoutUserId = chatModeratorActions.TargetUserId,
							TimeoutDuration = TimeSpan.FromSeconds(int.Parse(chatModeratorActions.Args[1])),
							TimeoutReason = text,
							TimedoutUser = chatModeratorActions.Args[0],
							ChannelId = value
						});
						return;
					case "ban":
						if (chatModeratorActions.Args.Count > 1)
						{
							text = chatModeratorActions.Args[1];
						}
						this.OnBan?.Invoke(this, new OnBanArgs
						{
							BannedBy = chatModeratorActions.CreatedBy,
							BannedByUserId = chatModeratorActions.CreatedByUserId,
							BannedUserId = chatModeratorActions.TargetUserId,
							BanReason = text,
							BannedUser = chatModeratorActions.Args[0],
							ChannelId = value
						});
						return;
					case "delete":
						this.OnMessageDeleted?.Invoke(this, new OnMessageDeletedArgs
						{
							DeletedBy = chatModeratorActions.CreatedBy,
							DeletedByUserId = chatModeratorActions.CreatedByUserId,
							TargetUserId = chatModeratorActions.TargetUserId,
							TargetUser = chatModeratorActions.Args[0],
							Message = chatModeratorActions.Args[1],
							MessageId = chatModeratorActions.Args[2],
							ChannelId = value
						});
						return;
					case "unban":
						this.OnUnban?.Invoke(this, new OnUnbanArgs
						{
							UnbannedBy = chatModeratorActions.CreatedBy,
							UnbannedByUserId = chatModeratorActions.CreatedByUserId,
							UnbannedUserId = chatModeratorActions.TargetUserId,
							UnbannedUser = chatModeratorActions.Args[0],
							ChannelId = value
						});
						return;
					case "untimeout":
						this.OnUntimeout?.Invoke(this, new OnUntimeoutArgs
						{
							UntimeoutedBy = chatModeratorActions.CreatedBy,
							UntimeoutedByUserId = chatModeratorActions.CreatedByUserId,
							UntimeoutedUserId = chatModeratorActions.TargetUserId,
							UntimeoutedUser = chatModeratorActions.Args[0],
							ChannelId = value
						});
						return;
					case "host":
						this.OnHost?.Invoke(this, new OnHostArgs
						{
							HostedChannel = chatModeratorActions.Args[0],
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "subscribers":
						this.OnSubscribersOnly?.Invoke(this, new OnSubscribersOnlyArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "subscribersoff":
						this.OnSubscribersOnlyOff?.Invoke(this, new OnSubscribersOnlyOffArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "clear":
						this.OnClear?.Invoke(this, new OnClearArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "emoteonly":
						this.OnEmoteOnly?.Invoke(this, new OnEmoteOnlyArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "emoteonlyoff":
						this.OnEmoteOnlyOff?.Invoke(this, new OnEmoteOnlyOffArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "r9kbeta":
						this.OnR9kBeta?.Invoke(this, new OnR9kBetaArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					case "r9kbetaoff":
						this.OnR9kBetaOff?.Invoke(this, new OnR9kBetaOffArgs
						{
							Moderator = chatModeratorActions.CreatedBy,
							ChannelId = value
						});
						return;
					}
					break;
				}
				case "channel-bits-events-v1":
					if (message2.MessageData is ChannelBitsEvents channelBitsEvents)
					{
						this.OnBitsReceived?.Invoke(this, new OnBitsReceivedArgs
						{
							BitsUsed = channelBitsEvents.BitsUsed,
							ChannelId = channelBitsEvents.ChannelId,
							ChannelName = channelBitsEvents.ChannelName,
							ChatMessage = channelBitsEvents.ChatMessage,
							Context = channelBitsEvents.Context,
							Time = channelBitsEvents.Time,
							TotalBitsUsed = channelBitsEvents.TotalBitsUsed,
							UserId = channelBitsEvents.UserId,
							Username = channelBitsEvents.Username
						});
						return;
					}
					break;
				case "channel-bits-events-v2":
					if (message2.MessageData is ChannelBitsEventsV2 channelBitsEventsV)
					{
						this.OnBitsReceivedV2?.Invoke(this, new OnBitsReceivedV2Args
						{
							IsAnonymous = channelBitsEventsV.IsAnonymous,
							BitsUsed = channelBitsEventsV.BitsUsed,
							ChannelId = channelBitsEventsV.ChannelId,
							ChannelName = channelBitsEventsV.ChannelName,
							ChatMessage = channelBitsEventsV.ChatMessage,
							Context = channelBitsEventsV.Context,
							Time = channelBitsEventsV.Time,
							TotalBitsUsed = channelBitsEventsV.TotalBitsUsed,
							UserId = channelBitsEventsV.UserId,
							UserName = channelBitsEventsV.UserName
						});
						return;
					}
					break;
				case "channel-ext-v1":
				{
					ChannelExtensionBroadcast channelExtensionBroadcast = message2.MessageData as ChannelExtensionBroadcast;
					this.OnChannelExtensionBroadcast?.Invoke(this, new OnChannelExtensionBroadcastArgs
					{
						Messages = channelExtensionBroadcast.Messages,
						ChannelId = value
					});
					return;
				}
				case "video-playback-by-id":
				{
					VideoPlayback videoPlayback = message2.MessageData as VideoPlayback;
					switch (videoPlayback?.Type)
					{
					case VideoPlaybackType.StreamDown:
						this.OnStreamDown?.Invoke(this, new OnStreamDownArgs
						{
							ServerTime = videoPlayback.ServerTime,
							ChannelId = value
						});
						return;
					case VideoPlaybackType.StreamUp:
						this.OnStreamUp?.Invoke(this, new OnStreamUpArgs
						{
							PlayDelay = videoPlayback.PlayDelay,
							ServerTime = videoPlayback.ServerTime,
							ChannelId = value
						});
						return;
					case VideoPlaybackType.ViewCount:
						this.OnViewCount?.Invoke(this, new OnViewCountArgs
						{
							ServerTime = videoPlayback.ServerTime,
							Viewers = videoPlayback.Viewers,
							ChannelId = value
						});
						return;
					case VideoPlaybackType.Commercial:
						this.OnCommercial?.Invoke(this, new OnCommercialArgs
						{
							ServerTime = videoPlayback.ServerTime,
							Length = videoPlayback.Length,
							ChannelId = value
						});
						return;
					}
					break;
				}
				case "following":
				{
					Following following = (Following)message2.MessageData;
					following.FollowedChannelId = message2.Topic.Split(new char[1] { '.' })[1];
					this.OnFollow?.Invoke(this, new OnFollowArgs
					{
						FollowedChannelId = following.FollowedChannelId,
						DisplayName = following.DisplayName,
						UserId = following.UserId,
						Username = following.Username
					});
					return;
				}
				case "community-points-channel-v1":
				{
					CommunityPointsChannel communityPointsChannel = message2.MessageData as CommunityPointsChannel;
					CommunityPointsChannelType? communityPointsChannelType = communityPointsChannel?.Type;
					if (communityPointsChannelType.HasValue)
					{
						switch (communityPointsChannelType.GetValueOrDefault())
						{
						case CommunityPointsChannelType.RewardRedeemed:
							this.OnRewardRedeemed?.Invoke(this, new OnRewardRedeemedArgs
							{
								TimeStamp = communityPointsChannel.TimeStamp,
								ChannelId = communityPointsChannel.ChannelId,
								Login = communityPointsChannel.Login,
								DisplayName = communityPointsChannel.DisplayName,
								Message = communityPointsChannel.Message,
								RewardId = communityPointsChannel.RewardId,
								RewardTitle = communityPointsChannel.RewardTitle,
								RewardPrompt = communityPointsChannel.RewardPrompt,
								RewardCost = communityPointsChannel.RewardCost,
								Status = communityPointsChannel.Status,
								RedemptionId = communityPointsChannel.RedemptionId
							});
							break;
						case CommunityPointsChannelType.CustomRewardUpdated:
							this.OnCustomRewardUpdated?.Invoke(this, new OnCustomRewardUpdatedArgs
							{
								TimeStamp = communityPointsChannel.TimeStamp,
								ChannelId = communityPointsChannel.ChannelId,
								RewardId = communityPointsChannel.RewardId,
								RewardTitle = communityPointsChannel.RewardTitle,
								RewardPrompt = communityPointsChannel.RewardPrompt,
								RewardCost = communityPointsChannel.RewardCost
							});
							break;
						case CommunityPointsChannelType.CustomRewardCreated:
							this.OnCustomRewardCreated?.Invoke(this, new OnCustomRewardCreatedArgs
							{
								TimeStamp = communityPointsChannel.TimeStamp,
								ChannelId = communityPointsChannel.ChannelId,
								RewardId = communityPointsChannel.RewardId,
								RewardTitle = communityPointsChannel.RewardTitle,
								RewardPrompt = communityPointsChannel.RewardPrompt,
								RewardCost = communityPointsChannel.RewardCost
							});
							break;
						case CommunityPointsChannelType.CustomRewardDeleted:
							this.OnCustomRewardDeleted?.Invoke(this, new OnCustomRewardDeletedArgs
							{
								TimeStamp = communityPointsChannel.TimeStamp,
								ChannelId = communityPointsChannel.ChannelId,
								RewardId = communityPointsChannel.RewardId,
								RewardTitle = communityPointsChannel.RewardTitle,
								RewardPrompt = communityPointsChannel.RewardPrompt
							});
							break;
						}
					}
					return;
				}
				case "channel-points-channel-v1":
				{
					ChannelPointsChannel channelPointsChannel = message2.MessageData as ChannelPointsChannel;
					switch (channelPointsChannel.Type)
					{
					case ChannelPointsChannelType.RewardRedeemed:
					{
						RewardRedeemed rewardRedeemed = channelPointsChannel.Data as RewardRedeemed;
						this.OnChannelPointsRewardRedeemed?.Invoke(this, new OnChannelPointsRewardRedeemedArgs
						{
							ChannelId = rewardRedeemed.Redemption.ChannelId,
							RewardRedeemed = rewardRedeemed
						});
						break;
					}
					case ChannelPointsChannelType.Unknown:
						UnaccountedFor("Unknown channel points type. Msg: " + channelPointsChannel.RawData);
						break;
					}
					return;
				}
				case "leaderboard-events-v1":
				{
					LeaderboardEvents leaderboardEvents = message2.MessageData as LeaderboardEvents;
					LeaderBoardType? leaderBoardType = leaderboardEvents?.Type;
					if (leaderBoardType.HasValue)
					{
						switch (leaderBoardType.GetValueOrDefault())
						{
						case LeaderBoardType.BitsUsageByChannel:
							this.OnLeaderboardBits?.Invoke(this, new OnLeaderboardEventArgs
							{
								ChannelId = leaderboardEvents.ChannelId,
								TopList = leaderboardEvents.Top
							});
							break;
						case LeaderBoardType.SubGiftSent:
							this.OnLeaderboardSubs?.Invoke(this, new OnLeaderboardEventArgs
							{
								ChannelId = leaderboardEvents.ChannelId,
								TopList = leaderboardEvents.Top
							});
							break;
						}
					}
					return;
				}
				case "raid":
				{
					RaidEvents raidEvents = message2.MessageData as RaidEvents;
					RaidType? raidType = raidEvents?.Type;
					if (raidType.HasValue)
					{
						switch (raidType.GetValueOrDefault())
						{
						case RaidType.RaidUpdate:
							this.OnRaidUpdate?.Invoke(this, new OnRaidUpdateArgs
							{
								Id = raidEvents.Id,
								ChannelId = raidEvents.ChannelId,
								TargetChannelId = raidEvents.TargetChannelId,
								AnnounceTime = raidEvents.AnnounceTime,
								RaidTime = raidEvents.RaidTime,
								RemainingDurationSeconds = raidEvents.RemainigDurationSeconds,
								ViewerCount = raidEvents.ViewerCount
							});
							break;
						case RaidType.RaidUpdateV2:
							this.OnRaidUpdateV2?.Invoke(this, new OnRaidUpdateV2Args
							{
								Id = raidEvents.Id,
								ChannelId = raidEvents.ChannelId,
								TargetChannelId = raidEvents.TargetChannelId,
								TargetLogin = raidEvents.TargetLogin,
								TargetDisplayName = raidEvents.TargetDisplayName,
								TargetProfileImage = raidEvents.TargetProfileImage,
								ViewerCount = raidEvents.ViewerCount
							});
							break;
						case RaidType.RaidGo:
							this.OnRaidGo?.Invoke(this, new OnRaidGoArgs
							{
								Id = raidEvents.Id,
								ChannelId = raidEvents.ChannelId,
								TargetChannelId = raidEvents.TargetChannelId,
								TargetLogin = raidEvents.TargetLogin,
								TargetDisplayName = raidEvents.TargetDisplayName,
								TargetProfileImage = raidEvents.TargetProfileImage,
								ViewerCount = raidEvents.ViewerCount
							});
							break;
						}
					}
					return;
				}
				case "predictions-channel-v1":
				{
					PredictionEvents predictionEvents = message2.MessageData as PredictionEvents;
					switch (predictionEvents?.Type)
					{
					case PredictionType.EventCreated:
						this.OnPrediction?.Invoke(this, new OnPredictionArgs
						{
							CreatedAt = predictionEvents.CreatedAt,
							Title = predictionEvents.Title,
							ChannelId = predictionEvents.ChannelId,
							EndedAt = predictionEvents.EndedAt,
							Id = predictionEvents.Id,
							Outcomes = predictionEvents.Outcomes,
							LockedAt = predictionEvents.LockedAt,
							PredictionTime = predictionEvents.PredictionTime,
							Status = predictionEvents.Status,
							WinningOutcomeId = predictionEvents.WinningOutcomeId,
							Type = predictionEvents.Type
						});
						break;
					case PredictionType.EventUpdated:
						this.OnPrediction?.Invoke(this, new OnPredictionArgs
						{
							CreatedAt = predictionEvents.CreatedAt,
							Title = predictionEvents.Title,
							ChannelId = predictionEvents.ChannelId,
							EndedAt = predictionEvents.EndedAt,
							Id = predictionEvents.Id,
							Outcomes = predictionEvents.Outcomes,
							LockedAt = predictionEvents.LockedAt,
							PredictionTime = predictionEvents.PredictionTime,
							Status = predictionEvents.Status,
							WinningOutcomeId = predictionEvents.WinningOutcomeId,
							Type = predictionEvents.Type
						});
						break;
					case null:
						UnaccountedFor("Prediction Type: null");
						break;
					default:
						UnaccountedFor($"Prediction Type: {predictionEvents.Type}");
						break;
					}
					return;
				}
				}
				break;
			}
			case "pong":
				_pongReceived = true;
				return;
			case "reconnect":
				_socket.Close(true);
				break;
			}
			UnaccountedFor(message);
		}

		private static string GenerateNonce()
		{
			return new string((from s in Enumerable.Repeat("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 8)
				select s[Random.Next(s.Length)]).ToArray());
		}

		private void ListenToTopic(string topic)
		{
			_topicList.Add(topic);
		}

		private void ListenToTopics(params string[] topics)
		{
			foreach (string item in topics)
			{
				_topicList.Add(item);
			}
		}

		public void SendTopics(string oauth = null, bool unlisten = false)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			if (oauth != null && oauth.Contains("oauth:"))
			{
				oauth = oauth.Replace("oauth:", "");
			}
			string text = GenerateNonce();
			JArray val = new JArray();
			_previousRequestsSemaphore.WaitOne();
			try
			{
				foreach (string topic in _topicList)
				{
					_previousRequests.Add(new PreviousRequest(text, PubSubRequestType.ListenToTopic, topic));
					val.Add((JToken)new JValue(topic));
				}
			}
			finally
			{
				_previousRequestsSemaphore.Release();
			}
			JObject val2 = new JObject(new object[3]
			{
				(object)new JProperty("type", (object)((!unlisten) ? "LISTEN" : "UNLISTEN")),
				(object)new JProperty("nonce", (object)text),
				(object)new JProperty("data", (object)new JObject((object)new JProperty("topics", (object)val)))
			});
			if (oauth != null)
			{
				JObject val3 = (JObject)((JToken)val2).SelectToken("data");
				if ((int)val3 != 0)
				{
					((JContainer)val3).Add((object)new JProperty("auth_token", (object)oauth));
				}
			}
			_socket.Send(((object)val2).ToString());
			_topicList.Clear();
		}

		private void UnaccountedFor(string message)
		{
			_logger?.LogInformation("[TwitchPubSub] " + message);
		}

		public void ListenToFollows(string channelId)
		{
			string text = "following." + channelId;
			_topicToChannelId[text] = channelId;
			ListenToTopic(text);
		}

		public void ListenToChatModeratorActions(string userId, string channelId)
		{
			string text = "chat_moderator_actions." + userId + "." + channelId;
			_topicToChannelId[text] = channelId;
			ListenToTopic(text);
		}

		public void ListenToUserModerationNotifications(string myTwitchId, string channelTwitchId)
		{
			string text = "user-moderation-notifications." + myTwitchId + "." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToAutomodQueue(string userTwitchId, string channelTwitchId)
		{
			string text = "automod-queue." + userTwitchId + "." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToChannelExtensionBroadcast(string channelId, string extensionId)
		{
			string text = "channel-ext-v1." + channelId + "-" + extensionId + "-broadcast";
			_topicToChannelId[text] = channelId;
			ListenToTopic(text);
		}

		[Obsolete("This topic is deprecated by Twitch. Please use ListenToBitsEventsV2()", false)]
		public void ListenToBitsEvents(string channelTwitchId)
		{
			string text = "channel-bits-events-v1." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToBitsEventsV2(string channelTwitchId)
		{
			string text = "channel-bits-events-v2." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToVideoPlayback(string channelTwitchId)
		{
			string text = "video-playback-by-id." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToWhispers(string channelTwitchId)
		{
			string text = "whispers." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		[Obsolete("This method listens to an undocumented/retired/obsolete topic. Consider using ListenToChannelPoints()", false)]
		public void ListenToRewards(string channelTwitchId)
		{
			string text = "community-points-channel-v1." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToChannelPoints(string channelTwitchId)
		{
			string text = "channel-points-channel-v1." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToLeaderboards(string channelTwitchId)
		{
			string text = "leaderboard-events-v1.bits-usage-by-channel-v1-" + channelTwitchId + "-WEEK";
			string text2 = "leaderboard-events-v1.sub-gift-sent-" + channelTwitchId + "-WEEK";
			_topicToChannelId[text] = channelTwitchId;
			_topicToChannelId[text2] = channelTwitchId;
			ListenToTopics(text, text2);
		}

		public void ListenToRaid(string channelTwitchId)
		{
			string text = "raid." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void ListenToSubscriptions(string channelId)
		{
			string text = "channel-subscribe-events-v1." + channelId;
			_topicToChannelId[text] = channelId;
			ListenToTopic(text);
		}

		public void ListenToPredictions(string channelTwitchId)
		{
			string text = "predictions-channel-v1." + channelTwitchId;
			_topicToChannelId[text] = channelTwitchId;
			ListenToTopic(text);
		}

		public void Connect()
		{
			_socket.Open();
		}

		public void Disconnect()
		{
			_socket.Close(true);
		}

		public void TestMessageParser(string testJsonString)
		{
			ParseMessage(testJsonString);
		}
	}
}
namespace TwitchLib.PubSub.Models
{
	public class LeaderBoard
	{
		public int Place { get; set; }

		public int Score { get; set; }

		public string UserId { get; set; }
	}
	public class Outcome
	{
		public class Predictor
		{
			public long Points { get; set; }

			public string UserId { get; set; }

			public string DisplayName { get; set; }
		}

		public Guid Id { get; set; }

		public string Color { get; set; }

		public string Title { get; set; }

		public long TotalPoints { get; set; }

		public long TotalUsers { get; set; }

		public ICollection<Predictor> TopPredictors { get; set; } = new List<Predictor>();

	}
	public class PreviousRequest
	{
		public string Nonce { get; }

		public PubSubRequestType RequestType { get; }

		public string Topic { get; }

		public PreviousRequest(string nonce, PubSubRequestType requestType, string topic = "none set")
		{
			Nonce = nonce;
			RequestType = requestType;
			Topic = topic;
		}
	}
}
namespace TwitchLib.PubSub.Models.Responses
{
	public class Message
	{
		public readonly MessageData MessageData;

		public string Topic { get; }

		public Message(string jsonStr)
		{
			JToken val = ((JToken)JObject.Parse(jsonStr)).SelectToken("data");
			Topic = ((object)val.SelectToken("topic"))?.ToString();
			string text = ((object)val.SelectToken("message")).ToString();
			string topic = Topic;
			switch ((topic != null) ? topic.Split(new char[1] { '.' })[0] : null)
			{
			case "user-moderation-notifications":
				MessageData = new UserModerationNotifications(text);
				break;
			case "automod-queue":
				MessageData = new AutomodQueue(text);
				break;
			case "chat_moderator_actions":
				MessageData = new ChatModeratorActions(text);
				break;
			case "channel-bits-events-v1":
				MessageData = new ChannelBitsEvents(text);
				break;
			case "channel-bits-events-v2":
			{
				text = text.Replace("\\", "");
				string text2 = ((object)JObject.Parse(text)["data"]).ToString();
				MessageData = JsonConvert.DeserializeObject<ChannelBitsEventsV2>(text2);
				break;
			}
			case "video-playback-by-id":
				MessageData = new VideoPlayback(text);
				break;
			case "whispers":
				MessageData = new Whisper(text);
				break;
			case "channel-subscribe-events-v1":
				MessageData = new ChannelSubscription(text);
				break;
			case "channel-ext-v1":
				MessageData = new ChannelExtensionBroadcast(text);
				break;
			case "following":
				MessageData = new Following(text);
				break;
			case "community-points-channel-v1":
				MessageData = new CommunityPointsChannel(text);
				break;
			case "channel-points-channel-v1":
				MessageData = new ChannelPointsChannel(text);
				break;
			case "leaderboard-events-v1":
				MessageData = new LeaderboardEvents(text);
				break;
			case "raid":
				MessageData = new RaidEvents(text);
				break;
			case "predictions-channel-v1":
				MessageData = new PredictionEvents(text);
				break;
			}
		}
	}
	public class Response
	{
		public string Error { get; }

		public string Nonce { get; }

		public bool Successful { get; }

		public Response(string json)
		{
			Error = ((object)((JToken)JObject.Parse(json)).SelectToken("error"))?.ToString();
			Nonce = ((object)((JToken)JObject.Parse(json)).SelectToken("nonce"))?.ToString();
			if (string.IsNullOrWhiteSpace(Error))
			{
				Successful = true;
			}
		}
	}
}
namespace TwitchLib.PubSub.Models.Responses.Messages
{
	public class AutomodQueue : MessageData
	{
		public AutomodQueueType Type { get; private set; }

		public AutomodQueueData Data { get; private set; }

		public string RawData { get; private set; }

		public AutomodQueue(string jsonStr)
		{
			RawData = jsonStr;
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			if (((object)val.SelectToken("type")).ToString() == "automod_caught_message")
			{
				Type = AutomodQueueType.CaughtMessage;
				Data = JsonConvert.DeserializeObject<TwitchLib.PubSub.Models.Responses.Messages.AutomodCaughtMessage.AutomodCaughtMessage>(((object)val.SelectToken("data")).ToString());
			}
			else
			{
				Type = AutomodQueueType.Unknown;
			}
		}
	}
	public abstract class AutomodQueueData
	{
	}
	public class ChannelBitsEvents : MessageData
	{
		public string Username { get; }

		public string ChannelName { get; }

		public string UserId { get; }

		public string ChannelId { get; }

		public string Time { get; }

		public string ChatMessage { get; }

		public int BitsUsed { get; }

		public int TotalBitsUsed { get; }

		public string Context { get; }

		public ChannelBitsEvents(string jsonStr)
		{
			JObject val = JObject.Parse(jsonStr);
			Username = ((object)((JToken)val).SelectToken("data").SelectToken("user_name"))?.ToString();
			ChannelName = ((object)((JToken)val).SelectToken("data").SelectToken("channel_name"))?.ToString();
			UserId = ((object)((JToken)val).SelectToken("data").SelectToken("user_id"))?.ToString();
			ChannelId = ((object)((JToken)val).SelectToken("data").SelectToken("channel_id"))?.ToString();
			Time = ((object)((JToken)val).SelectToken("data").SelectToken("time"))?.ToString();
			ChatMessage = ((object)((JToken)val).SelectToken("data").SelectToken("chat_message"))?.ToString();
			BitsUsed = int.Parse(((object)((JToken)val).SelectToken("data").SelectToken("bits_used")).ToString());
			TotalBitsUsed = int.Parse(((object)((JToken)val).SelectToken("data").SelectToken("total_bits_used")).ToString());
			Context = ((object)((JToken)val).SelectToken("data").SelectToken("context"))?.ToString();
		}
	}
	public class ChannelBitsEventsV2 : MessageData
	{
		[JsonProperty(PropertyName = "user_name")]
		public string UserName { get; protected set; }

		[JsonProperty(PropertyName = "channel_name")]
		public string ChannelName { get; protected set; }

		[JsonProperty(PropertyName = "user_id")]
		public string UserId { get; protected set; }

		[JsonProperty(PropertyName = "channel_id")]
		public string ChannelId { get; protected set; }

		[JsonProperty(PropertyName = "time")]
		public DateTime Time { get; protected set; }

		[JsonProperty(PropertyName = "chat_message")]
		public string ChatMessage { get; protected set; }

		[JsonProperty(PropertyName = "bits_used")]
		public int BitsUsed { get; protected set; }

		[JsonProperty(PropertyName = "total_bits_used")]
		public int TotalBitsUsed { get; protected set; }

		[JsonProperty(PropertyName = "is_anonymous")]
		public bool IsAnonymous { get; protected set; }

		[JsonProperty(PropertyName = "context")]
		public string Context { get; protected set; }
	}
	public class ChannelExtensionBroadcast : MessageData
	{
		public List<string> Messages { get; } = new List<string>();


		public ChannelExtensionBroadcast(string jsonStr)
		{
			foreach (JToken item in (IEnumerable<JToken>)JObject.Parse(jsonStr)["content"])
			{
				Messages.Add(((object)item).ToString());
			}
		}
	}
	public class ChannelPointsChannel : MessageData
	{
		public ChannelPointsChannelType Type { get; private set; }

		public ChannelPointsData Data { get; private set; }

		public string RawData { get; private set; }

		public ChannelPointsChannel(string jsonStr)
		{
			RawData = jsonStr;
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			if (((object)val.SelectToken("type")).ToString() == "reward-redeemed")
			{
				Type = ChannelPointsChannelType.RewardRedeemed;
				Data = JsonConvert.DeserializeObject<RewardRedeemed>(((object)val.SelectToken("data")).ToString());
			}
			else
			{
				Type = ChannelPointsChannelType.Unknown;
			}
		}
	}
	public abstract class ChannelPointsData
	{
	}
	public class ChannelSubscription : MessageData
	{
		public string Username { get; }

		public string DisplayName { get; }

		public string RecipientName { get; }

		public string RecipientDisplayName { get; }

		public string ChannelName { get; }

		public string UserId { get; }

		public string ChannelId { get; }

		public string RecipientId { get; }

		public DateTime Time { get; }

		public SubscriptionPlan SubscriptionPlan { get; }

		public string SubscriptionPlanName { get; }

		public int? Months { get; }

		public int? CumulativeMonths { get; }

		public int? StreakMonths { get; }

		public string Context { get; }

		public SubMessage SubMessage { get; }

		public bool? IsGift { get; }

		public int? MultiMonthDuration { get; }

		public ChannelSubscription(string jsonStr)
		{
			JObject val = JObject.Parse(jsonStr);
			Username = ((object)((JToken)val).SelectToken("user_name"))?.ToString();
			DisplayName = ((object)((JToken)val).SelectToken("display_name"))?.ToString();
			RecipientName = ((object)((JToken)val).SelectToken("recipient_user_name"))?.ToString();
			RecipientDisplayName = ((object)((JToken)val).SelectToken("recipient_display_name"))?.ToString();
			ChannelName = ((object)((JToken)val).SelectToken("channel_name"))?.ToString();
			UserId = ((object)((JToken)val).SelectToken("user_id"))?.ToString();
			RecipientId = ((object)((JToken)val).SelectToken("recipient_id"))?.ToString();
			ChannelId = ((object)((JToken)val).SelectToken("channel_id"))?.ToString();
			Time = Helpers.DateTimeStringToObject(((object)((JToken)val).SelectToken("time"))?.ToString());
			switch (((object)((JToken)val).SelectToken("sub_plan")).ToString().ToLower())
			{
			case "prime":
				SubscriptionPlan = SubscriptionPlan.Prime;
				break;
			case "1000":
				SubscriptionPlan = SubscriptionPlan.Tier1;
				break;
			case "2000":
				SubscriptionPlan = SubscriptionPlan.Tier2;
				break;
			case "3000":
				SubscriptionPlan = SubscriptionPlan.Tier3;
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
			SubscriptionPlanName = ((object)((JToken)val).SelectToken("sub_plan_name"))?.ToString();
			SubMessage = new SubMessage(((JToken)val).SelectToken("sub_message"));
			string text = ((object)((JToken)val).SelectToken("is_gift"))?.ToString();
			if (text != null)
			{
				IsGift = Convert.ToBoolean(text.ToString());
			}
			string text2 = ((object)((JToken)val).SelectToken("multi_month_duration"))?.ToString();
			if (text2 != null)
			{
				MultiMonthDuration = int.Parse(text2.ToString());
			}
			Context = ((object)((JToken)val).SelectToken("context"))?.ToString();
			JToken val2 = ((JToken)val).SelectToken("months");
			if (val2 != null)
			{
				Months = int.Parse(((object)val2).ToString());
			}
			JToken val3 = ((JToken)val).SelectToken("cumulative_months");
			if (val3 != null)
			{
				CumulativeMonths = int.Parse(((object)val3).ToString());
			}
			JToken val4 = ((JToken)val).SelectToken("streak_months");
			if (val4 != null)
			{
				StreakMonths = int.Parse(((object)val4).ToString());
			}
		}
	}
	public class ChatModeratorActions : MessageData
	{
		public string Type { get; }

		public string ModerationAction { get; }

		public List<string> Args { get; } = new List<string>();


		public string CreatedBy { get; }

		public string CreatedByUserId { get; }

		public string TargetUserId { get; }

		public ChatModeratorActions(string jsonStr)
		{
			JToken val = ((JToken)JObject.Parse(jsonStr)).SelectToken("data");
			Type = ((object)val.SelectToken("type"))?.ToString();
			ModerationAction = ((object)val.SelectToken("moderation_action"))?.ToString();
			if (val.SelectToken("args") != null)
			{
				foreach (JToken item in (IEnumerable<JToken>)val.SelectToken("args"))
				{
					Args.Add(((object)item).ToString());
				}
			}
			CreatedBy = ((object)val.SelectToken("created_by")).ToString();
			CreatedByUserId = ((object)val.SelectToken("created_by_user_id")).ToString();
			TargetUserId = ((object)val.SelectToken("target_user_id")).ToString();
		}
	}
	public class CommunityPointsChannel : MessageData
	{
		public CommunityPointsChannelType Type { get; protected set; }

		public DateTime TimeStamp { get; protected set; }

		public string ChannelId { get; protected set; }

		public string Login { get; protected set; }

		public string DisplayName { get; protected set; }

		public string Message { get; protected set; }

		public Guid RewardId { get; protected set; }

		public string RewardTitle { get; protected set; }

		public string RewardPrompt { get; protected set; }

		public int RewardCost { get; protected set; }

		public string Status { get; protected set; }

		public Guid RedemptionId { get; protected set; }

		public CommunityPointsChannel(string jsonStr)
		{
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			switch (((object)val.SelectToken("type")).ToString())
			{
			case "reward-redeemed":
			case "redemption-status-update":
				Type = CommunityPointsChannelType.RewardRedeemed;
				break;
			case "custom-reward-created":
				Type = CommunityPointsChannelType.CustomRewardCreated;
				break;
			case "custom-reward-updated":
				Type = CommunityPointsChannelType.CustomRewardUpdated;
				break;
			case "custom-reward-deleted":
				Type = CommunityPointsChannelType.CustomRewardDeleted;
				break;
			default:
				Type = (CommunityPointsChannelType)(-1);
				break;
			}
			TimeStamp = DateTime.Parse(((object)val.SelectToken("data.timestamp")).ToString());
			switch (Type)
			{
			case CommunityPointsChannelType.RewardRedeemed:
				ChannelId = ((object)val.SelectToken("data.redemption.channel_id")).ToString();
				Login = ((object)val.SelectToken("data.redemption.user.login")).ToString();
				DisplayName = ((object)val.SelectToken("data.redemption.user.display_name")).ToString();
				RewardId = Guid.Parse(((object)val.SelectToken("data.redemption.reward.id")).ToString());
				RewardTitle = ((object)val.SelectToken("data.redemption.reward.title")).ToString();
				RewardPrompt = ((object)val.SelectToken("data.redemption.reward.prompt")).ToString();
				RewardCost = int.Parse(((object)val.SelectToken("data.redemption.reward.cost")).ToString());
				Message = ((object)val.SelectToken("data.redemption.user_input"))?.ToString();
				Status = ((object)val.SelectToken("data.redemption.status")).ToString();
				RedemptionId = Guid.Parse(((object)val.SelectToken("data.redemption.id")).ToString());
				break;
			case CommunityPointsChannelType.CustomRewardUpdated:
				ChannelId = ((object)val.SelectToken("data.updated_reward.channel_id")).ToString();
				RewardId = Guid.Parse(((object)val.SelectToken("data.updated_reward.id")).ToString());
				RewardTitle = ((object)val.SelectToken("data.updated_reward.title")).ToString();
				RewardPrompt = ((object)val.SelectToken("data.updated_reward.prompt")).ToString();
				RewardCost = int.Parse(((object)val.SelectToken("data.updated_reward.cost")).ToString());
				break;
			case CommunityPointsChannelType.CustomRewardCreated:
				ChannelId = ((object)val.SelectToken("data.new_reward.channel_id")).ToString();
				RewardId = Guid.Parse(((object)val.SelectToken("data.new_reward.id")).ToString());
				RewardTitle = ((object)val.SelectToken("data.new_reward.title")).ToString();
				RewardPrompt = ((object)val.SelectToken("data.new_reward.prompt")).ToString();
				RewardCost = int.Parse(((object)val.SelectToken("data.new_reward.cost")).ToString());
				break;
			case CommunityPointsChannelType.CustomRewardDeleted:
				ChannelId = ((object)val.SelectToken("data.deleted_reward.channel_id")).ToString();
				RewardId = Guid.Parse(((object)val.SelectToken("data.deleted_reward.id")).ToString());
				RewardTitle = ((object)val.SelectToken("data.deleted_reward.title")).ToString();
				RewardPrompt = ((object)val.SelectToken("data.deleted_reward.prompt")).ToString();
				break;
			}
		}
	}
	public class Following : MessageData
	{
		public string DisplayName { get; }

		public string Username { get; }

		public string UserId { get; }

		public string FollowedChannelId { get; internal set; }

		public Following(string jsonStr)
		{
			JObject val = JObject.Parse(jsonStr);
			DisplayName = ((object)val["display_name"]).ToString();
			Username = ((object)val["username"]).ToString();
			UserId = ((object)val["user_id"]).ToString();
		}
	}
	public class LeaderboardEvents : MessageData
	{
		public LeaderBoardType Type { get; private set; }

		public string ChannelId { get; private set; }

		public List<LeaderBoard> Top { get; private set; } = new List<LeaderBoard>();


		public LeaderboardEvents(string jsonStr)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			string text = ((object)val.SelectToken("identifier.domain")).ToString();
			if (!(text == "bits-usage-by-channel-v1"))
			{
				if (text == "sub-gift-sent")
				{
					Type = LeaderBoardType.SubGiftSent;
				}
			}
			else
			{
				Type = LeaderBoardType.BitsUsageByChannel;
			}
			switch (Type)
			{
			case LeaderBoardType.BitsUsageByChannel:
				ChannelId = ((object)val.SelectToken("identifier.grouping_key")).ToString();
				{
					foreach (JToken item in val[(object)"top"].Children())
					{
						Top.Add(new LeaderBoard
						{
							Place = int.Parse(((object)item.SelectToken("rank")).ToString()),
							Score = int.Parse(((object)item.SelectToken("score")).ToString()),
							UserId = ((object)item.SelectToken("entry_key")).ToString()
						});
					}
					break;
				}
			case LeaderBoardType.SubGiftSent:
				ChannelId = ((object)val.SelectToken("identifier.grouping_key")).ToString();
				{
					foreach (JToken item2 in val[(object)"top"].Children())
					{
						Top.Add(new LeaderBoard
						{
							Place = int.Parse(((object)item2.SelectToken("rank")).ToString()),
							Score = int.Parse(((object)item2.SelectToken("score")).ToString()),
							UserId = ((object)item2.SelectToken("entry_key")).ToString()
						});
					}
					break;
				}
			}
		}
	}
	public abstract class MessageData
	{
	}
	public class PredictionEvents : MessageData
	{
		public PredictionType Type { get; protected set; }

		public Guid Id { get; protected set; }

		public string ChannelId { get; protected set; }

		public DateTime? CreatedAt { get; protected set; }

		public DateTime? LockedAt { get; protected set; }

		public DateTime? EndedAt { get; protected set; }

		public ICollection<Outcome> Outcomes { get; protected set; } = new List<Outcome>();


		public PredictionStatus Status { get; protected set; }

		public string Title { get; protected set; }

		public Guid? WinningOutcomeId { get; protected set; }

		public int PredictionTime { get; protected set; }

		public PredictionEvents(string jsonStr)
		{
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			JObject val = JObject.Parse(jsonStr);
			Type = (PredictionType)Enum.Parse(typeof(PredictionType), ((object)((JToken)val).SelectToken("type")).ToString().Replace("-", ""), ignoreCase: true);
			JToken val2 = ((JToken)val).SelectToken("data.event");
			Id = Guid.Parse(((object)val2.SelectToken("id")).ToString());
			ChannelId = ((object)val2.SelectToken("channel_id")).ToString();
			CreatedAt = (val2.SelectToken("created_at").IsEmpty() ? null : new DateTime?(DateTime.Parse(((object)val2.SelectToken("created_at")).ToString())));
			EndedAt = (val2.SelectToken("ended_at").IsEmpty() ? null : new DateTime?(DateTime.Parse(((object)val2.SelectToken("ended_at")).ToString())));
			LockedAt = (val2.SelectToken("locked_at").IsEmpty() ? null : new DateTime?(DateTime.Parse(((object)val2.SelectToken("locked_at")).ToString())));
			Status = (PredictionStatus)Enum.Parse(typeof(PredictionStatus), ((object)val2.SelectToken("status")).ToString().Replace("_", ""), ignoreCase: true);
			Title = ((object)val2.SelectToken("title")).ToString();
			WinningOutcomeId = (val2.SelectToken("winning_outcome_id").IsEmpty() ? null : new Guid?(Guid.Parse(((object)val2.SelectToken("winning_outcome_id")).ToString())));
			PredictionTime = int.Parse(((object)val2.SelectToken("prediction_window_seconds")).ToString());
			foreach (JToken item in val2.SelectToken("outcomes").Children())
			{
				Outcome outcome = new Outcome
				{
					Id = Guid.Parse(((object)item.SelectToken("id")).ToString()),
					Color = ((object)item.SelectToken("color")).ToString(),
					Title = ((object)item.SelectToken("title")).ToString(),
					TotalPoints = long.Parse(((object)item.SelectToken("total_points")).ToString()),
					TotalUsers = long.Parse(((object)item.SelectToken("total_users")).ToString())
				};
				foreach (JToken item2 in item.SelectToken("top_predictors").Children())
				{
					outcome.TopPredictors.Add(new Outcome.Predictor
					{
						DisplayName = ((object)item2.SelectToken("user_display_name")).ToString(),
						Points = int.Parse(((object)item2.SelectToken("points")).ToString()),
						UserId = ((object)item2.SelectToken("user_id")).ToString()
					});
				}
				Outcomes.Add(outcome);
			}
		}
	}
	public class RaidEvents : MessageData
	{
		public RaidType Type { get; protected set; }

		public Guid Id { get; protected set; }

		public string ChannelId { get; protected set; }

		public string TargetChannelId { get; protected set; }

		public string TargetLogin { get; protected set; }

		public string TargetDisplayName { get; protected set; }

		public string TargetProfileImage { get; protected set; }

		public DateTime AnnounceTime { get; protected set; }

		public DateTime RaidTime { get; protected set; }

		public int RemainigDurationSeconds { get; protected set; }

		public int ViewerCount { get; protected set; }

		public RaidEvents(string jsonStr)
		{
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			switch (((object)val.SelectToken("type")).ToString())
			{
			case "raid_update":
				Type = RaidType.RaidUpdate;
				break;
			case "raid_update_v2":
				Type = RaidType.RaidUpdateV2;
				break;
			case "raid_go_v2":
				Type = RaidType.RaidGo;
				break;
			}
			switch (Type)
			{
			case RaidType.RaidUpdate:
				Id = Guid.Parse(((object)val.SelectToken("raid.id")).ToString());
				ChannelId = ((object)val.SelectToken("raid.source_id")).ToString();
				TargetChannelId = ((object)val.SelectToken("raid.target_id")).ToString();
				AnnounceTime = DateTime.Parse(((object)val.SelectToken("raid.announce_time")).ToString());
				RaidTime = DateTime.Parse(((object)val.SelectToken("raid.raid_time")).ToString());
				RemainigDurationSeconds = int.Parse(((object)val.SelectToken("raid.remaining_duration_seconds")).ToString());
				ViewerCount = int.Parse(((object)val.SelectToken("raid.viewer_count")).ToString());
				break;
			case RaidType.RaidUpdateV2:
				Id = Guid.Parse(((object)val.SelectToken("raid.id")).ToString());
				ChannelId = ((object)val.SelectToken("raid.source_id")).ToString();
				TargetChannelId = ((object)val.SelectToken("raid.target_id")).ToString();
				TargetLogin = ((object)val.SelectToken("raid.target_login")).ToString();
				TargetDisplayName = ((object)val.SelectToken("raid.target_display_name")).ToString();
				TargetProfileImage = ((object)val.SelectToken("raid.target_profile_image")).ToString();
				ViewerCount = int.Parse(((object)val.SelectToken("raid.viewer_count")).ToString());
				break;
			case RaidType.RaidGo:
				Id = Guid.Parse(((object)val.SelectToken("raid.id")).ToString());
				ChannelId = ((object)val.SelectToken("raid.source_id")).ToString();
				TargetChannelId = ((object)val.SelectToken("raid.target_id")).ToString();
				TargetLogin = ((object)val.SelectToken("raid.target_login")).ToString();
				TargetDisplayName = ((object)val.SelectToken("raid.target_display_name")).ToString();
				TargetProfileImage = ((object)val.SelectToken("raid.target_profile_image")).ToString();
				ViewerCount = int.Parse(((object)val.SelectToken("raid.viewer_count")).ToString());
				break;
			}
		}
	}
	public class SubMessage : MessageData
	{
		public class Emote
		{
			public int Start { get; }

			public int End { get; }

			public string Id { get; }

			public Emote(JToken json)
			{
				Start = int.Parse(((object)json.SelectToken("start")).ToString());
				End = int.Parse(((object)json.SelectToken("end")).ToString());
				Id = ((object)json.SelectToken("id")).ToString();
			}
		}

		public string Message { get; }

		public List<Emote> Emotes { get; } = new List<Emote>();


		public SubMessage(JToken json)
		{
			Message = ((object)json.SelectToken("message"))?.ToString();
			foreach (JToken item in (IEnumerable<JToken>)json.SelectToken("emotes"))
			{
				Emotes.Add(new Emote(item));
			}
		}
	}
	public class User
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "login")]
		public string Login { get; protected set; }

		[JsonProperty(PropertyName = "display_name")]
		public string DisplayName { get; protected set; }
	}
	public abstract class UserModerationNotificationsData
	{
	}
	public class VideoPlayback : MessageData
	{
		public VideoPlaybackType Type { get; }

		public string ServerTime { get; }

		public int PlayDelay { get; }

		public int Viewers { get; }

		public int Length { get; }

		public VideoPlayback(string jsonStr)
		{
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			switch (((object)val.SelectToken("type")).ToString())
			{
			case "stream-up":
				Type = VideoPlaybackType.StreamUp;
				break;
			case "stream-down":
				Type = VideoPlaybackType.StreamDown;
				break;
			case "viewcount":
				Type = VideoPlaybackType.ViewCount;
				break;
			case "commercial":
				Type = VideoPlaybackType.Commercial;
				break;
			}
			ServerTime = ((object)val.SelectToken("server_time"))?.ToString();
			switch (Type)
			{
			case VideoPlaybackType.StreamUp:
				PlayDelay = int.Parse(((object)val.SelectToken("play_delay")).ToString());
				break;
			case VideoPlaybackType.ViewCount:
				Viewers = int.Parse(((object)val.SelectToken("viewers")).ToString());
				break;
			case VideoPlaybackType.Commercial:
				Length = int.Parse(((object)val.SelectToken("length")).ToString());
				break;
			case VideoPlaybackType.StreamDown:
				break;
			}
		}
	}
	public class Whisper : MessageData
	{
		public class DataObjThread
		{
			public class SpamInfoObj
			{
				public string Likelihood { get; }

				public long LastMarkedNotSpam { get; }

				public SpamInfoObj(JToken json)
				{
					Likelihood = ((object)json.SelectToken("likelihood")).ToString();
					LastMarkedNotSpam = long.Parse(((object)json.SelectToken("last_marked_not_spam")).ToString());
				}
			}

			public string Id { get; }

			public long LastRead { get; }

			public bool Archived { get; }

			public bool Muted { get; }

			public SpamInfoObj SpamInfo { get; }

			public DataObjThread(JToken json)
			{
				Id = ((object)json.SelectToken("id")).ToString();
				LastRead = long.Parse(((object)json.SelectToken("last_read")).ToString());
				Archived = bool.Parse(((object)json.SelectToken("archived")).ToString());
				Muted = bool.Parse(((object)json.SelectToken("muted")).ToString());
				SpamInfo = new SpamInfoObj(json.SelectToken("spam_info"));
			}
		}

		public class DataObjWhisperReceived
		{
			public class TagsObj
			{
				public class EmoteObj
				{
					public string Id { get; protected set; }

					public int Start { get; protected set; }

					public int End { get; protected set; }

					public EmoteObj(JToken json)
					{
						Id = ((object)json.SelectToken("emote_id")).ToString();
						Start = int.Parse(((object)json.SelectToken("start")).ToString());
						End = int.Parse(((object)json.SelectToken("end")).ToString());
					}
				}

				public readonly List<EmoteObj> Emotes = new List<EmoteObj>();

				public readonly List<Badge> Badges = new List<Badge>();

				public string Login { get; protected set; }

				public string DisplayName { get; protected set; }

				public string Color { get; protected set; }

				public string UserType { get; protected set; }

				public TagsObj(JToken json)
				{
					Login = ((object)json.SelectToken("login"))?.ToString();
					DisplayName = ((object)json.SelectToken("login"))?.ToString();
					Color = ((object)json.SelectToken("color"))?.ToString();
					UserType = ((object)json.SelectToken("user_type"))?.ToString();
					foreach (JToken item in (IEnumerable<JToken>)json.SelectToken("emotes"))
					{
						Emotes.Add(new EmoteObj(item));
					}
					foreach (JToken item2 in (IEnumerable<JToken>)json.SelectToken("badges"))
					{
						Badges.Add(new Badge(item2));
					}
				}
			}

			public class RecipientObj
			{
				public string Id { get; protected set; }

				public string Username { get; protected set; }

				public string DisplayName { get; protected set; }

				public string Color { get; protected set; }

				public string UserType { get; protected set; }

				public RecipientObj(JToken json)
				{
					Id = ((object)json.SelectToken("id")).ToString();
					Username = ((object)json.SelectToken("username"))?.ToString();
					DisplayName = ((object)json.SelectToken("display_name"))?.ToString();
					Color = ((object)json.SelectToken("color"))?.ToString();
					UserType = ((object)json.SelectToken("user_type"))?.ToString();
				}
			}

			public class Badge
			{
				public string Id { get; protected set; }

				public string Version { get; protected set; }

				public Badge(JToken json)
				{
					Id = ((object)json.SelectToken("id"))?.ToString();
					Version = ((object)json.SelectToken("version"))?.ToString();
				}
			}

			public string Id { get; protected set; }

			public string ThreadId { get; protected set; }

			public string Body { get; protected set; }

			public long SentTs { get; protected set; }

			public string FromId { get; protected set; }

			public TagsObj Tags { get; protected set; }

			public RecipientObj Recipient { get; protected set; }

			public string Nonce { get; protected set; }

			public DataObjWhisperReceived(JToken json)
			{
				Id = ((object)json.SelectToken("id")).ToString();
				ThreadId = ((object)json.SelectToken("thread_id"))?.ToString();
				Body = ((object)json.SelectToken("body"))?.ToString();
				SentTs = long.Parse(((object)json.SelectToken("sent_ts")).ToString());
				FromId = ((object)json.SelectToken("from_id")).ToString();
				Tags = new TagsObj(json.SelectToken("tags"));
				Recipient = new RecipientObj(json.SelectToken("recipient"));
				Nonce = ((object)json.SelectToken("nonce"))?.ToString();
			}
		}

		public string Type { get; }

		public WhisperType TypeEnum { get; }

		public string Data { get; }

		public DataObjWhisperReceived DataObjectWhisperReceived { get; }

		public DataObjThread DataObjectThread { get; }

		public Whisper(string jsonStr)
		{
			JObject val = JObject.Parse(jsonStr);
			Type = ((object)((JToken)val).SelectToken("type")).ToString();
			Data = ((object)((JToken)val).SelectToken("data")).ToString();
			string type = Type;
			if (!(type == "whisper_received"))
			{
				if (type == "thread")
				{
					TypeEnum = WhisperType.Thread;
					DataObjectThread = new DataObjThread(((JToken)val).SelectToken("data_object"));
				}
				else
				{
					TypeEnum = WhisperType.Unknown;
				}
			}
			else
			{
				TypeEnum = WhisperType.WhisperReceived;
				DataObjectWhisperReceived = new DataObjWhisperReceived(((JToken)val).SelectToken("data_object"));
			}
		}
	}
}
namespace TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotificationsTypes
{
	public class AutomodCaughtMessage : UserModerationNotificationsData
	{
		[JsonProperty(PropertyName = "message_id")]
		public string MessageId { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public string Status { get; protected set; }
	}
}
namespace TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotifications
{
	public class UserModerationNotifications : MessageData
	{
		public UserModerationNotificationsType Type { get; private set; }

		public UserModerationNotificationsData Data { get; private set; }

		public string RawData { get; private set; }

		public UserModerationNotifications(string jsonStr)
		{
			RawData = jsonStr;
			JToken val = (JToken)(object)JObject.Parse(jsonStr);
			if (((object)val.SelectToken("type")).ToString() == "automod_caught_message")
			{
				Type = UserModerationNotificationsType.AutomodCaughtMessage;
				Data = JsonConvert.DeserializeObject<TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotificationsTypes.AutomodCaughtMessage>(((object)val.SelectToken("data")).ToString());
			}
			else
			{
				Type = UserModerationNotificationsType.Unknown;
			}
		}
	}
}
namespace TwitchLib.PubSub.Models.Responses.Messages.Redemption
{
	public class GlobalCooldown
	{
		[JsonProperty(PropertyName = "is_enabled")]
		public string IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "global_cooldown_seconds")]
		public int GlobalCooldownSeconds { get; protected set; }
	}
	public class MaxPerStream
	{
		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "max_per_stream")]
		public int MaxPerStreamValue { get; protected set; }
	}
	public class MaxPerUserPerStream
	{
		[JsonProperty(PropertyName = "is_enabled")]
		public string IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "max_per_user_per_stream")]
		public int MaxPerUserPerStreamValue { get; protected set; }
	}
	public class Redemption
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "user")]
		public User User { get; protected set; }

		[JsonProperty(PropertyName = "channel_id")]
		public string ChannelId { get; protected set; }

		[JsonProperty(PropertyName = "redeemed_at")]
		public DateTime RedeemedAt { get; protected set; }

		[JsonProperty(PropertyName = "reward")]
		public Reward Reward { get; protected set; }

		[JsonProperty(PropertyName = "user_input")]
		public string UserInput { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public string Status { get; protected set; }
	}
	public class RedemptionImage
	{
		[JsonProperty(PropertyName = "url_1x")]
		public string Url1x { get; protected set; }

		[JsonProperty(PropertyName = "url_2x")]
		public string Url2x { get; protected set; }

		[JsonProperty(PropertyName = "url_4x")]
		public string Url4x { get; protected set; }
	}
	public class Reward
	{
		[JsonProperty(PropertyName = "id")]
		public string Id { get; protected set; }

		[JsonProperty(PropertyName = "channel_id")]
		public string ChannelId { get; protected set; }

		[JsonProperty(PropertyName = "title")]
		public string Title { get; protected set; }

		[JsonProperty(PropertyName = "prompt")]
		public string Prompt { get; protected set; }

		[JsonProperty(PropertyName = "cost")]
		public int Cost { get; protected set; }

		[JsonProperty(PropertyName = "is_user_input_required")]
		public bool IsUserInputRequired { get; protected set; }

		[JsonProperty(PropertyName = "is_sub_only")]
		public bool IsSubOnly { get; protected set; }

		[JsonProperty(PropertyName = "image")]
		public RedemptionImage Image { get; protected set; }

		[JsonProperty(PropertyName = "default_image")]
		public RedemptionImage DefaultImage { get; protected set; }

		[JsonProperty(PropertyName = "background_color")]
		public string BackgroundColor { get; protected set; }

		[JsonProperty(PropertyName = "is_enabled")]
		public bool IsEnabled { get; protected set; }

		[JsonProperty(PropertyName = "is_paused")]
		public bool IsPaused { get; protected set; }

		[JsonProperty(PropertyName = "is_in_stock")]
		public bool IsInStock { get; protected set; }

		[JsonProperty(PropertyName = "max_per_stream")]
		public MaxPerStream MaxPerStream { get; protected set; }

		[JsonProperty(PropertyName = "should_redemptions_skip_request_queue")]
		public bool ShouldRedemptionsSkipRequestQueue { get; protected set; }

		[JsonProperty(PropertyName = "template_id")]
		public string TemplateId { get; protected set; }

		[JsonProperty(PropertyName = "updated_for_indicator_at")]
		public DateTime UpdatedForIndicatorAt { get; protected set; }

		[JsonProperty(PropertyName = "max_per_user_per_stream")]
		public MaxPerUserPerStream MaxPerUserPerStream { get; protected set; }

		[JsonProperty(PropertyName = "global_cooldown")]
		public GlobalCooldown GlobalCooldown { get; protected set; }

		[JsonProperty(PropertyName = "cooldown_expires_at")]
		public DateTime? CooldownExpiresAt { get; protected set; }
	}
	public class RewardRedeemed : ChannelPointsData
	{
		[JsonProperty(PropertyName = "timestamp")]
		public DateTime Timestamp { get; protected set; }

		[JsonProperty(PropertyName = "redemption")]
		public Redemption Redemption { get; protected set; }
	}
}
namespace TwitchLib.PubSub.Models.Responses.Messages.AutomodCaughtMessage
{
	public class Automod
	{
		[JsonProperty(PropertyName = "topics")]
		public Dictionary<string, int> Topics;
	}
	public class AutomodCaughtMessage : AutomodQueueData
	{
		[JsonProperty(PropertyName = "content_classification")]
		public ContentClassification ContentClassification { get; protected set; }

		[JsonProperty(PropertyName = "message")]
		public Message Message { get; protected set; }

		[JsonProperty(PropertyName = "reason_code")]
		public string ReasonCode { get; protected set; }

		[JsonProperty(PropertyName = "resolver_id")]
		public string ResolverId { get; protected set; }

		[JsonProperty(PropertyName = "resolver_login")]
		public string ResolverLogin { get; protected set; }

		[JsonProperty(PropertyName = "status")]
		public string Status { get; protected set; }
	}
	public class Content
	{
		[JsonProperty(PropertyName = "text")]
		public string Text;

		[JsonProperty(PropertyName = "fragments")]
		public Fragment[] Fragments;
	}
	public class ContentClassification
	{
		public string Category;

		public int Level;
	}
	public class Fragment
	{
		[JsonProperty(PropertyName = "text")]
		public string Text;

		[JsonProperty(PropertyName = "automod")]
		public Automod Automod;
	}
	public class Message
	{
		[JsonProperty(PropertyName = "content")]
		public Content Content;

		[JsonProperty(PropertyName = "id")]
		public string Id;

		[JsonProperty(PropertyName = "sender")]
		public Sender Sender;

		[JsonProperty(PropertyName = "sent_at")]
		public DateTime SentAt;
	}
	public class Sender
	{
		[JsonProperty(PropertyName = "user_id")]
		public string UserId;

		[JsonProperty(PropertyName = "login")]
		public string Login;

		[JsonProperty(PropertyName = "display_name")]
		public string DisplayName;
	}
}
namespace TwitchLib.PubSub.Interfaces
{
	public interface ITwitchPubSub
	{
		event EventHandler<OnBanArgs> OnBan;

		event EventHandler<OnBitsReceivedArgs> OnBitsReceived;

		event EventHandler<OnChannelExtensionBroadcastArgs> OnChannelExtensionBroadcast;

		event EventHandler<OnChannelSubscriptionArgs> OnChannelSubscription;

		event EventHandler<OnClearArgs> OnClear;

		event EventHandler<OnEmoteOnlyArgs> OnEmoteOnly;

		event EventHandler<OnEmoteOnlyOffArgs> OnEmoteOnlyOff;

		event EventHandler<OnFollowArgs> OnFollow;

		event EventHandler<OnHostArgs> OnHost;

		event EventHandler<OnMessageDeletedArgs> OnMessageDeleted;

		event EventHandler<OnListenResponseArgs> OnListenResponse;

		event EventHandler OnPubSubServiceClosed;

		event EventHandler OnPubSubServiceConnected;

		event EventHandler<OnPubSubServiceErrorArgs> OnPubSubServiceError;

		event EventHandler<OnR9kBetaArgs> OnR9kBeta;

		event EventHandler<OnR9kBetaOffArgs> OnR9kBetaOff;

		event EventHandler<OnStreamDownArgs> OnStreamDown;

		event EventHandler<OnStreamUpArgs> OnStreamUp;

		event EventHandler<OnSubscribersOnlyArgs> OnSubscribersOnly;

		event EventHandler<OnSubscribersOnlyOffArgs> OnSubscribersOnlyOff;

		event EventHandler<OnTimeoutArgs> OnTimeout;

		event EventHandler<OnUnbanArgs> OnUnban;

		event EventHandler<OnUntimeoutArgs> OnUntimeout;

		event EventHandler<OnViewCountArgs> OnViewCount;

		event EventHandler<OnWhisperArgs> OnWhisper;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		event EventHandler<OnCustomRewardCreatedArgs> OnCustomRewardCreated;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		event EventHandler<OnCustomRewardUpdatedArgs> OnCustomRewardUpdated;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		event EventHandler<OnCustomRewardDeletedArgs> OnCustomRewardDeleted;

		[Obsolete("This event fires on an undocumented/retired/obsolete topic.", false)]
		event EventHandler<OnRewardRedeemedArgs> OnRewardRedeemed;

		event EventHandler<OnChannelPointsRewardRedeemedArgs> OnChannelPointsRewardRedeemed;

		event EventHandler<OnLeaderboardEventArgs> OnLeaderboardSubs;

		event EventHandler<OnLeaderboardEventArgs> OnLeaderboardBits;

		event EventHandler<OnRaidUpdateArgs> OnRaidUpdate;

		event EventHandler<OnRaidUpdateV2Args> OnRaidUpdateV2;

		event EventHandler<OnRaidGoArgs> OnRaidGo;

		event EventHandler<OnLogArgs> OnLog;

		event EventHandler<OnCommercialArgs> OnCommercial;

		event EventHandler<OnPredictionArgs> OnPrediction;

		void Connect();

		void Disconnect();

		[Obsolete("This topic is deprecated by Twitch. Please use ListenToBitsEventsV2()", false)]
		void ListenToBitsEvents(string channelTwitchId);

		void ListenToChannelExtensionBroadcast(string channelId, string extensionId);

		void ListenToChatModeratorActions(string myTwitchId, string channelTwitchId);

		void ListenToFollows(string channelId);

		void ListenToSubscriptions(string channelId);

		void ListenToVideoPlayback(string channelName);

		void ListenToWhispers(string channelTwitchId);

		[Obsolete("This method listens to an undocumented/retired/obsolete topic. Consider using ListenToChannelPoints()", false)]
		void ListenToRewards(string channelTwitchId);

		void ListenToChannelPoints(string channelTwitchId);

		void ListenToLeaderboards(string channelTwitchId);

		void ListenToRaid(string channelTwitchId);

		void ListenToPredictions(string channelTwitchId);

		void SendTopics(string oauth = null, bool unlisten = false);

		void TestMessageParser(string testJsonString);
	}
}
namespace TwitchLib.PubSub.Extensions
{
	public static class JSONObjectExtensions
	{
		public static bool IsEmpty(this JToken token)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			if (token != null && ((int)token.Type != 2 || token.HasValues) && ((int)token.Type != 1 || token.HasValues) && ((int)token.Type != 8 || !(((object)token).ToString() == string.Empty)))
			{
				return (int)token.Type == 10;
			}
			return true;
		}
	}
}
namespace TwitchLib.PubSub.Events
{
	public class OnAutomodCaughtMessageArgs
	{
		public TwitchLib.PubSub.Models.Responses.Messages.AutomodCaughtMessage.AutomodCaughtMessage AutomodCaughtMessage;

		public string ChannelId;
	}
	public class OnAutomodCaughtUserMessage
	{
		public TwitchLib.PubSub.Models.Responses.Messages.UserModerationNotificationsTypes.AutomodCaughtMessage AutomodCaughtMessage;

		public string ChannelId;

		public string UserId;
	}
	public class OnBanArgs : EventArgs
	{
		public string BannedUserId;

		public string BannedUser;

		public string BanReason;

		public string BannedBy;

		public string BannedByUserId;

		public string ChannelId;
	}
	public class OnBitsReceivedArgs : EventArgs
	{
		public string Username;

		public string ChannelName;

		public string UserId;

		public string ChannelId;

		public string Time;

		public string ChatMessage;

		public int BitsUsed;

		public int TotalBitsUsed;

		public string Context;
	}
	public class OnBitsReceivedV2Args
	{
		public string UserName { get; internal set; }

		public string ChannelName { get; internal set; }

		public string UserId { get; internal set; }

		public string ChannelId { get; internal set; }

		public DateTime Time { get; internal set; }

		public string ChatMessage { get; internal set; }

		public int BitsUsed { get; internal set; }

		public int TotalBitsUsed { get; internal set; }

		public bool IsAnonymous { get; internal set; }

		public string Context { get; internal set; }
	}
	public class OnChannelExtensionBroadcastArgs : EventArgs
	{
		public List<string> Messages;

		public string ChannelId;
	}
	public class OnChannelPointsRewardRedeemedArgs : EventArgs
	{
		public string ChannelId { get; internal set; }

		public RewardRedeemed RewardRedeemed { get; internal set; }
	}
	public class OnChannelSubscriptionArgs : EventArgs
	{
		public ChannelSubscription Subscription;

		public string ChannelId;
	}
	public class OnClearArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnCommercialArgs : EventArgs
	{
		public int Length;

		public string ServerTime;

		public string ChannelId;
	}
	public class OnCustomRewardCreatedArgs : EventArgs
	{
		public DateTime TimeStamp;

		public string ChannelId;

		public Guid RewardId;

		public string RewardTitle;

		public string RewardPrompt;

		public int RewardCost;
	}
	public class OnCustomRewardDeletedArgs
	{
		public DateTime TimeStamp;

		public string ChannelId;

		public Guid RewardId;

		public string RewardTitle;

		public string RewardPrompt;
	}
	public class OnCustomRewardUpdatedArgs : EventArgs
	{
		public DateTime TimeStamp;

		public string ChannelId;

		public Guid RewardId;

		public string RewardTitle;

		public string RewardPrompt;

		public int RewardCost;
	}
	public class OnEmoteOnlyArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnEmoteOnlyOffArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnFollowArgs : EventArgs
	{
		public string FollowedChannelId;

		public string DisplayName;

		public string Username;

		public string UserId;
	}
	public class OnHostArgs : EventArgs
	{
		public string Moderator;

		public string HostedChannel;

		public string ChannelId;
	}
	public class OnLeaderboardEventArgs : EventArgs
	{
		public string ChannelId;

		public List<LeaderBoard> TopList;
	}
	public class OnListenResponseArgs : EventArgs
	{
		public string Topic;

		public Response Response;

		public bool Successful;

		public string ChannelId;
	}
	public class OnLogArgs : EventArgs
	{
		public string Data;
	}
	public class OnMessageDeletedArgs : EventArgs
	{
		public string TargetUser;

		public string TargetUserId;

		public string DeletedBy;

		public string DeletedByUserId;

		public string Message;

		public string MessageId;

		public string ChannelId;
	}
	public class OnPredictionArgs : EventArgs
	{
		public PredictionType Type;

		public Guid Id;

		public string ChannelId;

		public DateTime? CreatedAt;

		public DateTime? LockedAt;

		public DateTime? EndedAt;

		public ICollection<Outcome> Outcomes;

		public PredictionStatus Status;

		public string Title;

		public Guid? WinningOutcomeId;

		public int PredictionTime;
	}
	public class OnPubSubServiceErrorArgs : EventArgs
	{
		public Exception Exception;
	}
	public class OnR9kBetaArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnR9kBetaOffArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnRaidGoArgs : EventArgs
	{
		public string ChannelId;

		public Guid Id;

		public string TargetChannelId;

		public string TargetLogin;

		public string TargetDisplayName;

		public string TargetProfileImage;

		public int ViewerCount;
	}
	public class OnRaidUpdateArgs : EventArgs
	{
		public string ChannelId;

		public Guid Id;

		public string TargetChannelId;

		public DateTime AnnounceTime;

		public DateTime RaidTime;

		public int RemainingDurationSeconds;

		public int ViewerCount;
	}
	public class OnRaidUpdateV2Args : EventArgs
	{
		public string ChannelId;

		public Guid Id;

		public string TargetChannelId;

		public string TargetLogin;

		public string TargetDisplayName;

		public string TargetProfileImage;

		public int ViewerCount;
	}
	public class OnRewardRedeemedArgs : EventArgs
	{
		public DateTime TimeStamp;

		public string ChannelId;

		public string Login;

		public string DisplayName;

		public string Message;

		public Guid RewardId;

		public string RewardTitle;

		public string RewardPrompt;

		public int RewardCost;

		public string Status;

		public Guid RedemptionId;
	}
	public class OnStreamDownArgs : EventArgs
	{
		public string ServerTime;

		public string ChannelId;
	}
	public class OnStreamUpArgs : EventArgs
	{
		public string ServerTime;

		public int PlayDelay;

		public string ChannelId;
	}
	public class OnSubscribersOnlyArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnSubscribersOnlyOffArgs : EventArgs
	{
		public string Moderator;

		public string ChannelId;
	}
	public class OnTimeoutArgs : EventArgs
	{
		public string TimedoutUserId;

		public string TimedoutUser;

		public TimeSpan TimeoutDuration;

		public string TimeoutReason;

		public string TimedoutBy;

		public string TimedoutById;

		public string ChannelId;
	}
	public class OnUnbanArgs : EventArgs
	{
		public string UnbannedUser;

		public string UnbannedUserId;

		public string UnbannedBy;

		public string UnbannedByUserId;

		public string ChannelId;
	}
	public class OnUntimeoutArgs : EventArgs
	{
		public string UntimeoutedUser;

		public string UntimeoutedUserId;

		public string UntimeoutedBy;

		public string UntimeoutedByUserId;

		public string ChannelId;
	}
	public class OnViewCountArgs : EventArgs
	{
		public string ServerTime;

		public int Viewers;

		public string ChannelId;
	}
	public class OnWhisperArgs : EventArgs
	{
		public Whisper Whisper;

		public string ChannelId;
	}
}
namespace TwitchLib.PubSub.Enums
{
	public enum AutomodQueueType
	{
		CaughtMessage,
		Unknown
	}
	public enum ChannelPointsChannelType
	{
		RewardRedeemed,
		Unknown
	}
	public enum CommunityPointsChannelType
	{
		RewardRedeemed,
		CustomRewardUpdated,
		CustomRewardCreated,
		CustomRewardDeleted
	}
	public enum LeaderBoardType
	{
		BitsUsageByChannel,
		SubGiftSent
	}
	public enum PredictionStatus
	{
		Canceled = -4,
		CancelPending,
		Resolved,
		ResolvePending,
		Locked,
		Active
	}
	public enum PredictionType
	{
		EventCreated,
		EventUpdated
	}
	public enum PubSubRequestType
	{
		ListenToTopic
	}
	public enum RaidType
	{
		RaidUpdate,
		RaidUpdateV2,
		RaidGo
	}
	public enum SubscriptionPlan
	{
		NotSet,
		Prime,
		Tier1,
		Tier2,
		Tier3
	}
	public enum UserModerationNotificationsType
	{
		AutomodCaughtMessage,
		Unknown
	}
	public enum VideoPlaybackType
	{
		StreamUp,
		StreamDown,
		ViewCount,
		Commercial
	}
	public enum WhisperType
	{
		WhisperReceived,
		Thread,
		Unknown
	}
}
namespace TwitchLib.PubSub.Common
{
	public static class Helpers
	{
		public static DateTime DateTimeStringToObject(string dateTime)
		{
			if (dateTime != null)
			{
				return Convert.ToDateTime(dateTime);
			}
			return default(DateTime);
		}

		public static string Base64Encode(string plainText)
		{
			return Convert.ToBase64String(Encoding.UTF8.GetBytes(plainText));
		}
	}
}