Иконка ресурса

FREE TPNotifications : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;

namespace Oxide.Plugins
{
	[Info("TPNotifications", "pluginfuel.ru", "1.0.0")]
	[Description("Система уведомлений с интеграцией VK API")]
	class TPNotifications : RustPlugin
	{
		#region Variables
		[PluginReference] Plugin ImageLibrary, TPMenuSystem;
		
		private static TPNotifications _instance;
		private const string Layer = "TPNotifications_UI";
		private Dictionary<ulong, PlayerData> _playerData = new Dictionary<ulong, PlayerData>();
		private List<SentNotification> _sentNotifications = new List<SentNotification>();
		private Dictionary<ulong, PendingVerification> _pendingVerifications = new Dictionary<ulong, PendingVerification>();
		private Dictionary<ulong, string> _tempVkIds = new Dictionary<ulong, string>();
		#endregion

		#region Data Classes
		public class PlayerData
		{
			[JsonProperty("Ник игрока")]
			public string DisplayName { get; set; }
			
			[JsonProperty("VK ID")]
			public string VkId { get; set; } = "";
			
			[JsonProperty("VK Подтвержден")]
			public bool VkConfirmed { get; set; } = false;
			
			[JsonProperty("История уведомлений")]
			public List<NotificationHistory> History { get; set; } = new List<NotificationHistory>();
			
			[JsonProperty("Настройки уведомлений")]
			public NotificationSettings Settings { get; set; } = new NotificationSettings();
		}

		public class NotificationHistory
		{
			[JsonProperty("Тип")]
			public string Type { get; set; }
			
			[JsonProperty("Сообщение")]
			public string Message { get; set; }
			
			[JsonProperty("Время")]
			public string Timestamp { get; set; }
			
			[JsonProperty("Прочитано")]
			public bool IsRead { get; set; }
		}

		public class NotificationSettings
		{
			[JsonProperty("Рейды")]
			public bool Raid { get; set; } = true;
			
			[JsonProperty("Убийства")]
			public bool Kill { get; set; } = true;
			
			[JsonProperty("Награды")]
			public bool Reward { get; set; } = true;
			
			[JsonProperty("Сообщения админов")]
			public bool AdminMessage { get; set; } = true;
			
			[JsonProperty("Вайп")]
			public bool Wipe { get; set; } = true;
		}

		public class PendingVerification
		{
			public string VkId { get; set; }
			public string Code { get; set; }
			public DateTime ExpiresAt { get; set; }
		}

		public class SentNotification
		{
			[JsonProperty("Тип")]
			public string Type { get; set; }
			
			[JsonProperty("Сообщение")]
			public string Message { get; set; }
			
			[JsonProperty("Время")]
			public string Timestamp { get; set; }
			
			[JsonProperty("Статус")]
			public string Status { get; set; }
		}
		#endregion

		#region Configuration
		private Configuration _config;

		public class Configuration
		{
			[JsonProperty("VK API Settings")]
			public VKAPISettings VKSettings { get; set; } = new VKAPISettings();

			[JsonProperty("Notification Types")]
			public NotificationTypesConfig NotificationTypes { get; set; } = new NotificationTypesConfig();

			[JsonProperty("Settings")]
			public GeneralSettings Settings { get; set; } = new GeneralSettings();

			public class VKAPISettings
			{
				[JsonProperty("VK_Token")]
				public string VKToken { get; set; } = "СТАВИМ_СЮДА";

				[JsonProperty("Group_ID")]
				public string GroupID { get; set; } = "public141783468";

				[JsonProperty("Chat_ID")]
				public string ChatID { get; set; } = "1";

				[JsonProperty("API_Version")]
				public string APIVersion { get; set; } = "v=5.199";
			}

			public class NotificationTypesConfig
			{
				[JsonProperty("Raid")]
				public bool Raid { get; set; } = true;

				[JsonProperty("Kill")]
				public bool Kill { get; set; } = true;

				[JsonProperty("Reward")]
				public bool Reward { get; set; } = true;

				[JsonProperty("AdminMessage")]
				public bool AdminMessage { get; set; } = true;

				[JsonProperty("Wipe")]
				public bool Wipe { get; set; } = true;
			}

			public class GeneralSettings
			{
				[JsonProperty("Enable_Notifications")]
				public bool EnableNotifications { get; set; } = true;

				[JsonProperty("Max_History_Items")]
				public int MaxHistoryItems { get; set; } = 50;

				[JsonProperty("Notification_Prefix")]
				public string NotificationPrefix { get; set; } = "[СЕРВЕР]";
			}
		}

