C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Rust;
namespace Oxide.Plugins {
[Info("ReportSystem", "Chibubrik", "1.0.0")]
class ReportSystem : RustPlugin {
#region Вар
private string Layer = "Report_UI";
private string LayerNote = "NOTE_UI";
private string LayerCheck = "CHECK_UI";
private string LayerDeath = "DEATH_UI";
#endregion
#region Класс
private Dictionary<ulong, PlayersSettings> playersSettings;
public class PlayersSettings {
[JsonProperty("Ник игрока")]
public string DisplayName;
[JsonProperty("Кол-во жалоб")]
public int Count;
[JsonProperty("Сколько раз игрок проверялся")]
public int Amount;
[JsonProperty("Откат")]
public double Time;
}
public class Settings {
[JsonProperty("Разрешение для использования команды (check)")]
public string Perm;
[JsonProperty("Включить логирование жалоб?")]
public bool LogFile;
[JsonProperty("Кол-во жалоб для вызова на проверку")]
public int Count;
[JsonProperty("Кулдаун на отправку жалобы(в секундах)")]
public int Time;
[JsonProperty("Время всплывающего уведомления(в секундах)")]
public int NoteTime;
}
public class SettingsVK {
[JsonProperty("Включить использование вконтакте?")]
public bool UseVK;
[JsonProperty("ID Беседы вконтакте")]
public string VKId;
[JsonProperty("Token Группы вконтакте")]
public string VKTokens;
}
#endregion
#region Конфиг
public Configuration config;
public class Configuration {
[JsonProperty("Настройки")]
public Settings settings = new Settings();
[JsonProperty("Настройки вконтакте")]
public SettingsVK SettingsVk = new SettingsVK();
[JsonProperty("Список жалоб")]
public Dictionary<string, string> Reasons;
public static Configuration GetNewCong() {
return new Configuration {
settings = new Settings() {
Perm = "ReportSystem.use", LogFile = false, Count = 3, Time = 60, NoteTime = 10
}
, SettingsVk = new SettingsVK() {
UseVK = false, VKId = "1", VKTokens = "TokenGroupVK"
}
, Reasons = new Dictionary<string, string>() {
["Reason_1"]
= "2+", ["Reason_2"] = "МАКРОСЫ", ["Reason_3"] = "ЧИТЫ", ["Reason_4"] = "БАГОЮЗ"
}
}
;
}
}
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config?.Reasons == null) LoadDefaultConfig();
}
catch {
PrintWarning($"Ошибка чтения конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
protected override void LoadDefaultConfig() => config = Configuration.GetNewCong();
protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Команды
[ChatCommand("report")]
private void CommandReport(BasePlayer player) {
var currentTime = GetCurrentTime();
if (playersSettings[player.userID].Time > currentTime) {
SendReply(player, $"Подождите <color=#8fde5b>{TimeExtensions.FormatTime(TimeSpan.FromSeconds(playersSettings[player.userID].Time - currentTime))}</color> до следующей жалобы!");
}
if (playersSettings[player.userID].Time < currentTime) {
ReportUI(player);
}
}
[ConsoleCommand("check")]
private void CommandCheck(ConsoleSystem.Arg args) {
var player = args.Player();
if (!permission.UserHasPermission(player.UserIDString, config.settings.Perm)) {
player.ConsoleMessage("У вас нет доступа к данной команде!");
return;
}
if (args.Args == null || args.Args.Length == 0 || args.Args.Length < 2) {
player.ConsoleMessage($"Используйте: check add/remove SteamID");
return;
}
BasePlayer target = BasePlayer.FindByID(ulong.Parse(args.Args[1]));
if (player != null && args.HasArgs(1)) {
if (args.Args[0] == "add") {
CheckUI(target);
playersSettings[player.userID].Amount += 1;
}
if (args.Args[0] == "remove") {
CuiHelper.DestroyUi(target, LayerCheck);
if (playersSettings[player.userID].Count >= config.settings.Count) {
playersSettings[player.userID].Count -= playersSettings[player.userID].Count;
}
}
}
}
[ConsoleCommand("discord_skype")]
private void CommandDiscordSkype(ConsoleSystem.Arg args) {
var player = args.Player();
if (!args.HasArgs(1)) {
SendReply(player, "Вы ничего не ввели");
}
if (player != null && args.HasArgs(1)) {
SendReply(player, "Ваше сообщение отправленно!");
MessageVK($"Игрок {player.displayName}\nПредоставил данные на проверку: {args.Args[0]}");
}
}
[ConsoleCommand("report")]
private void PlayerReport(ConsoleSystem.Arg args, HitInfo info) {
var player = args.Player();
if (args.Args.Length == 0) {
ReportUI(player);
return;
}
if (player != null && args.HasArgs(1)) {
if (args.Args[0] == "players") {
ReportUI(player, args.Args[1]);
return;
}
if (args.Args[0] == "skip") {
ReportUI(player, "", "", int.Parse(args.Args[1]));
}
if (args.Args[0] == "death") {
if (!args.HasArgs(2)) {
Puts("Вы ничего не ввели");
return;
}
var name = args.Args[1];
if (name != null) {
Puts($"Игрок {player.displayName} отправил жалобу на игрока {args.Args[1]}\nПричина: Жалобы при респавне");
MessageVK($"Игрок {player.displayName} отправил жалобу на игрока {args.Args[1]}\nПричина: Жалобы при респавне");
Sucess(player);
}
}
if (args.Args[0].Length != 17) {
for (int i = 0; i < 32; i++) {
CuiHelper.DestroyUi(player, $"Buttons.{i}");
}
for (int t = 0; t < 32; t++) {
CuiHelper.DestroyUi(player, $"Players.{t}");
}
CuiHelper.DestroyUi(player, "button");
ReportUI(player, args.Args[0]);
return;
}
if (args.Args.Length >= 2) {
BasePlayer target = BasePlayer.Find(args.Args[0]);
if (player != target) {
playersSettings[player.userID].Count += 1;
string text = playersSettings[player.userID].Count > config.settings.Count ? "Игрок превысил количество репортов" : $"{playersSettings[player.userID].Count}";
if (config.settings.LogFile) {
LogToFile("ReportSystem", $"Игрок {player.displayName} отправил жалобу на игрока {target.displayName}\nПричина: {args.Args[1]}\nКоличество жалоб: {text}\nПроверялся: {playersSettings[player.userID].Amount} раз(а)\nSteamID: {target.userID}\nСтим профиль: https://steamcommunity.com/profiles/{target.userID}/\n", this);
return;
}
Puts($"Игрок {player.displayName} отправил жалобу на игрока {target.displayName}.Причина: {args.Args[1]}");
MessageVK($"Игрок {player.displayName}, отправил жалобу на игрока {target.displayName}\nПричина: {args.Args[1]}\nКоличество жалоб: {text}\nПроверялся: {playersSettings[player.userID].Amount} раз(а)\nSteamID: {target.userID}\nСтим профиль: https://steamcommunity.com/profiles/{target.userID}/");
playersSettings[player.userID].Time = GetCurrentTime() + config.settings.Time;
CuiHelper.DestroyUi(player, Layer);
NoteUI(player);
}
else {
SendReply(player, $"Вы жалуйтесь сами на себя");
}
}
}
}
[ConsoleCommand("clear.report")]
private void DataClear(ConsoleSystem.Arg args) {
var player = args.Player();
if (player != null && !player.IsAdmin) return;
playersSettings.Clear();
player.ConsoleMessage($"Вы успешно очистили дату {Name}");
player.SendConsoleCommand("o.reload ReportSystem");
}
#endregion
#region Хуки
private void OnServerInitialized() {
if (Interface.Oxide.DataFileSystem.ExistsDatafile("ReportSystem/PlayerList")) {
playersSettings = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, PlayersSettings>>("ReportSystem/PlayerList");
}
else {
playersSettings = new Dictionary<ulong, PlayersSettings>();
}
foreach (var check in BasePlayer.activePlayerList) OnPlayerConnected(check);
permission.RegisterPermission(config.settings.Perm, this);
}
private void OnPlayerConnected(BasePlayer player) {
if (!playersSettings.ContainsKey(player.userID)) {
playersSettings.Add(player.userID, new PlayersSettings {
DisplayName = player.displayName, Count = 0, Amount = 0, Time = 0
}
);
}
SaveData();
}
private void SaveData() {
Interface.Oxide.DataFileSystem.WriteObject("ReportSystem/PlayerList", playersSettings);
}
private void OnPlayerDisconnected(BasePlayer player, string reason) {
SaveData();
}
private void Unload() {
SaveData();
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, Layer);
CuiHelper.DestroyUi(player, LayerNote);
CuiHelper.DestroyUi(player, LayerCheck);
CuiHelper.DestroyUi(player, LayerDeath);
}
}
private void OnPlayerDie(BasePlayer player, HitInfo info) {
if (info.damageTypes.GetMajorityDamageType() == DamageType.Suicide || info.damageTypes.GetMajorityDamageType() == DamageType.Generic || !(info?.Initiator is BasePlayer) || player.GetComponent<NPCPlayer>() != null || info.InitiatorPlayer.GetComponent<NPCPlayer>() != null) return;
DeathUI(player);
}
private void OnPlayerRespawn(BasePlayer player) => CuiHelper.DestroyUi(player, LayerDeath);
private void OnPlayerRespawned(BasePlayer player) => CuiHelper.DestroyUi(player, LayerDeath);
#endregion
#region Интерфейс
#region Табличка проверки
private void CheckUI(BasePlayer player) {
CuiElementContainer container = new CuiElementContainer();
CuiHelper.DestroyUi(player, LayerCheck);
container.Add(new CuiPanel {
CursorEnabled = true, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-640 180", OffsetMax = "640 280"
}
, Image = {
Color = "0 0 0 0"
}
,
}
, "Overlay", LayerCheck);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0"
}
, Text = {
Text = $"<size=20><b>{player.displayName.ToUpper()}, ВАС ВЫЗВАЛИ НА ПРОВЕРКУ</b></size>\nПредоставте свой дискорд или скайп\nПоле для ввода информации ниже!\n\n", Color = HexToUiColor("#FFFFFF9A"), Align = TextAnchor.MiddleCenter, FontSize = 14, Font = "robotocondensed-regular.ttf"
}
}
, LayerCheck);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.43 0.05", AnchorMax = "0.57 0.3", OffsetMax = "0 0"
}
, Button = {
Color = "1 1 1 0.15"
}
, Text = {
Text = $"Ваш дискорд или скайп", Color = HexToUiColor("#FFFFFF2A"), Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-regular.ttf"
}
}
, LayerCheck, "Checks");
container.Add(new CuiElement {
Parent = "Checks", Components = {
new CuiInputFieldComponent {
Command = "discord_skype ", Text = "Ваш дискорд или скайп", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, FontSize = 20, Font = "robotocondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
}
);
CuiHelper.AddUi(player, container);
}
#endregion
#region Уведомление
private void NoteUI(BasePlayer player) {
CuiElementContainer container = new CuiElementContainer();
CuiHelper.DestroyUi(player, LayerNote);
container.Add(new CuiPanel {
CursorEnabled = false, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-400 180", OffsetMax = "400 280"
}
, Image = {
Color = "0 0 0 0"
}
,
}
, "Hud", LayerNote);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0"
}
, Text = {
Text = $"<size=20><b>{player.displayName.ToUpper()}, ВАША ЖАЛОБА ОТПРАВЛЕНА</b></size>\nОчень скоро мы найдем эту скотину, и забьем до смерти\nНадейтесь, что на вас жалоба не придет!", Color = HexToUiColor("#FFFFFF9A"), Align = TextAnchor.MiddleCenter, FontSize = 14, Font = "robotocondensed-regular.ttf"
}
}
, LayerNote);
CuiHelper.AddUi(player, container);
timer.Once(config.settings.NoteTime, () => {
CuiHelper.DestroyUi(player, LayerNote);
}
);
}
#endregion
#region Основной интерфейс
private void ReportUI(BasePlayer player, string target = "", string reason = "", int page = 0) {
CuiElementContainer container = new CuiElementContainer();
if (target == "" && reason == "") {
CuiHelper.DestroyUi(player, Layer);
container.Add(new CuiPanel {
CursorEnabled = true, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Image = {
Color = "0 0 0 0"
}
,
}
, "Overlay", Layer);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "-2 -2", AnchorMax = "2 2", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0.9", Close = Layer
}
, Text = {
Text = ""
}
}
, Layer);
#region Скип
if (page != 0) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.165 0.45", AnchorMax = "0.223 0.55", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Command = $"report skip {page - 1}"
}
, Text = {
Text = $"<", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", FontSize = 62
}
}
, Layer);
}
if ((float)BasePlayer.activePlayerList.Where(p => p.displayName.ToLower().Contains(target.ToLower())).Count() > (page + 1) * 32) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.777 0.45", AnchorMax = "0.835 0.55", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Command = $"report skip {page + 1}"
}
, Text = {
Text = $">", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", FontSize = 62
}
}
, Layer);
}
#endregion
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.226 0.215", AnchorMax = "0.774 0.785", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0"
}
, Text = {
Text = ""
}
}
, Layer, "Report");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 0.1", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0"
}
, Text = {
Text = $"ВЫБЕРИТЕ ИГРОКА НА КОТОРОГО ХОТИТЕ ПОЖАЛОВАТЬСЯ", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 20
}
}
, "Report", "Text");
#region Поиск ника
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0.89", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "1 1 1 0.1"
}
, Text = {
Text = "РУЧНОЙ ПОИСК ПО НИКУ / STEAMID", Color = HexToUiColor("#FFFFFF05"), Align = TextAnchor.MiddleCenter, FontSize = 20, Font = "robotocondensed-regular.ttf"
}
}
, "Report", "Nik");
container.Add(new CuiElement {
Parent = "Nik", Components = {
new CuiInputFieldComponent {
Command = "report ", Text = "РУЧНОЙ ПОИСК ПО НИКУ / STEAMID", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, FontSize = 20, Font = "robotocondensed-regular.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
}
);
#endregion
}
if (target.Length != 17 && reason == "") {
float gap = 0f, width = 0.249f, height = 0.097f, startxBox = 0.002f, startyBox = 0.88f - height, xmin = startxBox, ymin = startyBox;
for (int i = 0; i < 32; i++) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = xmin + " " + ymin, AnchorMax = (xmin + width) + " " + (ymin + height * 1), OffsetMax = "-3 -3", OffsetMin = "3 3"
}
, Button = {
Color = "1 1 1 0.1"
}
, Text = {
Text = $""
}
}
, "Report", $"Buttons.{i}");
xmin += width + gap;
if (xmin + width >= 1) {
xmin = startxBox;
ymin -= height + gap;
}
}
timer.Once(0.1f, () => {
CuiElementContainer containers = new CuiElementContainer();
float gap1 = 0f, width1 = 0.249f, height1 = 0.097f, startxBox1 = 0.002f, startyBox1 = 0.88f - height1, xmin1 = startxBox1, ymin1 = startyBox1;
int t = 0;
foreach (var check in BasePlayer.activePlayerList.Where(p => p.displayName.ToLower().Contains(target.ToLower())).Skip((page - 1) * 1).Take(32)) {
string command = $"report players {check.userID}";
containers.Add(new CuiButton {
RectTransform = {
AnchorMin = xmin1 + " " + ymin1, AnchorMax = (xmin1 + width1) + " " + (ymin1 + height1 * 1), OffsetMax = "-3 -3", OffsetMin = "3 3"
}
, Button = {
Command = command, Color = "0 0 0 0"
}
, Text = {
Text = $"{check.displayName}", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, FontSize = 16, Font = "robotocondensed-regular.ttf"
}
}
, "Report", $"Players.{t}");
xmin1 += width1 + gap1;
if (xmin1 + width1 >= 1) {
xmin1 = startxBox1;
ymin1 -= height1 + gap1;
}
t++;
if (t > 32) {
break;
}
}
CuiHelper.AddUi(player, containers);
}
);
}
else {
CuiHelper.DestroyUi(player, "button");
CuiHelper.DestroyUi(player, "Text");
if (reason == "") {
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.226 0.215", AnchorMax = "0.774 0.272", OffsetMax = "0 0"
}
, Image = {
Color = "0 0 0 0"
}
}
, Layer, "button");
float gap2 = 0.0055f, width2 = 0.245f, height2 = 1f, startxBox2 = 0.002f, startyBox2 = 1f - height2, xmin2 = startxBox2, ymin2 = startyBox2;
int current = 0;
foreach (var check in config.Reasons) {
container.Add(new CuiButton {
RectTransform = {
AnchorMin = xmin2 + " " + ymin2, AnchorMax = (xmin2 + width2) + " " + (ymin2 + height2 * 1), OffsetMax = "0 -3", OffsetMin = "0 3"
}
, Button = {
Color = "0.81 0.30 0.30 0.5", Command = $"report {target.Replace(" ", "").Replace(" ", "").Replace(" ", "")} {check.Value}"
}
, Text = {
Text = $"{check.Value}", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, FontSize = 20, Font = "robotocondensed-bold.ttf"
}
}
, "button", $"{check.Key}");
xmin2 += width2 + gap2;
if (xmin2 + width2 >= 1) {
xmin2 = startxBox2;
ymin2 -= height2 + gap2;
}
current++;
if (current > 4) {
break;
}
}
}
}
CuiHelper.AddUi(player, container);
}
#endregion
#region Окно смерти
private void DeathUI(BasePlayer player) {
CuiElementContainer container = new CuiElementContainer();
CuiHelper.DestroyUi(player, LayerDeath);
container.Add(new CuiPanel {
CursorEnabled = false, RectTransform = {
AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "350 280", OffsetMax = "620 340"
}
, Image = {
Color = "0 0 0 0", FadeIn = 5f
}
,
}
, "Overlay", LayerDeath);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0.4", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "1 1 1 0"
}
, Text = {
Text = $"ПОЖАЛОВАТЬСЯ", FadeIn = 5f, Color = HexToUiColor("#FFFFFF30"), Align = TextAnchor.MiddleCenter, FontSize = 17, Font = "robotocondensed-bold.ttf"
}
}
, LayerDeath);
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.15 0", AnchorMax = "0.85 0.5", OffsetMax = "0 0"
}
, Button = {
Color = "1 1 1 0.1", FadeIn = 5f
}
, Text = {
Text = $"Укажите ник игрока", FadeIn = 5f, Color = HexToUiColor("#FFFFFF10"), Align = TextAnchor.MiddleCenter, FontSize = 17, Font = "robotocondensed-regular.ttf"
}
}
, LayerDeath, "Death");
container.Add(new CuiElement {
Name = "Buttons", Parent = "Death", Components = {
new CuiInputFieldComponent {
Command = $"report death ", Text = "Ваш дискорд или скайп", Color = HexToUiColor("#FFFFFF5A"), Align = TextAnchor.MiddleCenter, FontSize = 20, Font = "robotocondensed-bold.ttf"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1"
}
}
}
);
CuiHelper.AddUi(player, container);
}
private void Sucess(BasePlayer player) {
CuiElementContainer container = new CuiElementContainer();
CuiHelper.DestroyUi(player, "Death");
CuiHelper.DestroyUi(player, "succes");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.15 0", AnchorMax = "0.85 0.5", OffsetMax = "0 0"
}
, Button = {
Color = "0.46 0.73 0.43 0.4", Material = "assets/content/ui/uibackgroundblur-ingamemenu.mat"
}
, Text = {
Text = $"ОТПРАВЛЕНО", Color = HexToUiColor("#FFFFFF90"), Align = TextAnchor.MiddleCenter, FontSize = 20, Font = "robotocondensed-bold.ttf"
}
}
, LayerDeath, "succes");
CuiHelper.AddUi(player, container);
}
#endregion
#endregion
#region Хелпер
private static string HexToUiColor(string hex) {
if (string.IsNullOrEmpty(hex)) {
hex = "#FFFFFFFF";
}
var str = hex.Trim('#');
if (str.Length == 6) str += "FF";
if (str.Length != 8) {
throw new Exception(hex);
throw new InvalidOperationException("Cannot convert a wrong format.");
}
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);
Color color = new Color32(r, g, b, a);
return $"{color.r:F2} {color.g:F2} {color.b:F2} {color.a:F2}";
}
private void MessageVK(string message) {
int randomId = 0;
if (!config.SettingsVk.UseVK) return;
string text = $"{message}";
while (text.Contains("#")) {
text = text.Replace("#", "%23");
}
webrequest.Enqueue($"https://api.vk.com/method/messages.send?chat_id={config.SettingsVk.VKId}&random_id={randomId}&message={text}&access_token={config.SettingsVk.VKTokens}&v=5.92", null, (code, response) => {
}
, this);
randomId++;
}
private double GetCurrentTime() => new TimeSpan(DateTime.UtcNow.Ticks).TotalSeconds;
private static class TimeExtensions {
public static string FormatTime(TimeSpan time) {
string result = string.Empty;
if (time.Days != 0) result += $"{Format(time.Days, "дней", "дня", "день")} ";
if (time.Hours != 0) result += $"{Format(time.Hours, "часов", "часа", "час")} ";
if (time.Minutes != 0) result += $"{Format(time.Minutes, "минут", "минуты", "минута")} ";
if (time.Seconds != 0) result += $"{Format(time.Seconds, "секунд", "секунды", "секунда")} ";
return result;
}
private static string Format(int units, string form1, string form2, string form3) {
var tmp = units % 10;
if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9) return $"{units} {form1}";
if (tmp >= 2 && tmp <= 4) return $"{units} {form2}";
return $"{units} {form3}";
}
}
#endregion
}
}