C#:
using System;
using System.Globalization;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using System.Linq;
using Oxide.Core;
using CompanionServer;
namespace Oxide.Plugins {
[Info("DReportSystem", "TopPlugin.ru", "1.0.19")]
public class DReportSystem : RustPlugin {
#region Variables
[PluginReference]
private Plugin ImageLibrary;
private static DReportSystem _ins;
public Dictionary<ulong, player> Players = new Dictionary<ulong, player>();
public Dictionary<ulong, ulong> Check = new Dictionary<ulong, ulong>();
string Layer = "DReportSystem.Main";
string Layer2 = "DReportSystem.Notify";
string Layer3 = "DReportSystem.PlayerInfo";
bool debug = false;
#endregion
#region Lang
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
{
"Repeated Report", "Вы уже отправляли репорт на этого игрока!"
}
, {
"New Report", "Поступила новая жалоба на игрока!\nНик игрока отправившего жалобу: {0}, его SteamID: {1}\nПодозреваемый: {2}, его SteamID: {3}\n\nЗаголовок жалобы: {4}, текст жалобы: {5}"
}
, {
"Report Command", "Чтобы отправить жалобу на игрока нажмите клавишу F7"
}
, {
"No Access", "У вас нет доступа к этой команде"
}
, {
"Player Not Found", "Игрок не найден.Возможно он вышел"
}
, {
"Player On Check", "Игрок уже находится на проверке!"
}
, {
"You On Check", "Вы находитесь на проверке игрока! Чтобы начать новую, завершите текущую"
}
, {
"Player Check Notify", "<size=16>ВНИМАНИЕ!</size>\nВы подозреваетесь в использовании постороннего ПО\nПредоставьте свой Discord модератору командой /discord, у вас есть 5 минут"
}
, {
"Moderator Check Notify", "<size=16>ВНИМАНИЕ!</size>\nВы находитесь на проверке игрока\nОжидайте пока игрок предоставит свой Discord и приступайте к работе\nЧтобы завершить проверку пропишите /check и следуйте дальнейшим инструкциям, если игрока требуется забанить - используйте /ban после этого"
}
, {
"Send Discord Help", "Чтобы отправить свой Discord модератору, используйте: /discord\nОбязательно следуйте инструкции, иначе модератор не увидит ваш дискорд!"
}
, {
"Send Discord Error", "Вы не правильно ввели свой Discord.Следуйте инструкциям по команде /discord"
}
, {
"Moderator Leave", "Модератор который вас проверял вышел.Проверка завершена автоматически без вынесения вердикта"
}
, {
"Player Send Discord", "ВНИМАНИЕ! Игрок, которого вы проверяете отправил вам свой Discord: {0}"
}
, {
"Discord Double", "Discord игрока так же продублирован вам в консоль (F1)"
}
, {
"Verdict Help", "Чтобы заврешить проверку игрока введите /check cancel \"Вердикт\", обязательно используйте кавычки!"
}
, {
"Verdict Error", "Вы не правильно вынесли вердикт.Следуйте инструкциям по команде /check"
}
, {
"Success Vedict", "Вы успешно завершили проверку и вынесли вердикт\nНе забудьте забанить игрока, если он оказался нарушителем :)"
}
,
}
, this);
}
private static string GetMsg(string key, string userId = null) => _ins.lang.GetMessage(key, _ins, userId);
#endregion
#region Data
private void SaveData() {
Interface.Oxide.DataFileSystem.WriteObject($"{Title}/Players", Players);
}
private void LoadData() {
try {
Players = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, player>>($"{Title}/Players");
}
catch (Exception e) {
PrintError(e.ToString());
}
if (Players == null) Players = new Dictionary<ulong, player>();
}
#endregion
#region Config
public class report {
[JsonProperty("Никнейм")]
public string name;
[JsonProperty("SteamID")]
public ulong steamid;
[JsonProperty("Заголовок")]
public string subject;
[JsonProperty("Сообщение")]
public string message;
}
public class player {
[JsonProperty("Никнейм")]
public string name;
[JsonProperty("Количество репортов")]
public int reportscount;
[JsonProperty("Список репортов на игрока")]
public Dictionary<ulong, List<report>> Reports = new Dictionary<ulong, List<report>>();
}
private PluginConfig cfg;
public class PluginConfig {
[JsonProperty("Настройки плагина")]
public PSettings pluginsettings = new PSettings();
[JsonProperty("Настройки интерфейса")]
public PInterface plugininterface = new PInterface();
[JsonProperty("Настройки доступа")]
public Settings access = new Settings();
[JsonProperty("Настройки оповещений")]
public AlertSettings alerts = new AlertSettings();
public class PSettings {
[JsonProperty("Включить оповещение при вводе команды /report?")]
public bool alert = true;
}
public class PInterface {
[JsonProperty("Сортировать игроков? (если true, то вначале списка будут игроки отсортированные по убыванию количества репортов)")]
public bool sortplayers = false;
[JsonProperty("Английский интерфейс плагина")]
public bool english = false;
}
public class Settings {
[JsonProperty("Пермишн для доступа к команде /reports (должен начинатся с dreportsystem.)")]
public string perm = "dreportsystem.moderator";
[JsonProperty("Пермишн для доступа к очистке репортов игрока (должен начинатся с dreportsystem.)")]
public string clearperm = "dreportsystem.clear";
}
public class AlertSettings {
[JsonProperty("[Chat] Включить оповещения о новых репортах модераторам в чат ?")]
public bool chatalert = true;
[JsonProperty("[Rust+] Включить оповещения о новых репортах модераторам через Rust+ ?")]
public bool rustplusalert = true;
[JsonProperty("[VK] Включить оповещения о новых репортах модераторам в беседу VK (не будет работать если хостинг машина находится в Украине) ?")]
public bool vkalert = true;
[JsonProperty("[VK] Токен приложения ВК (лучше использовать отдельную страницу для получения токена)")]
public string token = "Если не собираетесь использовать оповещения в беседу VK, не изменяйте это значение";
[JsonProperty("[VK] ID чата ВК")]
public string chatid = "Если не собираетесь использовать оповещения в беседу VK, не изменяйте это значение";
[JsonProperty("[Discord] Использовать оповещения о новых репортах в отдельный канал Discord ?")]
public bool discordalert = true;
[JsonProperty("[Discord] Webhook (см.инструкцию по настройке оповещений Discord)")]
public string webhook = "Если не собираетесь использовать оповещения в канал Discord, не изменяйте это значение";
[JsonProperty("[Discord] Webhook для логов действий модераторов")]
public string logwebhook = "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение";
}
}
protected override void LoadDefaultConfig() {
Config.WriteObject(new PluginConfig(), true);
}
#endregion
#region Hooks
private void Init() {
cfg = Config.ReadObject<PluginConfig>();
Config.WriteObject(cfg);
}
void OnServerInitialized() {
_ins = this;
if (!plugins.Exists("ImageLibrary")) {
PrintError("ImageLibrary not found.Install it and reload plugin!");
return;
}
Request.Init();
LoadData();
ImageLibrary.Call("AddImage", "https://i.imgur.com/n0OUC31.png", "closeicon");
ImageLibrary.Call("AddImage", "https://i.imgur.com/XSTJVnB.png", "backicon");
if (!permission.PermissionExists(cfg.access.perm)) permission.RegisterPermission(cfg.access.perm, this);
if (!permission.PermissionExists(cfg.access.clearperm)) permission.RegisterPermission(cfg.access.clearperm, this);
if (BasePlayer.activePlayerList.Count > 0) foreach (var player in BasePlayer.activePlayerList) OnPlayerConnected(player);
}
void Unload() {
SaveData();
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, Layer);
CuiHelper.DestroyUi(player, Layer2);
CuiHelper.DestroyUi(player, Layer3);
}
Check.Clear();
Request.Dispose();
_ins = null;
}
void OnServerSave() {
SaveData();
}
private void OnPlayerConnected(BasePlayer player) {
if (player.IsReceivingSnapshot) {
NextTick(() => OnPlayerConnected(player));
return;
}
if (player == null) return;
if (!Players.ContainsKey(player.userID)) {
Players.Add(player.userID, new player {
name = player.displayName, reportscount = 0
}
);
}
if (Players.ContainsKey(player.userID) && Players[player.userID].name != player.displayName) Players[player.userID].name = player.displayName;
}
private void OnPlayerReported(BasePlayer player, string targetName, string targetId, string subject, string message, string type) {
if (player == null) return;
var suspect = BasePlayer.FindByID(ulong.Parse(targetId));
if (suspect == null || player == null || player.IsNpc || suspect.IsNpc) return;
SendReport(player, suspect, subject, message);
}
#endregion
#region Methods
#region API
[HookMethod("API_SendReport")]
public void API_SendReport(BasePlayer player, BasePlayer suspect, string subject, string message) {
if (player == null || suspect == null || subject == null || message == null) return;
SendReport(player, suspect, subject, message);
}
#endregion
#region RustPlus
void RustPlusAlert(ulong userid, string reportplayername, string suspectname, ulong reportplayerid, ulong suspectid, string subject, string message) {
if (!cfg.plugininterface.english) NotificationList.SendNotificationTo(userid, NotificationChannel.SmartAlarm, "ReportSystem", $"Игрок {reportplayername}/{reportplayerid} отправил жалобу на игрока {suspectname}/{suspectid}.Заголовок жалобы: {subject}, текст жалобы: {message}", new Dictionary<string, string>());
else NotificationList.SendNotificationTo(userid, NotificationChannel.SmartAlarm, "ReportSystem", $"Player {reportplayername}/{reportplayerid} sent a report to the player {suspectname}/{suspectid}.Report subject: {subject}, report message: {message}", new Dictionary<string, string>());
}
#endregion
#region VK
private void SendVKChatMessage(string message) {
var apiver = "v=5.92";
var randomid = UnityEngine.Random.Range(Int32.MinValue, Int32.MaxValue);
webrequest.Enqueue("https://api.vk.com/method/messages.send?chat_id=" + cfg.alerts.chatid + "&message=" + URLEncode(message) + "&"+apiver+ "&random_id=" + randomid +"&access_token=" + cfg.alerts.token, null, (code, response) => GetCallback(code, response, "Сообщение в беседу"), this);
}
private string URLEncode(string input) {
if (input.Contains("#")) input = input.Replace("#", "%23");
if (input.Contains("$")) input = input.Replace("$", "%24");
if (input.Contains("+")) input = input.Replace("+", "%2B");
if (input.Contains("/")) input = input.Replace("/", "%2F");
if (input.Contains(":")) input = input.Replace(":", "%3A");
if (input.Contains(";")) input = input.Replace(";", "%3B");
if (input.Contains("?")) input = input.Replace("?", "%3F");
if (input.Contains("@")) input = input.Replace("@", "%40");
return input;
}
void GetCallback(int code, string response, string type, BasePlayer player = null) {
if (!response.Contains("error")) {
Puts($"{type} отправлен(о): {response}");
if (type == "Код подтверждения" && player != null) return;
}
else {
if (type == "Код подтверждения") {
if (response.Contains("Can't send messages for users without permission") && player != null) return;
else PrintWarning("errorconfcode", $"Ошибка отправки кода подтверждения.Ответ сервера ВК: {response}");
}
else {
PrintWarning("Errors", $"{type} не отправлен(о).Ошибка: " + response);
}
}
}
#endregion
#region Discord
public readonly JsonSerializerSettings jsonSettings = new JsonSerializerSettings();
private readonly Dictionary<string, string> _headers = new Dictionary<string, string> {
["Content-Type"]
= "application/json"
}
;
private class Request {
private static bool _rateLimited;
private static bool _busy;
private static Queue<Request> _requestQueue;
private readonly string _payload;
private readonly Plugin _plugin;
private readonly Action<BaseResponse> _response;
private readonly string _url;
public static void Init() {
_requestQueue = new Queue<Request>();
}
private Request(string url, FancyMessage message, Action<BaseResponse> response = null, Plugin plugin = null ) {
_url = url;
_payload = message.ToJson();
_response = response;
_plugin = plugin;
}
private Request(string url, FancyMessage message, Plugin plugin = null ) {
_url = url;
_payload = message.ToJson();
_plugin = plugin;
}
private static void SendNextRequest() {
if (_requestQueue.Count == 0 ) {
return;
}
Request request = _requestQueue.Dequeue();
request.Send();
}
private static void EnqueueRequest(Request request ) {
_requestQueue.Enqueue(request );
}
private void Send() {
if (_busy ) {
EnqueueRequest(this );
return;
}
_busy = true;
_ins.webrequest.Enqueue(_url, _payload, (code, rawResponse ) => {
var response = new BaseResponse {
Message = rawResponse, Code = code
}
;
if (response.IsRatelimit ) {
RateLimitResponse rateLimit = response.GetRateLimit();
if (rateLimit != null ) {
EnqueueRequest(this );
OnRateLimit(rateLimit.RetryAfter );
}
}
else if (response.IsBad ) {
_ins.PrintWarning("Failed! Discord responded with code: {0}.Plugin: {1}\n{2}", code, _plugin != null ? _plugin.Name : "Unknown Plugin", response.Message );
}
else {
try {
_response?.Invoke(response );
}
catch (Exception ex ) {
Interface.Oxide.LogException("[DReportSystem] Request callback raised an exception!", ex );
}
}
_busy = false;
SendNextRequest();
}
, _ins, Core.Libraries.RequestMethod.POST, _ins._headers );
}
private static void OnRateLimit(int retryAfter ) {
if (_rateLimited ) {
return;
}
_rateLimited = true;
_ins.timer.In(retryAfter / 1000, OnRateLimitEnd );
}
private static void OnRateLimitEnd() {
_rateLimited = false;
SendNextRequest();
}
public static void Send(string url, FancyMessage message, Plugin plugin = null ) {
new Request(url, message, plugin ).Send();
}
public static void Send(string url, FancyMessage message, Action<BaseResponse> callback, Plugin plugin = null ) {
new Request(url, message, callback, plugin ).Send();
}
public static void Dispose() {
_requestQueue = null;
_rateLimited = false;
_busy = false;
}
}
public class FancyMessage {
[JsonProperty("content" )]
private string Content {
get;
set;
}
[JsonProperty("tts" )]
private bool TextToSpeech {
get;
set;
}
[JsonProperty("embeds" )]
private EmbedBuilder[] Embeds {
get;
set;
}
public FancyMessage WithContent(string value ) {
Content = value;
return this;
}
public FancyMessage AsTTS(bool value ) {
TextToSpeech = value;
return this;
}
public FancyMessage SetEmbed(EmbedBuilder value ) {
Embeds = new[] {
value
}
;
return this;
}
public string GetContent() {
return Content;
}
public bool IsTTS() {
return TextToSpeech;
}
public EmbedBuilder GetEmbed() {
return Embeds[0];
}
public string ToJson() {
return JsonConvert.SerializeObject(this, _ins.jsonSettings );
}
}
public class EmbedBuilder {
public EmbedBuilder() {
Fields = new List<Field>();
}
[JsonProperty("title" )]
private string Title {
get;
set;
}
[JsonProperty("color" )]
private int Color {
get;
set;
}
[JsonProperty("fields" )]
private List<Field> Fields {
get;
}
[JsonProperty("description" )]
private string Description {
get;
set;
}
public EmbedBuilder WithTitle(string title ) {
Title = title;
return this;
}
public EmbedBuilder WithDescription(string description ) {
Description = description;
return this;
}
public EmbedBuilder SetColor(int color ) {
Color = color;
return this;
}
public EmbedBuilder SetColor(string color ) {
Color = ParseColor(color );
return this;
}
public EmbedBuilder AddInlineField(string name, object value ) {
Fields.Add(new Field(name, value, true ) );
return this;
}
public EmbedBuilder AddField(string name, object value ) {
Fields.Add(new Field(name, value, false ) );
return this;
}
public EmbedBuilder AddField(Field field ) {
Fields.Add(field );
return this;
}
public EmbedBuilder AddFields(Field[] fields ) {
for (var i = 0; i < fields.Length; i++ ) {
Fields.Add(fields[i] );
}
return this;
}
public int GetColor() {
return Color;
}
public string GetTitle() {
return Title;
}
public Field[] GetFields() {
return Fields.ToArray();
}
private int ParseColor(string input ) {
int color;
if (!int.TryParse(input, out color ) ) {
color = 3329330;
}
return color;
}
public class Field {
[JsonProperty("inline" )]
public bool Inline;
[JsonProperty("name" )]
public string Name;
[JsonProperty("value" )]
public object Value;
public Field(string name, object value, bool inline ) {
Name = name;
Value = value;
Inline = inline;
}
public Field() {
}
}
}
private abstract class Response {
public int Code {
get;
set;
}
public string Message {
get;
set;
}
}
private class BaseResponse : Response {
public bool IsRatelimit => Code == 429;
public bool IsOk => (Code == 200 ) | (Code == 204 );
public bool IsBad => !IsRatelimit && !IsOk;
public RateLimitResponse GetRateLimit() {
return Message.Length == 0 ? null : JsonConvert.DeserializeObject<RateLimitResponse>(Message );
}
}
private class RateLimitResponse : BaseResponse {
[JsonProperty("retry_after" )]
public int RetryAfter {
get;
set;
}
}
void DiscordMessage(string message) {
if (cfg.alerts.webhook == "Если не собираетесь использовать оповещения в канал Discord, не изменяйте это значение") return;
//DiscordMessages?.Call("API_SendTextMessage", cfg.alerts.webhook, message);
Request.Send(cfg.alerts.webhook, new FancyMessage().AsTTS(false).WithContent(message), null);
}
void DiscordLog(string message) {
if (cfg.alerts.logwebhook == "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") return;
//DiscordMessages?.Call("API_SendTextMessage", cfg.alerts.logwebhook, message);
Request.Send(cfg.alerts.logwebhook, new FancyMessage().AsTTS(false).WithContent(message), null);
}
#endregion
void Log(string text) {
LogToFile("Checks", text, this, true);
}
void SendReport(BasePlayer player, BasePlayer suspect, string subject, string message) {
if (debug) PrintError($"API works! {player.displayName} reported {player.displayName} for {subject}, {message}");
if (player == null || suspect == null || player.IsNpc || suspect.IsNpc || player == suspect) return;
if (!Players.ContainsKey(suspect.userID) || !Players.ContainsKey(player.userID)) return;
if (Players[suspect.userID].Reports.ContainsKey(player.userID)) {
player.ChatMessage(GetMsg("Repeated Report"));
return;
}
Players[suspect.userID].reportscount++;
List<report> value;
var List = Players[suspect.userID].Reports.TryGetValue(player.userID, out value);
if (List == false) {
Players[suspect.userID].Reports.Add(player.userID, new List<report> {
new report {
name = player.displayName, steamid = player.userID, subject = subject, message = message
}
}
);
}
else {
Players[suspect.userID].Reports[player.userID].Add(new report {
name = player.displayName, steamid = player.userID, subject = subject, message = message
}
);
}
if (!cfg.plugininterface.english) Log($"Игрок {player.displayName}/{player.userID} отправил жалобу на игрока: {suspect.displayName}/{suspect.userID}.Заголовок жалобы: {subject}, текст: {message}");
else Log($"Player {player.displayName}/{player.userID} filed a complaint against player: {suspect.displayName}/{suspect.userID}.Complaint title: {subject}, text: {message}");
foreach (var players in BasePlayer.activePlayerList.Where(x => permission.UserHasPermission(x.UserIDString, cfg.access.perm))) {
if (cfg.alerts.rustplusalert) RustPlusAlert(players.userID, player.displayName, suspect.displayName, player.userID, suspect.userID, subject, message);
if (cfg.alerts.chatalert) players.ChatMessage(GetMsg("New Report").Replace("{0}", $"{player.displayName}").Replace("{1}", $"{player.userID}").Replace("{2}", $"{suspect.displayName}").Replace("{3}", $"{suspect.userID}").Replace("{4}", $"{subject}").Replace("{5}", $"{message}"));
}
if (cfg.alerts.vkalert && cfg.alerts.token != "Если не собираетесь использовать оповещения в беседу VK, не изменяйте это значение" && cfg.alerts.chatid != "Если не собираетесь использовать оповещения в беседу VK, не изменяйте это значение") SendVKChatMessage(GetMsg("New Report").Replace("{0}", $"{player.displayName}").Replace("{1}", $"{player.userID}").Replace("{2}", $"{suspect.displayName}").Replace("{3}", $"{suspect.userID}").Replace("{4}", $"{subject}").Replace("{5}", $"{message}"));
if (cfg.alerts.discordalert) DiscordMessage(GetMsg("New Report").Replace("{0}", $"``{player.displayName}``").Replace("{1}", $"``{player.userID}``").Replace("{2}", $"``{suspect.displayName}``").Replace("{3}", $"``{suspect.userID}``").Replace("{4}", $"``{subject}``").Replace("{5}", $"``{message}``"));
}
bool IsOnline(ulong id) {
var suspect = BasePlayer.FindByID(id);
if (suspect != null) return true;
else return false;
}
void DeletePlayerFromDict(ulong id, string name) {
if (!Players.ContainsKey(id)) return;
Players.Remove(id);
Players.Add(id, new player {
name = name, reportscount = 0
}
);
}
void AlarmCheckSuspect(BasePlayer suspect) {
if (suspect == null) return;
if (!Check.ContainsKey(suspect.userID)) return;
DrawNotify(suspect, GetMsg("Player Check Notify"));
}
void AlarmCheckModerator(BasePlayer moderator) {
if (moderator == null) return;
if (!Check.ContainsValue(moderator.userID)) return;
DrawNotify(moderator, GetMsg("Moderator Check Notify"));
}
void CancelCheck(BasePlayer suspect) {
Check.Remove(suspect.userID);
DeletePlayerFromDict(suspect.userID, suspect.displayName);
CuiHelper.DestroyUi(suspect, Layer2);
}
string CheckText(int chars, string text) {
if (text.Length >= chars) return text.Substring(0, chars - 2) + "..";
return text;
}
#endregion
#region Commands
[ChatCommand("check")]
private void CheckCommand(BasePlayer player, string command, string[] args) {
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, cfg.access.perm)) return;
if (!Check.ContainsValue(player.userID)) return;
if (args.Length < 1) {
player.ChatMessage(GetMsg("Verdict Help"));
return;
}
if (args.Length > 2) {
player.ChatMessage(GetMsg("Verdict Error"));
return;
}
if (args[0] == "cancel") {
if (args.Length < 2) {
player.ChatMessage(GetMsg("Verdict Error"));
return;
}
player.ChatMessage(GetMsg("Success Vedict"));
if (!cfg.plugininterface.english) Log($"{player.displayName}/{player.userID} закончил проверку игрока и вынес свой вердикт: {args[1]}");
else Log($"{player.displayName}/{player.userID} finished checking the player and delivered his verdict: {args[1]}");
if (!cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") DiscordLog($"``{player.displayName}/{player.userID}`` закончил проверку игрока и вынес свой вердикт: ``{args[1]}``");
if (cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") DiscordLog($"``{player.displayName}/{player.userID}`` finished checking the player and delivered his verdict: ``{args[1]}``");
foreach (var item in Check.ToArray()) {
if (item.Value == player.userID) {
var suspect = BasePlayer.FindByID(item.Key);
if (suspect == null) {
Check.Remove(suspect.userID);
return;
}
CancelCheck(suspect);
}
}
CuiHelper.DestroyUi(player, Layer2);
}
}
[ChatCommand("discord")]
private void SendDiscordCommand(BasePlayer player, string command, string[] args) {
if (player == null) return;
if (!Check.ContainsKey(player.userID)) return;
if (args.Length < 1) {
player.ChatMessage(GetMsg("Send Discord Help"));
return;
}
if (args.Length > 1) {
player.ChatMessage(GetMsg("Send Discord Error"));
return;
}
var moderator = BasePlayer.FindByID(Check[player.userID]);
if (moderator == null) {
player.ChatMessage(GetMsg("Moderator Leave"));
CancelCheck(player);
return;
}
moderator.ChatMessage(GetMsg("Player Send Discord").Replace("{0}", args[0].Replace("\"", string.Empty)) + "\n" + GetMsg("Discord Double"));
moderator.SendConsoleCommand($"echo {GetMsg("Player Send Discord").Replace(" {
0
}
", args[0].Replace("\"", string.Empty))
}
");
if (!cfg.plugininterface.english) Log($" {
player.displayName
}
/ {
player.userID
}
отправил свой Discord модератору {
moderator.displayName
}
/ {
moderator.userID
}
");
else Log($" {
player.displayName
}
/ {
player.userID
}
sent Discord to a moderator {
moderator.displayName
}
/ {
moderator.userID
}
");
if (!cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение")
DiscordLog($"`` {
player.displayName
}
/ {
player.userID
}
`` отправил свой Discord модератору `` {
moderator.displayName
}
/ {
moderator.userID
}
``");
if (cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение")
DiscordLog($"`` {
player.displayName
}
/ {
player.userID
}
`` sent Discord to a moderator `` {
moderator.displayName
}
/ {
moderator.userID
}
``");
}
[ChatCommand("report")]
private void ReportCommand(BasePlayer player)
{
if (player == null) return;
if (cfg.pluginsettings.alert) player.ChatMessage(GetMsg("Report Command"));
}
[ChatCommand("reports")]
private void ReportsCommand(BasePlayer player)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, cfg.access.perm))
{
player.ChatMessage(GetMsg("No Access"));
return;
}
DrawUI(player, 0);
}
[ConsoleCommand("drspage")]
private void ChangePage(ConsoleSystem.Arg args)
{
BasePlayer player = args.Player();
if (player != null && args.HasArgs(1))
{
var page = int.Parse(args.Args[0]);
if (page * 8 <= Players.Count)
{
DrawUI(player, page);
}
}
}
[ConsoleCommand("drstest")]
private void DRSTEST(ConsoleSystem.Arg args)
{
DiscordLog("``Test/76561111111`` отправил свой Discord модератору ``Test/76561111111``");
}
[ConsoleCommand("drspages")]
private void ChangePages(ConsoleSystem.Arg args)
{
BasePlayer player = args.Player();
if (player != null && args.HasArgs(2))
{
var page = int.Parse(args.Args[1]);
var steamid = ulong.Parse(args.Args[0]);
if (page * 8 <= Players[steamid].reportscount)
{
DrawPlayerInfo(player, steamid, page);
}
}
}
[ConsoleCommand("drsclear")]
private void DeletePlayer(ConsoleSystem.Arg args)
{
BasePlayer player = args.Player();
if (player == null || !permission.UserHasPermission(player.UserIDString, cfg.access.perm) || !args.HasArgs(2)) return;
var id = ulong.Parse(args.Args[1]);
var name = args.Args[0].Replace("\"", string.Empty);
DeletePlayerFromDict(id, name);
CuiHelper.DestroyUi(player, Layer);
DrawUI(player, 0);
if (!cfg.plugininterface.english) Log($"{player.displayName}/{player.userID} очистил количество репортов игроку {name}/{id}");
else Log($"{player.displayName}/{player.userID} cleared the number of reports to the player {name}/{id}");
if (!cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") DiscordLog($"``{player.displayName}/{player.userID}`` очистил количество репортов игроку ``{name}/{id}``");
if (cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") DiscordLog($"``{player.displayName}/{player.userID}`` cleared the number of reports to the player ``{name}/{id}``");
}
[ConsoleCommand("drscheck")]
private void CheckPlayer(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
if (player == null || !permission.UserHasPermission(player.UserIDString, cfg.access.perm) || !args.HasArgs(1)) return;
var id = ulong.Parse(args.Args[0]);
if (id == player.userID) return;
var suspect = BasePlayer.FindByID(id);
if (suspect == null) {
player.ChatMessage(GetMsg("Player Not Found"));
return;
}
if (Check.ContainsValue(player.userID)) {
player.ChatMessage(GetMsg("You On Check"));
return;
}
if (Check.ContainsKey(suspect.userID)) {
player.ChatMessage(GetMsg("Player On Check"));
return;
}
Check.Add(suspect.userID, player.userID);
AlarmCheckSuspect(suspect);
AlarmCheckModerator(player);
if (!cfg.plugininterface.english) Log($"{player.displayName}/{player.userID} начал проверку игрока {suspect.displayName}/{suspect.userID}");
else Log($"{player.displayName}/{player.userID} started checking the player {suspect.displayName}/{suspect.userID}");
if (!cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") DiscordLog($"``{player.displayName}/{player.userID}`` начал проверку игрока ``{suspect.displayName}/{suspect.userID}``");
if (cfg.plugininterface.english && cfg.alerts.discordalert && cfg.alerts.logwebhook != "Если не собираетесь использовать логи в канал Discord, не изменяйте это значение") DiscordLog($"``{player.displayName}/{player.userID}`` started checking the player ``{suspect.displayName}/{suspect.userID}``");
}
[ConsoleCommand("drsbackui")]
private void UIBack(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
if (player == null || !permission.UserHasPermission(player.UserIDString, cfg.access.perm)) return;
DrawUI(player, 0);
}
[ConsoleCommand("drsplayerinfo")]
private void OpenPlayerInfo(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
if (player == null || !permission.UserHasPermission(player.UserIDString, cfg.access.perm) || !args.HasArgs(1)) return;
DrawPlayerInfo(player, ulong.Parse(args.Args[0]), 0);
}
#endregion
#region UI
private void DrawUI(BasePlayer player, int page) {
if (cfg.plugininterface.sortplayers) Players = Players.OrderByDescending(pair => pair.Value.reportscount).ToDictionary(pair => pair.Key, pair => pair.Value);
CuiHelper.DestroyUi(player, Layer);
var container = new CuiElementContainer();
container.Add(new CuiPanel {
Image = {
Color = "0 0 0 1", Material = "assets/content/ui/uibackgroundblur-notice.mat"
}
, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, CursorEnabled = true,
}
, "Overlay", Layer);
container.Add(new CuiElement {
Parent = Layer, Components = {
new CuiImageComponent {
Color = HexToRustFormat("#181B18DB"), Material = ""
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1",
}
}
}
);
container.Add(new CuiElement {
Parent = Layer, Name = Layer + ".MainContainer", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#9C95956D")
}
, new CuiRectTransformComponent {
AnchorMin = "0.265625 0.08888885", AnchorMax = "0.734375 0.8222222"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".MainContainer", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#9C95952E"), Material = "assets/content/ui/uibackgroundblur.mat"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".MainContainer", Name = Layer + ".Top", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#484848AD")
}
, new CuiRectTransformComponent {
AnchorMin = "0 0.8787879", AnchorMax = "1 1",
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".MainContainer", Name = Layer + ".Bottom", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#484848AD")
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "0.999 0.1212172",
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Top", Components = {
new CuiTextComponent {
Color = HexToRustFormat("#DDDDDDFF"), Text = cfg.plugininterface.english ? "ALL REPORTS" : "ВСЕ ЖАЛОБЫ", Align = TextAnchor.UpperLeft, FontSize = 18, Font = "RobotoCondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0.05333334 0.1979178", AnchorMax = "0.3711112 0.7187503"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Top", Components = {
new CuiTextComponent {
Color = HexToRustFormat("#9A9A9AFF"), Text = cfg.plugininterface.english ? "WHO WILL WE CHECK TODAY? • CLICK ON THE PLAYER'S AVATAR TO SEE THE LIST OF REPORTS" : "КОГО БУДЕМ ПРОВЕРЯТЬ СЕГОДНЯ? • НАЖМИТЕ НА АВАТАР ИГРОКА ЧТОБЫ УВИДЕТЬ СПИСОК ЖАЛОБ", Align = TextAnchor.UpperLeft, FontSize = 12, Font = "RobotoCondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0.05444445 0.1979178", AnchorMax = "0.9988889 0.4270831"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom", Name = Layer + ".Bottom" + ".CloseButton", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#FF0000B8")
}
, new CuiRectTransformComponent {
AnchorMin = "0.8188888 0.4374651", AnchorMax = "0.9466667 0.6978856",
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom" + ".CloseButton", Components = {
new CuiRawImageComponent {
Color = "1 1 1 0.6", Png = (string) ImageLibrary.CallHook("GetImage", "closeicon")
}
, new CuiRectTransformComponent {
AnchorMin = "0.02608692 0.08000004", AnchorMax = "0.2086954 0.9200005"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom" + ".CloseButton", Components = {
new CuiTextComponent {
Color = HexToRustFormat("#DDDDDDFF"), Text = cfg.plugininterface.english ? "CLOSE" : "ЗАКРЫТЬ", Align = TextAnchor.MiddleCenter, FontSize = 11, Font = "RobotoCondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0.1217395 0.08000004", AnchorMax = "1 0.8799995"
}
}
}
);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Button = {
Close = Layer, Color = "0 0 0 0"
}
, Text = {
Text = ""
}
}
, Layer + ".Bottom" + ".CloseButton");
container.Add(new CuiElement {
Parent = Layer + ".Bottom", Name = Layer + ".Bottom" + ".Pages", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#FFFFFF32")
}
, new CuiRectTransformComponent {
AnchorMin = "0.03777974 0.3958336", AnchorMax = "0.1933326 0.7395837",
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom" + ".Pages", Components = {
new CuiTextComponent {
Color = HexToRustFormat("#DDDDDDFF"), Text = $"{page + 1}/{(int)Math.Ceiling(Convert.ToDecimal(Players.Count) / 8)}", Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "RobotoCondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom" + ".Pages", Name = Layer + ".Bottom" + ".Pages" + ".Left", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#74FF008A")
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "0.2357184 0.9696969",
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom" + ".Pages" + ".Left", Components = {
new CuiTextComponent {
Color = HexToRustFormat("#DDDDDDFF"), Text = "<", Align = TextAnchor.MiddleCenter, FontSize = 14, Font = "RobotoCondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
}
);
container.Add(new CuiElement {
Parent = Layer + ".Bottom" + ".Pages", Name = Layer + ".Bottom" + ".Pages" + ".Right", Components = {
new CuiImageComponent {
Color = HexToRustFormat("#74FF
// ... [Code preview truncated due to length. Full source in attached file] ...