		protected override void LoadConfig()
		{
			base.LoadConfig();
			try
			{
				_config = Config.ReadObject<Configuration>();
				if (_config == null)
				{
					LoadDefaultConfig();
				}
			}
			catch
			{
				PrintWarning("Ошибка чтения конфигурации, создаем новую");
				LoadDefaultConfig();
			}
			SaveConfig();
		}

		protected override void LoadDefaultConfig()
		{
			_config = new Configuration();
		}

		protected override void SaveConfig()
		{
			Config.WriteObject(_config, true);
		}
		#endregion

		#region Oxide Hooks
		void Init()
		{
			_instance = this;
			LoadData();
		}

		void OnServerInitialized()
		{
			// Регистрация команды для меню
			cmd.AddConsoleCommand("tpnotifications.open", this, nameof(CmdOpenNotifications));
		}

		void Unload()
		{
			SaveData();
			foreach (var player in BasePlayer.activePlayerList)
			{
				DestroyUI(player);
			}
			_instance = null;
		}

		void OnPlayerDisconnected(BasePlayer player, string reason)
		{
			DestroyUI(player);
		}
		#endregion

		#region Data Management
		void LoadData()
		{
			try
			{
				_playerData = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, PlayerData>>("TPSystem/TPNotifications/PlayerData");
				if (_playerData == null)
					_playerData = new Dictionary<ulong, PlayerData>();
			}
			catch
			{
				_playerData = new Dictionary<ulong, PlayerData>();
			}

			try
			{
				_sentNotifications = Interface.Oxide.DataFileSystem.ReadObject<List<SentNotification>>("TPSystem/TPNotifications/SentLog");
				if (_sentNotifications == null)
					_sentNotifications = new List<SentNotification>();
			}
			catch
			{
				_sentNotifications = new List<SentNotification>();
			}
		}

		void SaveData()
		{
			Interface.Oxide.DataFileSystem.WriteObject("TPSystem/TPNotifications/PlayerData", _playerData);
			Interface.Oxide.DataFileSystem.WriteObject("TPSystem/TPNotifications/SentLog", _sentNotifications);
		}

		PlayerData GetPlayerData(ulong userId)
		{
			if (!_playerData.ContainsKey(userId))
			{
				var player = BasePlayer.FindByID(userId);
				if (player != null)
				{
					_playerData[userId] = new PlayerData
					{
						DisplayName = player.displayName
					};
				}
			}
			return _playerData.ContainsKey(userId) ? _playerData[userId] : null;
		}

		void AddNotificationToHistory(ulong userId, string type, string message)
		{
			var data = GetPlayerData(userId);
			if (data == null) return;

			var notification = new NotificationHistory
			{
				Type = type,
				Message = message,
				Timestamp = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"),
				IsRead = false
			};

			data.History.Insert(0, notification);

			// Ограничение истории
			if (data.History.Count > _config.Settings.MaxHistoryItems)
			{
				data.History = data.History.Take(_config.Settings.MaxHistoryItems).ToList();
			}

			SaveData();
		}

		void LogSentNotification(string type, string message, string status)
		{
			var log = new SentNotification
			{
				Type = type,
				Message = message,
				Timestamp = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"),
				Status = status
			};

			_sentNotifications.Add(log);
			SaveData();
		}
		#endregion

		#region VK API
		private string URLEncode(string input)
		{
			return UnityEngine.Networking.UnityWebRequest.EscapeURL(input);
		}

		private int GetRandomId()
		{
			return UnityEngine.Random.Range(0, 999999999);
		}

		void SendVKNotification(string userIds, string message)
		{
			if (!_config.Settings.EnableNotifications)
			{
				LogSentNotification("VK", message, "Disabled");
				return;
			}

			if (string.IsNullOrEmpty(_config.VKSettings.VKToken) || _config.VKSettings.VKToken == "СТАВИМ_СЮДА")
			{
				PrintWarning("VK Token не настроен!");
				LogSentNotification("VK", message, "No Token");
				return;
			}

			string url = $"https://api.vk.com/method/messages.send?user_ids={userIds}&message={URLEncode(message)}&{_config.VKSettings.APIVersion}&random_id={GetRandomId()}&access_token={_config.VKSettings.VKToken}";
			
			webrequest.Enqueue(url, null, (code, response) =>
			{
				if (code == 200)
				{
					LogSentNotification("VK", message, "Success");
					Puts($"VK уведомление отправлено: {message}");
				}
				else
				{
					LogSentNotification("VK", message, $"Error {code}");
					PrintWarning($"Ошибка отправки VK уведомления: {code}");
				}
			}, this);
		}

