C#:
using System;
using System.Collections.Generic;
using UnityEngine.Networking;
using Facepunch.Utility;
using Oxide.Core.Libraries.Covalence;
using System.Collections;
using UnityEngine;
using Object = System.Object;
using System.Linq;
using System.Text.RegularExpressions;
using Oxide.Core.Plugins;
using Newtonsoft.Json.Linq;
using Oxide.Game.Rust.Cui;
using System.Text;
using Net = Network.Net;
using UnityEngine.UI;
using Newtonsoft.Json;
using ConVar;
using Time = UnityEngine.Time;
using Network;
using Oxide.Core.Libraries;
using Oxide.Core;
namespace Oxide.Plugins {
[Info("IQReportSystem", "Barry_Allenn", "2.9.6")]
[Description("One love IQReportSystem")]
internal class IQReportSystem : RustPlugin {
private class Response {
public List<String> last_ip;
public String last_nick;
public List<UInt64> another_accs;
public List<last_checks> last_check;
public class last_checks {
public UInt64 moderSteamID;
public String serverName;
public Int32 time;
}
public List<RustCCBans> bans;
public class RustCCBans {
public Int32 banID;
public String reason;
public String serverName;
public Int32 OVHserverID;
public Int32 banDate;
}
}
private void CheckStatusPlayer(BasePlayer player, String ReasonDisconnected = null) {
if (player == null) return;
if (!PlayerChecks.ContainsKey(player.userID)) return;
Boolean IsConsole = PlayerChecks[player.userID].ModeratorID == 0;
BasePlayer Moderator = BasePlayer.FindByID(PlayerChecks[player.userID].ModeratorID);
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifyStatusPlayerOrModerator;
if (Moderator == null && !IsConsole) {
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_DISCONNECTED", player.UserIDString), player);
Timer WaitModerator = timer.Once(600f, () => {
StopCheckedPlayer(player.userID, null, true);
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_DISCONNECTED_FULL_LEAVE", player.UserIDString), player);
}
);
if (!TimerWaitChecked.ContainsKey(player.userID)) TimerWaitChecked.Add(player.userID, WaitModerator);
else TimerWaitChecked[player.userID] = WaitModerator;
return;
}
if (ReasonDisconnected != null) {
if (config.CheckControllerSettings.StopCheckLeavePlayer) {
Timer WaitPlayer = timer.Once(900, () => {
StopCheckedPlayer(player.userID, Moderator, true);
}
);
if (!TimerWaitPlayer.ContainsKey(player.userID)) TimerWaitPlayer.Add(player.userID, WaitPlayer);
else TimerWaitPlayer[player.userID] = WaitPlayer;
}
if (IsConsole) {
Puts(LanguageEn ? $"The player's connection status has changed from server to : {ReasonDisconnected}" : $"У игрока изменился статус соединения с сервером на : {ReasonDisconnected}");
return;
}
DrawUI_Moderator_Checked_Menu_Status(Moderator, ReasonDisconnected);
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_PLAYER_ALERT_MODERATOR", Moderator.UserIDString, ReasonDisconnected), Moderator);
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_ChangeStatus(false, player.displayName, player.UserIDString, ReasonDisconnected);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_ChangeStatus(false, player.displayName, player.UserIDString, ReasonDisconnected));
StopDamageRemove(player);
return;
}
if (!player.IsConnected) return;
player.Invoke(() => {
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_PLAYER_ONLINE_ALERT_PLAYER", player.UserIDString), player);
DrawUI_Player_Alert(player);
if(config.CheckControllerSettings.UseDemo) player.StartDemoRecording();
if (IsConsole) {
Puts(LanguageEn ? "The player has connected to the server.Check continued" : "Игрок подключился к серверу.Проверка продолжена");
return;
}
if (Moderator == null) return;
DrawUI_Moderator_Checked_Menu_Status(Moderator, GetLang("TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_STATUS_DEFAULT", Moderator.UserIDString));
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_PLAYER_ONLINE_ALERT_MODERATOR", Moderator.UserIDString), Moderator);
StopDamageAdd(player);
}
, 3f);
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_ChangeStatus(false, player.displayName, player.UserIDString, "Online");
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_ChangeStatus(false, player.displayName, player.UserIDString, "Online"));
if (!TimerWaitPlayer.ContainsKey(player.userID)) return;
if (TimerWaitPlayer[player.userID].Destroyed) return;
TimerWaitPlayer[player.userID].Destroy();
TimerWaitPlayer.Remove(player.userID);
}
private List<String> GetServersBansOzProtect(UInt64 TargetID) {
if (String.IsNullOrWhiteSpace(config.ReferenceSettings.OzProtectSettings.OzProtectKey)) return null;
return !OzProtect_LocalRepository.ContainsKey(TargetID) ? new List<String>() : OzProtect_LocalRepository[TargetID].LastBansServers;
}
private void DrawUI_LeftMenu(BasePlayer player, Boolean IsModerator = false) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_LEFT_MENU");
if (Interface == null) return;
CuiHelper.DestroyUi(player, InterfaceBuilder.UI_REPORT_LEFT_PANEL);
CuiHelper.AddUi(player, Interface);
DrawUI_LeftMenu_Button(player, GetLang("TITLE_LEFT_MENU_BUTTON_REPORTS", player.UserIDString), ImageUi.GetImage(config.ImagesSettings.LeftBlockSettings.ReportIcon), IsModerator ? config.ColorsSettings.AdditionalColorElements : "0 0 0 0", "-70.333 -34", "55 0", IsModerator ? $"report.panel select.type.mod {true}" : "");
if (_.IsModerator(player)) DrawUI_LeftMenu_Button(player, GetLang("TITLE_LEFT_MENU_BUTTON_MODERATION", player.UserIDString), ImageUi.GetImage(config.ImagesSettings.LeftBlockSettings.ModerationIcon), IsModerator ? "0 0 0 0" : config.ColorsSettings.AdditionalColorElements, "-70.333 -71.267", "55 -37.267", IsModerator ? "" : $"report.panel select.type.mod {false}");
}
private void SoundPlay(BasePlayer player) {
SpeakerEntityMgr.SpeakerEntity speaker = SpeakerEntityMgr.Create(player);
speaker.SendEntitities();
String SoundName = lang.GetLanguage(player.UserIDString).Equals("ru") ? "ALERT_REPORT_RU" : "ALERT_REPORT_EN";
Coroutine routine = ServerMgr.Instance.StartCoroutine(SendSounds(player, SoundName, speaker));
if (!RoutineSounds.ContainsKey(player)) RoutineSounds.Add(player, routine);
else {
if (RoutineSounds[player] != null) ServerMgr.Instance.StopCoroutine(RoutineSounds[player]);
RoutineSounds[player] = routine;
}
timer.Once(15f, () => {
speaker.Kill();
if (RoutineSounds[player] != null) ServerMgr.Instance.StopCoroutine(RoutineSounds[player]);
}
);
}
private List<Fields> DT_PlayerMaxReport(String PlayerName, Int32 Reports, UInt64 TargetID) {
List<Fields> fields = new List<Fields> {
new Fields(LanguageEn ? "Information about the suspect :" : "Информация о подозреваемом :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{PlayerName}", true), new Fields("Steam64ID", $"[{TargetID}](https://steamcommunity.com/profiles/{TargetID})", true), new Fields(LanguageEn ? "Count reports" : "Количество репортов", $"{Reports}", true),
}
;
return fields;
}
private class PlayerInformation {
public Int32 Reports;
public Int32 SendReports;
public Int32 AmountChecked;
public String LastModerator;
public List<Configuration.LangText> ReasonHistory = new List<Configuration.LangText>();
}
private static InterfaceBuilder _interface;
private void DrawUI_TemplatePlayer_Moderator_IsSteam(BasePlayer player, String UserID) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_TEMPLATE_PLAYER_MODERATOR_ISSTEAM");
if (Interface == null) return;
Interface = Interface.Replace("%STATUS_PLAYER%", IsSteam(UserID) ? ImageUi.GetImage(config.ImagesSettings.ModeratorMenuCheckedSettings.SteamIcoPlayer) : ImageUi.GetImage(config.ImagesSettings.ModeratorMenuCheckedSettings.PirateIcoPlayer));
CuiHelper.AddUi(player, Interface);
}
private class SoundFileConverter : JsonConverter {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
JToken value = JToken.Load(reader);
return _.FromSaveData(Compression.Uncompress(Convert.FromBase64String(value.ToString())));
}
public override bool CanConvert(Type objectType) {
return typeof(List<Byte>) == objectType;
}
}
private void DrawUI_HeaderUI_Search(BasePlayer player, Boolean IsModerator = false) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_SEARCH_HEADER");
if (Interface == null) return;
Interface = Interface.Replace("%ISMODERATOR%", $"{IsModerator}");
Interface = Interface.Replace("%TITLE_PLAYER_HEADER_TITLE_SEARCH_PLAYER%", GetLang("TITLE_PLAYER_HEADER_TITLE_SEARCH_PLAYER", player.UserIDString));
CuiHelper.DestroyUi(player, "InputPanelSearch" + ".Input");
CuiHelper.AddUi(player, Interface);
}
private void StopDamageAdd(BasePlayer player) {
if (StopDamageMan == null) return;
if (!config.ReferenceSettings.StopDamageManSetting.UseStopDamage) return;
StopDamageMan.CallHook("AddPlayerSDM", player);
SendChat(GetLang("FUNCIONAL_PLAYER_STOP_DAMAGE_MAN_ADD", player.UserIDString), player);
}
public class SpeakerEntityMgr {
private static List<SpeakerEntity> _Entities = new List<SpeakerEntity>();
public static SpeakerEntity Create(BasePlayer listeners) {
var speaker = new SpeakerEntity();
speaker.SetListeners(listeners);
_Entities.Add(speaker);
return speaker;
}
public static void Shutdown() {
if (_Entities != null && _Entities.Count != 0) _Entities.ForEach(entity => _.NextTick(() => {
entity?.Kill();
}
));
}
public static void Kill(SpeakerEntity entity) {
_Entities.Remove(entity);
}
public class SpeakerEntity {
public UInt64 UID_SPEAKER = Network.Net.sv.TakeUID();
private UInt64 UID_CHAIR = Network.Net.sv.TakeUID();
public BasePlayer Listeners {
get;
private set;
}
public void SetListeners(BasePlayer listeners) {
Listeners = listeners;
}
public void SendEntitities() {
SendEntity(GetEntityChair);
SendEntity(GetEntitySpeaker);
}
private ProtoBuf.Entity GetEntitySpeaker(BasePlayer player) => new ProtoBuf.Entity() {
baseNetworkable = new ProtoBuf.BaseNetworkable() {
prefabID = player.prefabID, @group = BaseNetworkable.GlobalNetworkGroup.ID, uid = new NetworkableId(UID_SPEAKER),
}
, baseEntity = new ProtoBuf.BaseEntity() {
flags = 0, pos = new Vector3(0, 0, 0), rot = new Vector3(0, 0, 0), skinid = 0, time = Time.time,
}
, baseCombat = new ProtoBuf.BaseCombat() {
health = 10000, state = (Int32)BaseCombatEntity.LifeState.Alive
}
, basePlayer = new ProtoBuf.BasePlayer() {
health = 10000, modelState = new ModelState() {
mounted = true, onground = true, ducked = true, prone = true
}
, userid = UID_SPEAKER, name = "VOICE_P", playerFlags = (Int32)0, mounted = new NetworkableId(UID_CHAIR),
}
, parent = new ProtoBuf.ParentInfo() {
uid = new NetworkableId(UID_CHAIR), bone = 0
}
}
;
private ProtoBuf.Entity GetEntityChair(BasePlayer player) => new ProtoBuf.Entity() {
baseNetworkable = new ProtoBuf.BaseNetworkable() {
prefabID = 624857933, // static chair
@group = BaseNetworkable.GlobalNetworkGroup.ID, uid = new NetworkableId(UID_CHAIR),
}
, baseEntity = new ProtoBuf.BaseEntity() {
flags = 0, pos = new Vector3(0, 0.5f, -2.3f), rot = new Vector3(90, 180, 180), skinid = 0, time = Time.time,
}
, parent = new ProtoBuf.ParentInfo() {
uid = player.net.ID, bone = 2822582055 // head
}
}
;
public void Kill() {
DestroyEntity(UID_SPEAKER);
DestroyEntity(UID_CHAIR);
SpeakerEntityMgr.Kill(this);
}
private void SendEntity(Func<BasePlayer, ProtoBuf.Entity> entityGetter) {
NetWrite write = Network.Net.sv.StartWrite();
write.PacketID(Message.Type.Entities);
write.UInt32(++Listeners.net.connection.validate.entityUpdates);
entityGetter(Listeners)?.WriteToStream(write);
write.Send(new SendInfo(Listeners.net.connection));
}
private void DestroyEntity(UInt64 uid) {
NetWrite write = Network.Net.sv.StartWrite();
write.PacketID(Message.Type.EntityDestroy);
write.UInt64(uid);
write.Send(new SendInfo(Listeners.Connection) {
priority = Priority.Immediate
}
);
}
}
}
private void ChatCommandDiscord(BasePlayer player, String cmd, String[] args) {
String Discord = String.Join(" ", args);
SendPlayerDiscord(player, Discord);
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
if (config.NotifyVKSettings.VKTokenGroup == null) config.NotifyVKSettings.VKTokenGroup = "";
if (config.NotifyVKSettings.VKChatID == null) config.NotifyVKSettings.VKChatID = "";
}
catch {
PrintWarning(LanguageEn ? $"Error #58 reading configuration'oxide/config/{Name}', create a new configuration!" : $"Ошибка #58 чтения конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
/// <summary>
/// Обновление 2.0.x
/// Изменения :
/// - Изменил метод блокировки тиммейтов игрока
/// Исправления :
/// - Исправил неудачную отправку контактов в логировании ВК из-за тэга "#"
/// </summary>
private const Boolean LanguageEn = false;
private static IQReportSystem _;
private Dictionary<UInt64, LocalRepositoryRCC> RCC_LocalRepository = new Dictionary<UInt64, LocalRepositoryRCC>();
public Dictionary<BasePlayer, Coroutine> RoutineSounds = new Dictionary<BasePlayer, Coroutine>();
private void AlertModerator(BasePlayer Moderator, String PlayerName, Int32 ReportCount) {
if (!config.ReportContollerModerationSettings.AlertModerationSettings.AlertModerator) return;
SendChat(GetLang("NOTIFY_MODERATOR_MAX_REPORT", Moderator.UserIDString, PlayerName, ReportCount), Moderator);
RunEffect(Moderator);
}
public class Authors {
public String name {
get;
set;
}
public String url {
get;
set;
}
public String icon_url {
get;
set;
}
public String proxy_icon_url {
get;
set;
}
public Authors(String name, String url, String icon_url, String proxy_icon_url) {
this.name = name;
this.url = url;
this.icon_url = icon_url;
this.proxy_icon_url = proxy_icon_url;
}
}
private Authors GetAuthorDiscord(Configuration.NotifyDiscord.Webhooks.TemplatesNotify templatesNotify) => new Authors(templatesNotify.AuthorName, null, templatesNotify.IconURL, null);
void OnItemCraftCancelled(ItemCraftTask task, Item item, ItemCrafter ItemCrafter) {
BasePlayer player = ItemCrafter.owner;
if (player == null) return;
if (!PlayerChecks.ContainsKey(player.userID)) return;
if (config.CheckControllerSettings.TrackCrafting) {
BasePlayer Moderator = BasePlayer.FindByID(PlayerChecks[player.userID].ModeratorID);
if (Moderator != null) SendChat(GetLang("FUNCIONAL_MESSAGE_CHECK_AFK_PLAYER_CANCELLED_CRAFTING", Moderator.UserIDString), Moderator);
}
player.ResetInputIdleTime();
;
}
private Boolean IsFriendStartChecked(UInt64 userID, UInt64 targetID) => config.ReferenceSettings.FriendsSetting.StartCheckedFriend && IsFriends(userID, targetID);
private void CheckStatusModerator(BasePlayer Moderator, String ReasonDisconnected = null) {
if (Moderator == null) return;
KeyValuePair<UInt64, ProcessCheckRepository> ModeratorCheckeds = PlayerChecks.FirstOrDefault(m => m.Value.ModeratorID.Equals(Moderator.userID));
if (ModeratorCheckeds.Value == null) return;
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifyStatusPlayerOrModerator;
UInt64 TargetID = ModeratorCheckeds.Key;
BasePlayer Target = BasePlayer.FindByID(TargetID);
if (ReasonDisconnected != null) {
if (Target == null) {
StopCheckedPlayer(TargetID, Moderator);
return;
}
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_DISCONNECTED", Target.UserIDString), Target);
Timer WaitModerator = timer.Once(600f, () => {
StopCheckedPlayer(Target.userID, null, true);
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_DISCONNECTED_FULL_LEAVE", Target.UserIDString), Target);
}
);
if (!TimerWaitChecked.ContainsKey(Target.userID)) TimerWaitChecked.Add(Target.userID, WaitModerator);
else TimerWaitChecked[Target.userID] = WaitModerator;
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, ReasonDisconnected);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, ReasonDisconnected));
return;
}
if (!TimerWaitChecked.ContainsKey(TargetID)) return;
if (TimerWaitChecked[TargetID].Destroyed) return;
TimerWaitChecked[TargetID].Destroy();
TimerWaitChecked.Remove(TargetID);
DrawUI_Moderator_Checked_Menu(Moderator, TargetID);
String TargetStatus = GetLang("TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_STATUS_DEFAULT", Moderator.UserIDString);
if (Target == null || !Target.IsConnected) {
TargetStatus = "Disconnected";
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_PLAYER_ALERT_MODERATOR", Moderator.UserIDString, TargetStatus), Moderator);
}
DrawUI_Moderator_Checked_Menu_Status(Moderator, TargetStatus);
DrawUI_Moderator_Checked_Menu_Discord(Moderator, String.IsNullOrWhiteSpace(PlayerChecks[TargetID].DiscordTarget) ? GetLang("TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_DISCORD_EMPTY", Moderator.UserIDString) : PlayerChecks[TargetID].DiscordTarget);
if (Target != null) SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_RECONNECTED", Target.UserIDString), Target);
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, "Online");
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, "Online"));
}
private void StartCheckOzProtect(UInt64 TargetID, UInt64 ModerID) {
if (ModerID == 0) return;
if (String.IsNullOrWhiteSpace(config.ReferenceSettings.OzProtectSettings.OzProtectKey)) return;
String API = $"https://api.ozliginus.ru/methods/ozprotect.call?checking={ModerID}&suspect={TargetID}&ozprotectid={config.ReferenceSettings.OzProtectSettings.OzProtectKey}&minutes=30";
try {
webrequest.Enqueue(API, null, (code, response) => {
}
, this);
}
catch (Exception e) {
PrintError(LanguageEn ? "OzProtect : We were unable to get the player to check with OzProtect, please check if your key is up to date or if OzProtect is available" : "OzProtect : Мы не смогли вызвать игрока на проверку с помощью OzProtect, проверьте актуальность вашего ключа или доступность OzProtect");
}
}
public class FakePlayer {
public UInt64 UserID;
public String DisplayName;
}
private void DrawUI_Moderator_Checked_Menu_Status(BasePlayer moderator, String Status) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_ONLINE_STATUS_CHECKED_MODERATOR");
if (Interface == null) return;
Interface = Interface.Replace("%TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_STATUS%", GetLang("TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_STATUS", moderator.UserIDString, Status));
CuiHelper.DestroyUi(moderator, "InfoStatus");
CuiHelper.AddUi(moderator, Interface);
}
public class NpcSound {
[JsonConverter(typeof(SoundFileConverter))]
public List<byte[]> Data = new List<byte[]>();
}
private readonly Dictionary<UInt64, ProcessCheckRepository> PlayerChecks = new Dictionary<UInt64, ProcessCheckRepository>();
private const String HideMenuPermissions = "iqreportsystem.hidemenu";
private Boolean IsSteam(String id) {
if (MultiFighting == null) return true;
BasePlayer player = BasePlayer.Find(id);
if (player == null) return false;
Object obj = MultiFighting.CallHook("IsSteam", player.Connection);
if (obj is Boolean) return (Boolean)obj;
return false;
}
private void DrawUI_PoopUp_Moderator_InfoText(BasePlayer player, Int32 Y, String Text) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_POOPUP_MODERATOR_INFO_BLOCK_TEXT_TEMPLATE");
if (Interface == null) return;
Interface = Interface.Replace("%REASON_TITLE%", Text);
Interface = Interface.Replace("%OFFSET_MIN%", $"-51.667 {35.133 - (Y * 20)}");
Interface = Interface.Replace("%OFFSET_MAX%", $"51.667 {49.8 - (Y * 20)}");
CuiHelper.AddUi(player, Interface);
}
private static Configuration config = new Configuration();
private Boolean IsClansStartChecked(String userID, String targetID) => config.ReferenceSettings.ClansSetting.StartCheckedClan && IsClans(userID, targetID);
private Boolean IsFriendSendReport(UInt64 userID, UInt64 targetID) => config.ReferenceSettings.FriendsSetting.SendReportFriend && IsFriends(userID, targetID);
private void SendReportPlayer(BasePlayer Sender, UInt64 TargetID, Int32 ReasonIndex) {
CuiHelper.DestroyUi(Sender, "BLURED_POOP_UP");
CuiHelper.DestroyUi(Sender, InterfaceBuilder.UI_REPORT_POOPUP_PLAYER);
if (PlayerRepositories.ContainsKey(Sender.userID)) {
if (PlayerRepositories[Sender.userID].IsRepeatReported(TargetID)) {
SendChat(GetLang("FUNCIONAL_NO_DUPLE_SEND_REPORT", Sender.UserIDString), Sender);
return;
}
if (PlayerRepositories[Sender.userID].IsCooldown(TargetID)) {
SendChat(GetLang("FUNCIONAL_COOLDOWN_REPORT", Sender.UserIDString, PlayerRepositories[Sender.userID].GetCooldownLeft(TargetID)), Sender);
return;
}
}
PlayerInformations[Sender.userID].SendReports++;
PlayerInformations[TargetID].Reports++;
Configuration.ReasonReport Reason = config.ReasonList.Where(reasonReport => !reasonReport.HideUser).ToList()[ReasonIndex];
PlayerInformations[TargetID].ReasonHistory.Add(Reason.Title);
GetPlayerCheckServerRCC(TargetID);
GetPlayerCheckServerOzProtect(TargetID);
BasePlayer Target = BasePlayer.FindByID(TargetID);
if (Target != null) SendChat(GetLang("FUNCIONAL_SEND_REPORT_SUCCESS", Sender.UserIDString, Target.displayName), Sender);
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifySendReport;
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_PlayerSendReport(Sender, TargetID, LanguageEn ? Reason.Title.LanguageEN : Reason.Title.LanguageRU);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_PlayerSendReport(Sender, TargetID, LanguageEn ? Reason.Title.LanguageEN : Reason.Title.LanguageRU));
AddCooldown(Sender.userID, TargetID);
if (PlayerInformations[TargetID].Reports >= config.ReportContollerModerationSettings.ReportCountTrigger && Target != null) {
foreach (BasePlayer mList in BasePlayer.activePlayerList.Where(m => permission.UserHasPermission(m.UserIDString, ModeratorPermissions))) AlertModerator(mList, Target.displayName, PlayerInformations[TargetID].Reports);
AlertMaxReportDiscord(Target.displayName, PlayerInformations[TargetID].Reports, TargetID);
}
Interface.Call("OnSendedReport", Sender, TargetID, LanguageEn ? Reason.Title.LanguageEN : Reason.Title.LanguageRU);
}
public class OzResponse {
public int unixtime {
get;
set;
}
public string reason {
get;
set;
}
public string proofid {
get;
set;
}
public bool pirate {
get;
set;
}
public bool active {
get;
set;
}
public bool reliable {
get;
set;
}
public bool unnecessary {
get;
set;
}
public OzServer server {
get;
set;
}
public string admin {
get;
set;
}
public int game {
get;
set;
}
public string date {
get;
set;
}
public int bantime {
get;
set;
}
}
private void SendDiscord(String Webhook, List<Fields> fields, Authors Authors, Int32 Color) {
if (Webhook == null || String.IsNullOrWhiteSpace(Webhook)) return;
FancyMessage newMessage = new FancyMessage(null, false, new FancyMessage.Embeds[1] {
new FancyMessage.Embeds(null, Color, fields, Authors)
}
);
Request($"{Webhook}", newMessage.toJSON());
}
public Boolean HasImage(String imageName) => (Boolean)ImageLibrary?.Call("HasImage", imageName);
private void OnPlayerConnected(BasePlayer player) {
SteamAvatarAdd(player.UserIDString);
RegisteredPlayer(player);
CheckStatusPlayer(player);
if (IsModerator(player)) CheckStatusModerator(player);
}
private const String ModeratorPermissions = "iqreportsystem.moderation";
internal class LocalRepositoryRCC {
public List<String> LastChecksServers = new List<String>();
public List<String> LastBansServers = new List<String>();
}
private String VKT_PlayerMaxReport(String PlayerName, Int32 Reports, UInt64 TargetID) {
String Message = LanguageEn ? $"▣ EXCESS OF COMPLAINTS ▣\nInformation about the suspect:\n• Nickname: {PlayerName}\n• Steam64ID : {TargetID} (https://steamcommunity.com/profiles/{TargetID})\nNumber of reports: {Reports}" : $"▣ ПРЕВЫШЕНИЕ КОЛИЧЕСТВА ЖАЛОБ ▣\nИнформация об подозреваемом :\n• Ник : {PlayerName}\n• Steam64ID : {TargetID} (https://steamcommunity.com/profiles/{TargetID})\nКоличество репортов : {Reports}";
return Message;
}
public void StartSysncFakeActive() {
if (!IQFakeActive) return;
IQFakeActive?.Call("SyncReserved");
}
private class ProcessCheckRepository {
public String DiscordTarget;
public String DisplayName;
public UInt64 ModeratorID;
}
private List<Fields> DT_PlayerSendReport(BasePlayer Sender, UInt64 TargetID, String Reason) {
List<Fields> fields = new List<Fields> {
new Fields(LanguageEn ? "New complaint received :" : "Получена новая жалоба :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Information about the sender :" : "Информация об отправителе :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{Sender.displayName}", true), new Fields("Steam64ID", $"[{Sender.userID}](https://steamcommunity.com/profiles/{Sender.userID})", true), new Fields("", "", false), new Fields(LanguageEn ? "Information about the suspect :" : "Информация о подозреваемом :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{covalence.Players.FindPlayerById(TargetID.ToString()).Name ?? "EMPTY"}", true), new Fields("Steam64ID", $"[{TargetID}](https://steamcommunity.com/profiles/{TargetID})", true), new Fields(LanguageEn ? "Reason for complaint :" : "Причина жалобы :", Reason, false),
}
;
return fields;
}
private void AddCooldown(UInt64 SenderID, UInt64 TargetID) {
if (config.ReportSendControllerSettings.CooldownReport == 0 && !config.ReportSendControllerSettings.NoRepeatReport) return;
if (!PlayerRepositories.ContainsKey(SenderID)) {
PlayerRepositories.Add(SenderID, new PlayerRepository {
ReportedList = new Dictionary<UInt64, Double>(), Cooldown = 0
}
);
}
PlayerRepositories[SenderID].AddCooldown(TargetID);
}
private Dictionary<UInt64, PlayerInformation> PlayerInformations = new Dictionary<UInt64, PlayerInformation>();
private void SendRaitingModerator(UInt64 ModeratorID, Int32 IndexAchive, Int32 StarAmount) {
if (!ModeratorInformations.ContainsKey(ModeratorID)) return;
ModeratorInformation ModeratorInfo = ModeratorInformations[ModeratorID];
List<Int32> ListScore = IndexAchive == 1 ? ModeratorInfo.OneScore : IndexAchive == 2 ? ModeratorInfo.TwoScore : IndexAchive == 3 ? ModeratorInfo.ThreeScore : null;
ListScore?.Add(StarAmount);
Interface.Call("OnSendedFeedbackChecked", ModeratorID, IndexAchive, StarAmount);
}
private void DrawUI_PlayerPanel(BasePlayer player, Int32 Page = 0, Boolean IsModerator = false, String SearchName = "") {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_PANEL_PLAYERS");
if (Interface == null) return;
Interface = Interface.Replace("%TITLE_PLAYER_LIST%", GetLang("TITLE_PLAYER_LIST", player.UserIDString));
CuiHelper.DestroyUi(player, InterfaceBuilder.UI_REPORT_PLAYER_PANEL);
CuiHelper.AddUi(player, Interface);
DrawUI_PageController(player, Page, IsModerator, SearchName);
}
private List<Fields> DT_StopCheck(UInt64 TargetID, BasePlayer Moderator, Boolean AutoStop = false, Boolean IsConsole = false, Configuration.ReasonReport Verdict = null) {
String ModeratorName = !IsConsole && Moderator != null ? Moderator.displayName : "Console";
String ModeratorID = !IsConsole && Moderator != null ? Moderator.UserIDString : "Console";
List<Fields> fields;
if (AutoStop) {
fields = new List<Fields> {
new Fields(LanguageEn ? "Player verification is completed automatically :" : "Проверка игрока завершена автоматически :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Suspect Information:" : "Информация о подозреваемом :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{PlayerChecks[TargetID].DisplayName}", true), new Fields("SteamID", $"{TargetID}", true), new Fields("Результат", LanguageEn ? "The player's reports are not reset" : "Репорты игрока не сброшены", false),
}
;
}
else {
fields = new List<Fields> {
new Fields(LanguageEn ? "Player check completed :" : "Завершена проверка игрока :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Moderator Information :" : "Информация о модераторе :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{ModeratorName}", true), new Fields("Steam64ID", $"[{ModeratorID}](https://steamcommunity.com/profiles/{ModeratorID})", true), new Fields("", "", false), new Fields(LanguageEn ? "Suspect Information:" : "Информация о подозреваемом :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{PlayerChecks[TargetID].DisplayName}", true), new Fields("SteamID", $"{TargetID}", true), new Fields("Результат", $"{(Verdict == null ? (LanguageEn ? "No violations found" : "Нарушений не выявлено") : LanguageEn ? Verdict.Title.LanguageEN : Verdict.Title.LanguageRU)}", false),
}
;
}
return fields;
}
protected override void SaveConfig() => Config.WriteObject(config);
private void DrawUI_ModeratorStitistics_Banner(BasePlayer Moderator, String OffsetMin, String OffsetMax, String TitleBanner, String ArgBanner, String AdditionalText = "", Int32 CountRaiting = -1) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_PROFILE_BANNER_TEMPLATE");
if (Interface == null) return;
Interface = Interface.Replace("%OFFSET_MIN%", OffsetMin);
Interface = Interface.Replace("%OFFSET_MAX%", OffsetMax);
Interface = Interface.Replace("%TITLE_BANNER%", TitleBanner);
Interface = Interface.Replace("%ARGS_BANNER%", ArgBanner);
CuiHelper.AddUi(Moderator, Interface);
if (!String.IsNullOrWhiteSpace(AdditionalText)) {
DrawUI_ModeratorStitistics_Banner_AdditionalText(Moderator, AdditionalText);
return;
}
if (CountRaiting < 0) return;
for (Int32 Raiting = 0; Raiting < CountRaiting; Raiting++) DrawUI_ModeratorStitistics_Banner_RaitingImage(Moderator, Raiting);
}
private void StopCheckedPlayer(UInt64 TargetID, BasePlayer Moderator, Boolean AutoStop = false, Boolean IsConsole = false) {
if (!PlayerChecks.ContainsKey(TargetID)) return;
BasePlayer Target = BasePlayer.FindByID(TargetID);
if (Target != null) {
if(config.CheckControllerSettings.UseDemo) Target.StopDemoRecording();
if (!AutoStop) DrawUI_Raiting_Menu_Player(Target, PlayerChecks[TargetID].ModeratorID);
CuiHelper.DestroyUi(Target, InterfaceBuilder.UI_REPORT_PLAYER_ALERT);
StopDamageRemove(Target);
if (AfkCheckRoutine.ContainsKey(Target)) {
if (AfkCheckRoutine[Target] != null) {
ServerMgr.Instance.StopCoroutine(AfkCheckRoutine[Target]);
AfkCheckRoutine[Target] = null;
}
AfkCheckRoutine.Remove(Target);
}
}
if (!IsConsole) {
if (Moderator != null) {
CuiHelper.DestroyUi(Moderator, InterfaceBuilder.UI_REPORT_MODERATOR_MENU_CHECKED);
ModeratorInformations[Moderator.userID].AmountChecked++;
PlayerInformations[TargetID].LastModerator = Moderator.displayName;
}
}
else Puts(LanguageEn ? "Player checked completed" : "Проверка игрока завершена");
if (!AutoStop) {
if (config.NotifyChatSettings.UseNotifyStopCheck) {
if (Moderator != null || !IsConsole) {
foreach (BasePlayer player in BasePlayer.activePlayerList) SendChat(GetLang("NOTIFY_PLAYERS_STOP_CHECK_MODERATOR", player.UserIDString, Moderator.displayName, PlayerChecks[TargetID].DisplayName), player);
}
else {
foreach (BasePlayer player in BasePlayer.activePlayerList) SendChat(GetLang("NOTIFY_PLAYERS_STOP_CHECK_NOT_MODERATOR", player.UserIDString, PlayerChecks[TargetID].DisplayName), player);
}
}
PlayerInformations[TargetID].AmountChecked++;
PlayerInformations[TargetID].Reports = 0;
}
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifyStopCheck;
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_StopCheck(TargetID, Moderator, AutoStop, IsConsole);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_StopCheck(TargetID, Moderator, AutoStop, IsConsole));
if (PlayerChecks.ContainsKey(TargetID)) PlayerChecks.Remove(TargetID);
Interface.Call("OnStoppedChecked", Target, Moderator, AutoStop, IsConsole);
}
private void DrawUI_Raiting_Menu_Player(BasePlayer player, UInt64 ModeratorID) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_RAITING_MENU_PLAYER");
if (Interface == null) return;
IPlayer iModerator = covalence.Players.FindPlayerById(ModeratorID.ToString());
String ModeratorName = iModerator == null ? GetLang("TITLE_RAITING_WORK_MODERATOR_WHO_MODERATOR_NOT_NAME", player.UserIDString) : iModerator.Name;
Interface = Interface.Replace("%TITLE_CLOSE_BUTTON_REPORT%", GetLang("TITLE_CLOSE_BUTTON_REPORT", player.UserIDString));
Interface = Interface.Replace("%TITLE_RAITING_WORK_MODERATOR_TITLE%", GetLang("TITLE_RAITING_WORK_MODERATOR_TITLE", player.UserIDString));
Interface = Interface.Replace("%TITLE_RAITING_WORK_MODERATOR_WHO_MODERATOR%", GetLang("TITLE_RAITING_WORK_MODERATOR_WHO_MODERATOR", player.UserIDString, ModeratorName.ToUpper()));
Interface = Interface.Replace("%COMMAND_CLOSE%", $"report.panel close.select.raiting {ModeratorID}");
CuiHelper.AddUi(player, Interface);
DrawUI_Raiting_Menu_Stars(player, -1, ModeratorID);
}
private class ImageUi {
private static Coroutine coroutineImg = null;
private static Dictionary<String, String> Images = new Dictionary<String, String>();
private static List<String> KeyImages = new List<String>();
public static void DownloadImages() {
coroutineImg = ServerMgr.Instance.StartCoroutine(AddImage());
}
private static IEnumerator AddImage() {
if (_ == null) yield break;
_.PrintWarning("Генерируем интерфейс, ожидайте ~10-15 секунд!");
foreach (String URL in KeyImages) {
String KeyName = URL;
if (KeyName == null) throw new ArgumentNullException(nameof(KeyName));
UnityWebRequest www = UnityWebRequestTexture.GetTexture(URL);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError) {
_.PrintWarning($"Image download error! Error: {www.error}, Image name: {KeyName}");
www.Dispose();
coroutineImg = null;
yield break;
}
Texture2D texture = DownloadHandlerTexture.GetContent(www);
if (texture != null) {
Byte[] bytes = texture.EncodeToPNG();
String image = FileStorage.server.Store(bytes, FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
if (!Images.ContainsKey(KeyName)) Images.Add(KeyName, image);
else Images[KeyName] = image;
UnityEngine.Object.DestroyImmediate(texture);
}
www.Dispose();
yield return CoroutineEx.waitForSeconds(0.02f);
}
yield return CoroutineEx.waitForSeconds(0.02f);
coroutineImg = null;
_interface = new InterfaceBuilder();
_.PrintWarning("Интерфейс успешно загружен!");
}
public static string GetImage(String ImgKey) {
if (Images.ContainsKey(ImgKey)) return Images[ImgKey];
return _.GetImage("LOADING");
}
public static void Initialize() {
KeyImages = new List<String>();
Images = new Dictionary<string, string>();
Configuration.Images ImagesPlugin = config.ImagesSettings;
if (!KeyImages.Contains(ImagesPlugin.Background)) KeyImages.Add(ImagesPlugin.Background);
if (!KeyImages.Contains(ImagesPlugin.PageDown)) KeyImages.Add(ImagesPlugin.PageDown);
if (!KeyImages.Contains(ImagesPlugin.PageUp)) KeyImages.Add(ImagesPlugin.PageUp);
if (!KeyImages.Contains(ImagesPlugin.Search)) KeyImages.Add(ImagesPlugin.Search);
if (!KeyImages.Contains(ImagesPlugin.AvatarBlur)) KeyImages.Add(ImagesPlugin.AvatarBlur);
if (!KeyImages.Contains(ImagesPlugin.ReasonModeratorAndRaiting)) KeyImages.Add(ImagesPlugin.ReasonModeratorAndRaiting);
if (!KeyImages.Contains(ImagesPlugin.PlayerAlerts)) KeyImages.Add(ImagesPlugin.PlayerAlerts);
if (!KeyImages.Contains(ImagesPlugin.StatisticsBlockSettings.BlockStatsModeration)) KeyImages.Add(ImagesPlugin.StatisticsBlockSettings.BlockStatsModeration);
if (!KeyImages.Contains(ImagesPlugin.StatisticsBlockSettings.BlockStatsRaitingModeration)) KeyImages.Add(ImagesPlugin.StatisticsBlockSettings.BlockStatsRaitingModeration);
if (!KeyImages.Contains(ImagesPlugin.StatisticsBlockSettings.RaitingImage)) KeyImages.Add(ImagesPlugin.StatisticsBlockSettings.RaitingImage);
if (!KeyImages.Contains(ImagesPlugin.PlayerListBlockSettings.PoopUpBackgorund)) KeyImages.Add(ImagesPlugin.PlayerListBlockSettings.PoopUpBackgorund);
if (!KeyImages.Contains(ImagesPlugin.PlayerListBlockSettings.PoopUpReasonBackgorund)) KeyImages.Add(ImagesPlugin.PlayerListBlockSettings.PoopUpReasonBackgorund);
if (!KeyImages.Contains(ImagesPlugin.LeftBlockSettings.ButtonBackgorund)) KeyImages.Add(ImagesPlugin.LeftBlockSettings.ButtonBackgorund);
if (!KeyImages.Contains(ImagesPlugin.LeftBlockSettings.ModerationIcon)) KeyImages.Add(ImagesPlugin.LeftBlockSettings.ModerationIcon);
if (!KeyImages.Contains(ImagesPlugin.LeftBlockSettings.ReportIcon)) KeyImages.Add(ImagesPlugin.LeftBlockSettings.ReportIcon);
if (!KeyImages.Contains(ImagesPlugin.ModerationBlockSettings.ModeratorPoopUPBackg
// ... [Code preview truncated due to length. Full source in attached file] ...