		void SendVKNotificationToGroup(string message)
		{
			if (!_config.Settings.EnableNotifications)
			{
				LogSentNotification("VK Group", message, "Disabled");
				return;
			}

			if (string.IsNullOrEmpty(_config.VKSettings.VKToken) || _config.VKSettings.VKToken == "СТАВИМ_СЮДА")
			{
				PrintWarning("VK Token не настроен!");
				LogSentNotification("VK Group", message, "No Token");
				return;
			}

			// Для отправки в группу используется wall.post или другой метод
			// Здесь используем простой пример с messages.send для chat_id
			string url = $"https://api.vk.com/method/messages.send?chat_id={_config.VKSettings.ChatID}&message={URLEncode(message)}&{_config.VKSettings.APIVersion}&random_id={GetRandomId()}&access_token={_config.VKSettings.VKToken}";
			
			webrequest.Enqueue(url, null, (code, response) =>
			{
				if (code == 200)
				{
					LogSentNotification("VK Group", message, "Success");
					Puts($"VK групповое уведомление отправлено: {message}");
				}
				else
				{
					LogSentNotification("VK Group", message, $"Error {code}");
					PrintWarning($"Ошибка отправки VK группового уведомления: {code}");
				}
			}, this);
		}

		string GenerateVerificationCode()
		{
			return UnityEngine.Random.Range(100000, 999999).ToString();
		}

		void StartVkVerification(BasePlayer player, string vkId)
		{
			var data = GetPlayerData(player.userID);
			if (data == null) return;

			// Генерируем код
			string code = GenerateVerificationCode();
			
			// Сохраняем ожидание подтверждения (код действует 10 минут)
			_pendingVerifications[player.userID] = new PendingVerification
			{
				VkId = vkId,
				Code = code,
				ExpiresAt = DateTime.Now.AddMinutes(10)
			};

			// Отправляем код в VK
			string message = $"Ваш код подтверждения для сервера: {code}\nКод действителен 10 минут.";
			SendVKNotification(vkId, message);

			// Уведомляем игрока
			player.ChatMessage($"<color=#4CAF50>[Уведомления]</color> Код подтверждения отправлен в VK. Введите его в окне подтверждения.");
		}

		bool ConfirmVkVerification(BasePlayer player, string code)
		{
			if (!_pendingVerifications.ContainsKey(player.userID))
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Нет активного запроса на привязку VK.");
				return false;
			}

			var pending = _pendingVerifications[player.userID];

			// Проверяем срок действия
			if (DateTime.Now > pending.ExpiresAt)
			{
				_pendingVerifications.Remove(player.userID);
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Код подтверждения истек. Попробуйте снова.");
				return false;
			}

			// Проверяем код
			if (pending.Code != code)
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Неверный код подтверждения.");
				return false;
			}

			// Подтверждаем привязку
			var data = GetPlayerData(player.userID);
			if (data != null)
			{
				data.VkId = pending.VkId;
				data.VkConfirmed = true;
				SaveData();
			}

			_pendingVerifications.Remove(player.userID);
			player.ChatMessage($"<color=#4CAF50>[Успех]</color> VK успешно привязан!");
			return true;
		}

		void UnlinkVk(BasePlayer player)
		{
			var data = GetPlayerData(player.userID);
			if (data != null)
			{
				data.VkId = "";
				data.VkConfirmed = false;
				SaveData();
				player.ChatMessage($"<color=#FFC107>[Уведомления]</color> VK отвязан от вашего аккаунта.");
			}
		}
		#endregion

		#region API Methods
		// API для вызова из других плагинов
		void SendRaidNotification(BasePlayer player, string raiderName)
		{
			if (!_config.NotificationTypes.Raid) return;

			var data = GetPlayerData(player.userID);
			if (data != null && !data.Settings.Raid) return;

			string message = $"{_config.Settings.NotificationPrefix} Твой дом рейдит {raiderName}!";
			
			AddNotificationToHistory(player.userID, "Рейд", message);
			
			// Отправляем в VK если привязан
			if (data != null && data.VkConfirmed && !string.IsNullOrEmpty(data.VkId))
			{
				SendVKNotification(data.VkId, message);
			}
		}

		void SendKillNotification(BasePlayer player, string killerName)
		{
			if (!_config.NotificationTypes.Kill) return;

			var data = GetPlayerData(player.userID);
			if (data != null && !data.Settings.Kill) return;

			string message = $"{_config.Settings.NotificationPrefix} Тебя убил {killerName}!";
			
			AddNotificationToHistory(player.userID, "Убийство", message);
			
			// Отправляем в VK если привязан
			if (data != null && data.VkConfirmed && !string.IsNullOrEmpty(data.VkId))
			{
				SendVKNotification(data.VkId, message);
			}
		}

		void SendRewardNotification(BasePlayer player, string rewardName)
		{
			if (!_config.NotificationTypes.Reward) return;

			var data = GetPlayerData(player.userID);
			if (data != null && !data.Settings.Reward) return;

			string message = $"{_config.Settings.NotificationPrefix} Ты получил награду: {rewardName}!";
			
			AddNotificationToHistory(player.userID, "Награда", message);
			
			// Отправляем в VK если привязан
			if (data != null && data.VkConfirmed && !string.IsNullOrEmpty(data.VkId))
			{
				SendVKNotification(data.VkId, message);
			}
		}

		void SendAdminMessage(string message)
		{
			if (!_config.NotificationTypes.AdminMessage) return;

			string fullMessage = $"{_config.Settings.NotificationPrefix} {message}";
			
			// Отправляем всем игрокам
			foreach (var player in BasePlayer.activePlayerList)
			{
				var data = GetPlayerData(player.userID);
				if (data != null && data.Settings.AdminMessage)
				{
					AddNotificationToHistory(player.userID, "Админ", fullMessage);
				}
			}

			// Отправляем в VK группу
			SendVKNotificationToGroup(fullMessage);
		}

		void SendWipeNotification()
		{
			if (!_config.NotificationTypes.Wipe) return;

			string message = $"{_config.Settings.NotificationPrefix} Внимание! Скоро вайп сервера!";
			
			// Отправляем всем игрокам
			foreach (var player in BasePlayer.activePlayerList)
			{
				var data = GetPlayerData(player.userID);
				if (data != null && data.Settings.Wipe)
				{
					AddNotificationToHistory(player.userID, "Вайп", message);
				}
			}

			// Отправляем в VK группу
			SendVKNotificationToGroup(message);
		}
		#endregion

		#region UI
		void CmdOpenNotifications(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			OpenNotificationsUI(player);
		}

		void OpenNotificationsUI(BasePlayer player)
		{
			DestroyUI(player);

			var data = GetPlayerData(player.userID);
			if (data == null)
			{
				data = new PlayerData { DisplayName = player.displayName };
				_playerData[player.userID] = data;
			}

			CuiElementContainer container = new CuiElementContainer();

			// Главная панель
			container.Add(new CuiPanel
			{
				RectTransform = { AnchorMin = "0.15 0.15", AnchorMax = "0.85 0.85" },
				Image = { Color = "0.1 0.1 0.1 0.95" }
			}, "Overlay", Layer);

			// Заголовок
			container.Add(new CuiLabel
			{
				RectTransform = { AnchorMin = "0 0.92", AnchorMax = "1 1" },
				Text = { Text = "ОПОВЕЩЕНИЯ", Font = "robotocondensed-bold.ttf", FontSize = 24, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Кнопка закрытия
			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.92 0.92", AnchorMax = "0.99 0.99" },
				Button = { Command = "tpnotifications.close", Color = "0.8 0.2 0.2 0.8" },
				Text = { Text = "X", Font = "robotocondensed-bold.ttf", FontSize = 20, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Вкладки
			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.02 0.85", AnchorMax = "0.23 0.90" },
				Button = { Command = "tpnotifications.tab history", Color = "0.3 0.3 0.3 0.8" },
				Text = { Text = "История", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.25 0.85", AnchorMax = "0.46 0.90" },
				Button = { Command = "tpnotifications.tab settings", Color = "0.2 0.2 0.2 0.8" },
				Text = { Text = "Настройки", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.48 0.85", AnchorMax = "0.69 0.90" },
				Button = { Command = "tpnotifications.tab vklink", Color = "0.2 0.2 0.2 0.8" },
				Text = { Text = "Привязка VK", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Профиль VK если привязан
			if (data.VkConfirmed && !string.IsNullOrEmpty(data.VkId))
			{
				container.Add(new CuiPanel
				{
					RectTransform = { AnchorMin = "0.02 0.78", AnchorMax = "0.98 0.84" },
					Image = { Color = "0.15 0.6 0.3 0.3" }
				}, Layer, $"{Layer}_vkprofile");

				// Иконка VK
				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.01 0.1", AnchorMax = "0.08 0.9" },
					Text = { Text = "VK", Font = "robotocondensed-bold.ttf", FontSize = 20, Align = TextAnchor.MiddleCenter, Color = "0.3 0.6 0.9 1" }
				}, $"{Layer}_vkprofile");

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.09 0.1", AnchorMax = "0.5 0.9" },
					Text = { Text = $"VK ID: {data.VkId}", Font = "robotocondensed-regular.ttf", FontSize = 13, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1" }
				}, $"{Layer}_vkprofile");

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.5 0.1", AnchorMax = "0.85 0.9" },
					Text = { Text = "✓ Уведомления в VK включены", Font = "robotocondensed-regular.ttf", FontSize = 12, Align = TextAnchor.MiddleLeft, Color = "0.4 0.8 0.4 1" }
				}, $"{Layer}_vkprofile");

				container.Add(new CuiButton
				{
					RectTransform = { AnchorMin = "0.87 0.15", AnchorMax = "0.99 0.85" },
					Button = { Command = "tpnotifications.tab vklink", Color = "0.3 0.3 0.3 0.8" },
					Text = { Text = "Настроить", Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
				}, $"{Layer}_vkprofile");
			}

			// Контент - История уведомлений
			float yPos = data.VkConfirmed && !string.IsNullOrEmpty(data.VkId) ? 0.73f : 0.80f;
			int count = 0;
			foreach (var notification in data.History.Take(10))
			{
				float yMin = yPos - 0.07f;
				float yMax = yPos;

				string color = notification.IsRead ? "0.2 0.2 0.2 0.6" : "0.3 0.4 0.3 0.7";

				container.Add(new CuiPanel
				{
					RectTransform = { AnchorMin = $"0.02 {yMin}", AnchorMax = $"0.98 {yMax}" },
					Image = { Color = color }
				}, Layer, $"{Layer}_notification_{count}");

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.02 0.5", AnchorMax = "0.2 1" },
					Text = { Text = $"[{notification.Type}]", Font = "robotocondensed-bold.ttf", FontSize = 12, Align = TextAnchor.MiddleLeft, Color = "1 0.8 0.2 1" }
				}, $"{Layer}_notification_{count}");

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.02 0", AnchorMax = "0.98 0.5" },
					Text = { Text = notification.Message, Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleLeft, Color = "0.9 0.9 0.9 1" }
				}, $"{Layer}_notification_{count}");

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.75 0.5", AnchorMax = "0.98 1" },
					Text = { Text = notification.Timestamp, Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleRight, Color = "0.7 0.7 0.7 1" }
				}, $"{Layer}_notification_{count}");

				yPos -= 0.08f;
				count++;

				if (!notification.IsRead)
				{
					notification.IsRead = true;
				}
			}

			if (data.History.Count == 0)
			{
				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.02 0.4", AnchorMax = "0.98 0.5" },
					Text = { Text = "Нет уведомлений", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "0.6 0.6 0.6 1" }
				}, Layer);
			}

			SaveData();
			CuiHelper.AddUi(player, container);
		}

		void OpenSettingsUI(BasePlayer player)
		{
			DestroyUI(player);

			var data = GetPlayerData(player.userID);
			if (data == null) return;

			CuiElementContainer container = new CuiElementContainer();

			// Главная панель
			container.Add(new CuiPanel
			{
				RectTransform = { AnchorMin = "0.15 0.15", AnchorMax = "0.85 0.85" },
				Image = { Color = "0.1 0.1 0.1 0.95" }
			}, "Overlay", Layer);

			// Заголовок
			container.Add(new CuiLabel
			{
				RectTransform = { AnchorMin = "0 0.92", AnchorMax = "1 1" },
				Text = { Text = "НАСТРОЙКИ ОПОВЕЩЕНИЙ", Font = "robotocondensed-bold.ttf", FontSize = 24, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Кнопка закрытия
			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.92 0.92", AnchorMax = "0.99 0.99" },
				Button = { Command = "tpnotifications.close", Color = "0.8 0.2 0.2 0.8" },
				Text = { Text = "X", Font = "robotocondensed-bold.ttf", FontSize = 20, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Вкладки
			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.02 0.85", AnchorMax = "0.23 0.90" },
				Button = { Command = "tpnotifications.tab history", Color = "0.2 0.2 0.2 0.8" },
				Text = { Text = "История", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.25 0.85", AnchorMax = "0.46 0.90" },
				Button = { Command = "tpnotifications.tab settings", Color = "0.3 0.3 0.3 0.8" },
				Text = { Text = "Настройки", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Настройки
			float yPos = 0.75f;
			var settings = new Dictionary<string, bool>
			{
				{ "Рейды", data.Settings.Raid },
				{ "Убийства", data.Settings.Kill },
				{ "Награды", data.Settings.Reward },
				{ "Сообщения админов", data.Settings.AdminMessage },
				{ "Вайп", data.Settings.Wipe }
			};

			foreach (var setting in settings)
			{
				float yMin = yPos - 0.08f;
				float yMax = yPos;

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = $"0.1 {yMin}", AnchorMax = $"0.6 {yMax}" },
					Text = { Text = setting.Key, Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1" }
				}, Layer);

				string buttonText = setting.Value ? "ВКЛ" : "ВЫКЛ";
				string buttonColor = setting.Value ? "0.2 0.6 0.2 0.8" : "0.6 0.2 0.2 0.8";
				string settingKey = setting.Key.ToLower().Replace(" ", "_");

				container.Add(new CuiButton
				{
					RectTransform = { AnchorMin = $"0.7 {yMin + 0.01}", AnchorMax = $"0.9 {yMax - 0.01}" },
					Button = { Command = $"tpnotifications.toggle {settingKey}", Color = buttonColor },
					Text = { Text = buttonText, Font = "robotocondensed-bold.ttf", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
				}, Layer);

				yPos -= 0.10f;
			}

			CuiHelper.AddUi(player, container);
		}

		void OpenVkLinkUI(BasePlayer player)
		{
			DestroyUI(player);

			var data = GetPlayerData(player.userID);
			if (data == null) return;

			CuiElementContainer container = new CuiElementContainer();

			// Главная панель
			container.Add(new CuiPanel
			{
				RectTransform = { AnchorMin = "0.15 0.15", AnchorMax = "0.85 0.85" },
				Image = { Color = "0.1 0.1 0.1 0.95" }
			}, "Overlay", Layer);

			// Заголовок
			container.Add(new CuiLabel
			{
				RectTransform = { AnchorMin = "0 0.92", AnchorMax = "1 1" },
				Text = { Text = "ПРИВЯЗКА VK", Font = "robotocondensed-bold.ttf", FontSize = 24, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Кнопка закрытия
			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.92 0.92", AnchorMax = "0.99 0.99" },
				Button = { Command = "tpnotifications.close", Color = "0.8 0.2 0.2 0.8" },
				Text = { Text = "X", Font = "robotocondensed-bold.ttf", FontSize = 20, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Вкладки
			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.02 0.85", AnchorMax = "0.23 0.90" },
				Button = { Command = "tpnotifications.tab history", Color = "0.2 0.2 0.2 0.8" },
				Text = { Text = "История", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.25 0.85", AnchorMax = "0.46 0.90" },
				Button = { Command = "tpnotifications.tab settings", Color = "0.2 0.2 0.2 0.8" },
				Text = { Text = "Настройки", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			container.Add(new CuiButton
			{
				RectTransform = { AnchorMin = "0.48 0.85", AnchorMax = "0.69 0.90" },
				Button = { Command = "tpnotifications.tab vklink", Color = "0.3 0.3 0.3 0.8" },
				Text = { Text = "Привязка VK", Font = "robotocondensed-regular.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
			}, Layer);

			// Контент
			if (data.VkConfirmed && !string.IsNullOrEmpty(data.VkId))
			{
				// VK уже привязан
				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.1 0.65", AnchorMax = "0.9 0.75" },
					Text = { Text = $"VK ID: {data.VkId}", Font = "robotocondensed-regular.ttf", FontSize = 16, Align = TextAnchor.MiddleCenter, Color = "0.4 0.8 0.4 1" }
				}, Layer);

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.1 0.58", AnchorMax = "0.9 0.63" },
					Text = { Text = "✓ VK успешно привязан", Font = "robotocondensed-bold.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "0.4 0.8 0.4 1" }
				}, Layer);

				container.Add(new CuiButton
				{
					RectTransform = { AnchorMin = "0.35 0.45", AnchorMax = "0.65 0.52" },
					Button = { Command = "tpnotifications.vk.unlink", Color = "0.8 0.3 0.3 0.8" },
					Text = { Text = "Отвязать VK", Font = "robotocondensed-bold.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
				}, Layer);
			}
			else
			{
				// VK не привязан
				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.1 0.7", AnchorMax = "0.9 0.78" },
					Text = { Text = "Привязка VK аккаунта", Font = "robotocondensed-bold.ttf", FontSize = 18, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
				}, Layer);

				container.Add(new CuiLabel
				{
					RectTransform = { AnchorMin = "0.1 0.62", AnchorMax = "0.9 0.68" },
					Text = { Text = "Привяжите VK для получения уведомлений в личные сообщения", Font = "robotocondensed-regular.ttf", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.8 0.8 0.8 1" }
				}, Layer);

				// Проверяем, есть ли ожидание подтверждения
				if (_pendingVerifications.ContainsKey(player.userID))
{
var pending = _pendingVerifications[player.userID];
if (DateTime.Now <= pending.ExpiresAt)
{
// Показываем форму ввода кода
container.Add(new CuiLabel
{
RectTransform = { AnchorMin = "0.1 0.58", AnchorMax = "0.9 0.64" },
Text = { Text = $"Код отправлен в VK (ID: {pending.VkId})", Font = "robotocondensed-regular.ttf", FontSize = 13, Align = TextAnchor.MiddleCenter, Color = "0.4 0.8 0.4 1" }
}, Layer);

int secondsLeft = (int)(pending.ExpiresAt - DateTime.Now).TotalSeconds;
container.Add(new CuiLabel
{
RectTransform = { AnchorMin = "0.1 0.53", AnchorMax = "0.9 0.57" },
Text = { Text = $"Осталось времени: {secondsLeft} сек", Font = "robotocondensed-regular.ttf", FontSize = 11, Align = TextAnchor.MiddleCenter, Color = "1 0.8 0.2 1" }
}, Layer);

container.Add(new CuiLabel
{
RectTransform = { AnchorMin = "0.2 0.48", AnchorMax = "0.8 0.52" },
Text = { Text = "Введите код из VK:", Font = "robotocondensed-regular.ttf", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
}, Layer);

// Панель для поля ввода
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = "0.35 0.40", AnchorMax = "0.65 0.46" },
Image = { Color = "0.2 0.2 0.2 0.9" }
}, Layer, $"{Layer}_codeinputpanel");

// Поле ввода кода
container.Add(new CuiElement
{
Parent = $"{Layer}_codeinputpanel",
Components =
{
new CuiInputFieldComponent
{
Align = TextAnchor.MiddleCenter,
CharsLimit = 6,
FontSize = 16,
Font = "robotocondensed-bold.ttf",
Color = "1 1 1 1",
Command = "tpnotifications.vk.confirm ",
NeedsKeyboard = true
},
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}
});

// Подсказка
container.Add(new CuiLabel
{
RectTransform = { AnchorMin = "0.2 0.34", AnchorMax = "0.8 0.38" },
Text = { Text = "Нажмите ENTER после ввода кода", Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "0.7 0.7 0.7 1" }
}, Layer);
}
}
else
{
// Форма для ввода VK ID
container.Add(new CuiLabel
{
RectTransform = { AnchorMin = "0.1 0.57", AnchorMax = "0.9 0.61" },
Text = { Text = "Введите ваш VK ID:", Font = "robotocondensed-regular.ttf", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.8 0.8 0.8 1" }
}, Layer);

// Панель для поля ввода VK ID
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = "0.30 0.49", AnchorMax = "0.70 0.55" },
Image = { Color = "0.2 0.2 0.2 0.9" }
}, Layer, $"{Layer}_vkidinputpanel");

// Поле ввода VK ID
container.Add(new CuiElement
{
Parent = $"{Layer}_vkidinputpanel",
Components =
{
new CuiInputFieldComponent
{
Align = TextAnchor.MiddleCenter,
CharsLimit = 15,
FontSize = 14,
Font = "robotocondensed-regular.ttf",
Color = "1 1 1 1",
Command = "tpnotifications.vk.setid ",
NeedsKeyboard = true
},
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}
});

// Кнопка "Получить код"
container.Add(new CuiButton
{
RectTransform = { AnchorMin = "0.35 0.40", AnchorMax = "0.65 0.47" },
Button = { Command = $"tpnotifications.vk.getcode", Color = "0.2 0.6 0.3 0.8" },
Text = { Text = "Получить код", Font = "robotocondensed-bold.ttf", FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
}, Layer);

container.Add(new CuiLabel
{
RectTransform = { AnchorMin = "0.1 0.33", AnchorMax = "0.9 0.38" },
Text = { Text = "Где найти VK ID: vk.com/id123456789 (цифры после id)", Font = "robotocondensed-regular.ttf", FontSize = 10, Align = TextAnchor.MiddleCenter, Color = "0.6 0.6 0.6 1" }
}, Layer);
}
				}
			}

			CuiHelper.AddUi(player, container);
		}

		void DestroyUI(BasePlayer player)
		{
			CuiHelper.DestroyUi(player, Layer);
		}

		[ConsoleCommand("tpnotifications.close")]
		void CmdClose(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;
			DestroyUI(player);
		}

		[ConsoleCommand("tpnotifications.tab")]
		void CmdTab(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			string tab = arg.GetString(0);
			if (tab == "history")
			{
				OpenNotificationsUI(player);
			}
			else if (tab == "settings")
			{
				OpenSettingsUI(player);
			}
			else if (tab == "vklink")
			{
				OpenVkLinkUI(player);
			}
		}

		[ConsoleCommand("tpnotifications.toggle")]
		void CmdToggle(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			var data = GetPlayerData(player.userID);
			if (data == null) return;

			string setting = arg.GetString(0);

			switch (setting)
			{
				case "рейды":
					data.Settings.Raid = !data.Settings.Raid;
					break;
				case "убийства":
					data.Settings.Kill = !data.Settings.Kill;
					break;
				case "награды":
					data.Settings.Reward = !data.Settings.Reward;
					break;
				case "сообщения_админов":
					data.Settings.AdminMessage = !data.Settings.AdminMessage;
					break;
				case "вайп":
					data.Settings.Wipe = !data.Settings.Wipe;
					break;
			}

			SaveData();
			OpenSettingsUI(player);
		}
		#endregion

		#region Chat Commands
		[ChatCommand("notifications")]
		void CmdNotifications(BasePlayer player, string command, string[] args)
		{
			OpenNotificationsUI(player);
		}

		[ChatCommand("notify")]
		void CmdNotify(BasePlayer player, string command, string[] args)
		{
			OpenNotificationsUI(player);
		}

		[ChatCommand("vklink")]
		void CmdVkLink(BasePlayer player, string command, string[] args)
		{
			if (args.Length == 0)
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Используйте: /vklink <VK ID>");
				player.ChatMessage($"<color=#FFC107>[Подсказка]</color> Найдите ваш VK ID: vk.com/id123456789 (цифры после id)");
				return;
			}

			string vkId = args[0];
			
			// Проверяем, что введены только цифры
			if (!vkId.All(char.IsDigit))
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> VK ID должен содержать только цифры!");
				return;
			}

			StartVkVerification(player, vkId);
		}

		[ChatCommand("vkcode")]
		void CmdVkCode(BasePlayer player, string command, string[] args)
		{
			if (args.Length == 0)
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Используйте: /vkcode <код>");
				return;
			}

			string code = args[0];
			
			if (ConfirmVkVerification(player, code))
			{
				// Обновляем UI если открыт
				OpenVkLinkUI(player);
			}
		}

		[ConsoleCommand("tpnotifications.vk.unlink")]
		void CmdVkUnlink(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			UnlinkVk(player);
			OpenVkLinkUI(player);
		}

		[ConsoleCommand("tpnotifications.vk.unlink.confirm")]
		void CmdVkUnlinkConfirm(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			UnlinkVk(player);
			OpenNotificationsUI(player);
		}

		[ConsoleCommand("tpnotifications.vk.setid")]
		void CmdVkSetId(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			string vkId = arg.GetString(0);
			if (!string.IsNullOrEmpty(vkId))
			{
				_tempVkIds[player.userID] = vkId;
			}
		}

		[ConsoleCommand("tpnotifications.vk.getcode")]
		void CmdVkGetCode(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			if (!_tempVkIds.ContainsKey(player.userID) || string.IsNullOrEmpty(_tempVkIds[player.userID]))
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Введите VK ID в поле выше!");
				return;
			}

			string vkId = _tempVkIds[player.userID];

			// Проверяем, что введены только цифры
			if (!vkId.All(char.IsDigit))
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> VK ID должен содержать только цифры!");
				return;
			}

			StartVkVerification(player, vkId);
			timer.Once(1f, () => OpenVkLinkUI(player));
		}

		[ConsoleCommand("tpnotifications.vk.confirm")]
		void CmdVkConfirm(ConsoleSystem.Arg arg)
		{
			var player = arg.Player();
			if (player == null) return;

			string code = arg.GetString(0);

			if (string.IsNullOrEmpty(code))
			{
				player.ChatMessage($"<color=#F44336>[Ошибка]</color> Введите код!");
				return;
			}

			if (ConfirmVkVerification(player, code))
			{
				timer.Once(0.5f, () => OpenVkLinkUI(player));
			}
		}
		#endregion
	}
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху