PDA

Просмотр полной версии : [Мануал] Система бана [MySQL R8]



underwoker
24.07.2014, 06:01
И так, всем доброго времени суток! Надеюсь кому нибудь этот мануальчик будет полезен. Старался все расписать более менее подробно и настолько чтобы нубам было понятно.
Ув. Модераторы и пользователи, если увидите макрос который не указан в теме, напишите пожалуйста. А так же приветствуется адекватная критика.
Начнемс. Учтите, что нам понадобится инклуд и плагин mysql (https://github.com/pBlueG/SA-MP-MySQL/releases/download/R39-2/mysql-r39-2-win.zip),sscanf (http://dl.dropbox.com/u/21683085/sscanf.rar),mxdate (http://rghost.ru/35622578) и DC_CMD (http://pro-pawn.ru/showthread.php?1028-DC_CMD-v2-8-%2823-03-14%29).

Добавим пару макросов, переменных и массивов в начало мода, дабы было удобнее далее их использовать. Если у вас есть уже они, то не добавляйте, а измените на свои.

#define NewKick(%0) SetTimerEx("DelayedKick", 1000, false, "d", (%0))
#define fpub:%0(%1) forward %0(%1); public %0(%1)
#define GetName(%1) pPlayerName[%1]
new querybans[200];
new pPlayerName[MAX_PLAYERS][MAX_PLAYER_NAME];
В конец мода добавим этот паблик и форвард:

forward DelayedKick(playerid);
public DelayedKick(playerid) return Kick(playerid); // Этот паблик относится к таймеру, который был объявлен макросом в начале мануала. Тут мы кикаем игрока через 1000 милисекунд.

Добавим в OnPlayerConnect, после проверки на то, есть ли аккаунт игрока на сервере, запросы в бд, на нахождение ника в списке банов и IP адреса.

GetPlayerName(playerid, pPlayerName[playerid], MAX_PLAYER_NAME);
format(querybans, sizeof(querybans), "SELECT * FROM `Bans` WHERE `Nick` = '%s'", GetName(playerid)); // Форматируем запрос в бд
mysql_function_query(1, querybans, true, "CheckBan", "d", playerid); // Отправляем запрос.
new ipStr[16];
GetPlayerIp( playerid, ipStr, 16 );
format(querybans, sizeof(querybans), "SELECT * FROM `Bans` WHERE `IP` = '%s'", ipStr); // Форматируем запрос в бд
mysql_function_query(1, querybans, true, "CheckBanIP", "d", playerid); // Отправляем запрос.

Добавим паблики в конец мода, так же, в которых будем брать данные из БД после запроса который сделали в OnPlayerConnect

fpub:CheckBanIP(playerid)
{
new unbandate;
new rows,fields;
cache_get_data(rows, fields);
if(rows)
{
unbandate = cache_get_field_content_int(0, "UnbanDate");
if(gettime() >= unbandate)// Если сейчас дата больше чем та что была записана при бане, разбаниваем игрока
{
format(querybans, sizeof(querybans), "DELETE FROM `Bans` WHERE `Nick` = '%s'",GetName(playerid)); // Форматируем.
mysql_function_query(1, querybans, false, "",""); // Отправляем запрос.
return true;
}
else// Иначе выводим диалог что посиди еще в бане, время не вышло.
{
new str[100];
format(str, sizeof(str),"Ваш аккаунт заблокирован\nДата разблокировки: %s",date("%dd/%mm/%yyyy в %hh:%ii:%ss",unbandate));
ShowPlayerDialog(playerid,91,0,"Аккаунт заблокирован:",str,"Ok","");
NewKick(playerid);
}
}
return true;
}

fpub:CheckBan(playerid)
{
new rows,fields;
new unbandate;
cache_get_data(rows, fields);
if(rows)
{
unbandate = cache_get_field_content_int(0, "UnbanDate"); //
if(gettime() >= unbandate) // Если сейчас дата больше чем та что была записана при бане, разбаниваем игрока
{
format(querybans, sizeof(querybans), "DELETE FROM `Bans` WHERE `Nick` = '%s'",GetName(playerid)); // форматируем.
mysql_function_query(1, querybans, false, "","");// Отправляем запрос.
return true;
}
else // Иначе выводим диалог что посиди еще в бане, время не вышло.
{
new str[100];
format(str, sizeof(str),"Ваш аккаунт заблокирован\nДата разблокировки: %s",date("%dd/%mm/%yyyy в %hh:%ii:%ss",unbandate));
ShowPlayerDialog(playerid,91,0,"Аккаунт заблокирован:",str,"Ok","");
NewKick(playerid);
}
}
return true;
}

fpub:GetBan(playerid)
{
new rows,fields;
new str[100],unbandate;
cache_get_data(rows, fields);
if(rows) //Если в бд строки найдены
{
unbandate = cache_get_field_content_int(0, "UnbanDate");
format(str, sizeof(str),"Аккаунт заблокирован. Дата разблокировки: %s",date("%dd/%mm/%yyyy Время: %hh:%ii:%ss",unbandate));
SendClientMessage(playerid, -1, str);
return true;
}
else return SendClientMessage(playerid, -1, "Аккаунт не в бане");// иначе пишем игроку что не заблокирован.
}

fpub:GetBanIP(playerid, ip[])
{
new rows,fields;
new str[100],unbandate;
cache_get_data(rows, fields);
if(rows) //Если в бд строки найдены
{
unbandate = cache_get_field_content_int(0, "UnbanDate");
format(str, sizeof(str),"IP заблокирован. Дата разблокировки: %s",date("%dd/%mm/%yyyy Время: %hh:%ii:%ss",unbandate));
SendClientMessage(playerid, -1, str);
return true;
}
else return SendClientMessage(playerid, -1, "IP не заблокирован."); // иначе пишем игроку что не заблокирован.
}

fpub:Unban(i,nick[])
{
new rows,fields;
cache_get_data(rows, fields);
if(!rows) // Если в бд строки не найдены
{
SendClientMessage(i,-1,"Нету игрока с таким ником в бане!");
}
else // Иначе(если найдены)
{
new string[31+24];
format(querybans, sizeof(querybans), "DELETE FROM `Bans` WHERE `Nick` = '%s'",nick);// Форматируем запрос в бд
mysql_function_query(1, querybans, false, "",""); // отправляем запрос.
format(string, sizeof(string), "Вы успешно разбанили игрока %s!",nick); //форматируем
SendClientMessage(i,-1,string);// отправляем
}
return true;
}

Добавим команды бана, разбана, проверки на бан(Показываю на примере DC_CMD):

CMD:getban_player(playerid, params[])
{
//if(PINFO[playerid][pAdminLVL] < 1) return true; // Данную строчку расскоментируйте и измените переменную админки на свою.
if(sscanf(params,"s[25]",params[0])) return SendClientMessage(playerid, 0x00D900C8, "- Подсказка:{FFFFFF} /getban_player [Ник]");
format(querybans, sizeof(querybans), "SELECT * FROM `Bans` WHERE `Nick` = '%s'", params[0]);// Форматируем запрос в бд
mysql_function_query(1, querybans, true, "GetBan", "d", playerid); // отправляем запрос.
return true;
}

CMD:getban_playerip(playerid, params[])
{
//if(PINFO[playerid][pAdminLVL] < 1) return true; // Данную строчку расскоментируйте и измените переменную админки на свою.
if(sscanf(params,"s[20]",params[0])) return SendClientMessage(playerid, 0x00D900C8, "- Подсказка:{FFFFFF} /getban_playerip [ip]");
format(querybans, sizeof(querybans), "SELECT * FROM `Bans` WHERE `IP` = '%s'", params[0]);// Форматируем запрос в бд
mysql_function_query(1, querybans, true, "GetBanIP", "ds", playerid, params[0]); // отправляем запрос.
return true;
}

CMD:ban(playerid, params[])
{
//if(gPlayerLogged[playerid] == false) return true; //Переменная авторизации игрока поменяйте на свою
//if(PINFO[playerid][pAdminLVL] <= 0) return SendClientMessage(playerid, 0xFF0000AA, "Недостаточно прав!");// Данную строчку расскоментируйте и измените переменную админки на свою.
new string[144],id,days,unbandate2;
if(sscanf(params,"dds[99]",id,days)) return SendClientMessage(playerid, -1, "Используй: /ban [id] [Дни] [причина]"); //
//if(PINFO[params[0]][pAdminLVL] > PINFO[playerid][pAdminLVL]) return SendClientMessage(playerid,-1,"Нельзя забанить администратора");// Данную строчку расскоментируйте и измените переменную админки на свою.
if(!IsPlayerConnected(id)) return SendClientMessage(playerid, 0xFF0000AA, "Ошибка! Введёный id не верен или не в сети!"); // Проверка на онлайн игрока
if(days > 30 || days < 1) return SendClientMessage(playerid, 0xFF0000AA, "Ошибка! Дней от 1-30"); // Проверка на введенные дни
unbandate2 = gettime() + days*86400; // Бан на дни. Записываем нынешнюю дату + число умноженное на 86400 = дни бана.
format(querybans, sizeof(querybans), "INSERT INTO `Bans` (`Nick`, `UnbanDate`) VALUES ('%s', '%d')",GetName(id),unbandate2); // Форматируем запрос в бд
mysql_function_query(1, querybans, false, "",""); Отправляем запрос в бд
format(string, sizeof(string), "%s забанил [ID:%d]%s на %d дней(я)",GetName(playerid),id, GetName(id),days);// Форматируем
SendClientMessageToAll(-1, string);// отправляем всем форматированное сообщение.
NewKick(id); // кикаем игрока
return true;
}

CMD:unban(playerid, params[])
{
//if(gPlayerLogged[playerid] == false) return true; //Переменная авторизации игрока поменяйте на свою и расскоментируйте
//if(PINFO[playerid][pAdminLVL] < 5) return SendClientMessage(playerid, -1, YouCanNot); // Данную строчку расскоментируйте и измените переменную админки на свою.
if(sscanf(params,"s[24]",params[0])) return SendClientMessage(playerid, -1, "Используйте: /unban [Ник]");
format(querybans,sizeof(querybans),"SELECT * FROM Bans WHERE Nick = '%s'", params[0]);// Форматируем запрос в бд
mysql_function_query(1, querybans, true, "Unban", "ds",playerid, params[0]); // отправляем запрос в бд
return true;
}


Скачать саму таблицу Bans для Базы данных:
Тык (https://www.dropbox.com/s/snq9wg57cpicel7/Bans.sql)

Автор мануала: underwoker aka Be3yXa

wAx
24.07.2014, 09:16
publics:GetBan(playerid)
{
new rows,fields;
new string[144];
cache_get_data(rows, fields);
if(rows) //Если в бд строки найдены
{
SendClientMessage(playerid, -1, "Аккаунт заблокирован");
return true;
}
else return SendClientMessage(playerid, -1, "Аккаунт не в бане");// иначе пишем игроку что не заблокирован.
}

Для чего ты объявляешь тут string?


enum name_info
{
pPlayerName[MAX_PLAYER_NAME]
}
new PlayerNames[MAX_PLAYERS][name_info]; // данные ника игрока

Эм?


new pPlayerName[MAX_PLAYERS][24];


Не плохо бы добавить дату разбана, с помощью функции конвертирования из unix в обычное время.

underwoker
24.07.2014, 11:29
publics:GetBan(playerid)
{
new rows,fields;
new string[144];
cache_get_data(rows, fields);
if(rows) //Если в бд строки найдены
{
SendClientMessage(playerid, -1, "Аккаунт заблокирован");
return true;
}
else return SendClientMessage(playerid, -1, "Аккаунт не в бане");// иначе пишем игроку что не заблокирован.
}

Для чего ты объявляешь тут string?


enum name_info
{
pPlayerName[MAX_PLAYER_NAME]
}
new PlayerNames[MAX_PLAYERS][name_info]; // данные ника игрока

Эм?


new pPlayerName[MAX_PLAYERS][24];


Не плохо бы добавить дату разбана, с помощью функции конвертирования из unix в обычное время.

Исправил. Стринг я забыл убрать. А вот о массиве для имени игрока не подумал ;D. Спать хотел, время публикации то вон какое.

underwoker
24.07.2014, 14:29
Не плохо бы добавить дату разбана, с помощью функции конвертирования из unix в обычное время.
Дату разбана сделаю сегодня как приду.

- - - Добавлено - - -

Готово, дата разбана сделана.

wAx
24.07.2014, 16:07
Исправил. Стринг я забыл убрать. А вот о массиве для имени игрока не подумал ;D. Спать хотел, время публикации то вон какое.

Куда делась теперь переменная с ником? Или сейчас тоже спать хочешь?

MR_BEN
24.07.2014, 16:12
А где сама функция date?


publics:CheckBan(playerid)
{
new rows,fields;
new unbandate;
cache_get_data(rows, fields);
if(rows)
{
unbandate = cache_get_field_content_int(0, "UnbanDate"); //
if(gettime() >= unbandate) // Если сейчас дата больше чем та что была записана при бане, разбаниваем игрока
{
format(querybans, 90, "DELETE FROM `Bans` WHERE `Nick` = '%s'",GetName(playerid)); // форматируем.
mysql_function_query(1, querybans, false, "","");// Отправляем запрос.
return true;
}
else // Иначе выводим диалог что посиди еще в бане, время не вышло.
{
new str[100];
format(str, sizeof(str),"Ваш аккаунт заблокирован\nДата разблокировки: %s",date("%dd/%mm/%yyyy в %hh:%ii:%ss",unbandate));
ShowPlayerDialog(playerid,91,0,"Аккаунт заблокирован:",str,"Ok","");
NewKick(playerid);
}
}
return true;
}

wAx
24.07.2014, 16:15
А где сама функция date?


publics:CheckBan(playerid)
{
new rows,fields;
new unbandate;
cache_get_data(rows, fields);
if(rows)
{
unbandate = cache_get_field_content_int(0, "UnbanDate"); //
if(gettime() >= unbandate) // Если сейчас дата больше чем та что была записана при бане, разбаниваем игрока
{
format(querybans, 90, "DELETE FROM `Bans` WHERE `Nick` = '%s'",GetName(playerid)); // форматируем.
mysql_function_query(1, querybans, false, "","");// Отправляем запрос.
return true;
}
else // Иначе выводим диалог что посиди еще в бане, время не вышло.
{
new str[100];
format(str, sizeof(str),"Ваш аккаунт заблокирован\nДата разблокировки: %s",date("%dd/%mm/%yyyy в %hh:%ii:%ss",unbandate));
ShowPlayerDialog(playerid,91,0,"Аккаунт заблокирован:",str,"Ok","");
NewKick(playerid);
}
}
return true;
}

mxdate.inc (http://rghost.ru/35622578)

underwoker
24.07.2014, 17:41
Куда делась теперь переменная с ником? Или сейчас тоже спать хочешь?
Похоже уже не я. Т.к. она используется выше в макросе.

- - - Добавлено - - -


А где сама функция date?


publics:CheckBan(playerid)
{
new rows,fields;
new unbandate;
cache_get_data(rows, fields);
if(rows)
{
unbandate = cache_get_field_content_int(0, "UnbanDate"); //
if(gettime() >= unbandate) // Если сейчас дата больше чем та что была записана при бане, разбаниваем игрока
{
format(querybans, 90, "DELETE FROM `Bans` WHERE `Nick` = '%s'",GetName(playerid)); // форматируем.
mysql_function_query(1, querybans, false, "","");// Отправляем запрос.
return true;
}
else // Иначе выводим диалог что посиди еще в бане, время не вышло.
{
new str[100];
format(str, sizeof(str),"Ваш аккаунт заблокирован\nДата разблокировки: %s",date("%dd/%mm/%yyyy в %hh:%ii:%ss",unbandate));
ShowPlayerDialog(playerid,91,0,"Аккаунт заблокирован:",str,"Ok","");
NewKick(playerid);
}
}
return true;
}
Выше описаны инклуды которые используются в системе.

wAx
24.07.2014, 17:58
Похоже уже не я. Т.к. она используется выше в макросе.

- - - Добавлено - - -


Выше описаны инклуды которые используются в системе.


#define GetName(%1) pPlayerName[%1][MAX_PLAYER_NAME];

Ты об этом макросе?

Все-равно он не верный.

underwoker
24.07.2014, 19:36
#define GetName(%1) pPlayerName[%1][MAX_PLAYER_NAME];

Ты об этом макросе?

Все-равно он не верный.
Эээ, оказывается каким-то образом не сохранились мои изменения в первом посте O_o. Скорее всего когда правили модеры пост.
Все, исправил.

wAx
24.07.2014, 21:07
Ну я думаю хватит адекватной критики. По теме: Хороший урок ))

underwoker
24.07.2014, 21:08
Ну я думаю хватит адекватной критики. По теме: Хороший урок ))
Хех :) Спасибо!

Camelot
25.07.2014, 18:32
Бан работает, но вот есть одна проблема. Забанил я в 17:30, а в игре пишет 23:30. Хотя я живу по МСК времени... На 6 часов зачем-то прибавляет. Есть решение?

underwoker
25.07.2014, 21:22
Эм. Всмысле сервер определяет время неправильное чтоли?

Camelot
25.07.2014, 21:54
Эм. Всмысле сервер определяет время неправильное чтоли?
Да.

Daniel_Cortez
25.07.2014, 22:32
#define NewKick(%0) SetTimerEx("DelayedKick", 1000, false, "d", (%0))




forward DelayedKick(playerid);
public DelayedKick(playerid) return Kick(playerid);

Зачем это вообще нужно в мануале?!
Давно уже есть отдельные статьи (http://pro-pawn.ru/showthread.php?123), в которых описывается исправление проблемы с Kick/Ban/BanEx.





#define GetName(%1) pPlayerName[%1]

Пункт 1 дубль 2.





#define publics:%0(%1) forward %0(%1); public %0(%1)

Что означает название "publics"? Несколько public-функций, объединённых в одну?
Содержимое макроса совсем не соответствует названию. Всё равно, что взять тапок и написать на нём "Таракан".





format(querybans, sizeof(querybans), "SELECT * FROM `Bans` WHERE `IP` = '%s'", ipStr);




format(querybans, 90, "DELETE FROM `Bans` WHERE `Nick` = '%s'",GetName(playerid));

Вы уже определитесь, что будете использовать: оператор sizeof или подсчёт размера массива вручную. Первый вариант предпочтительнее.

Почему вместо хендла на подключение к БД передаётся число 1? Откуда вообще такая уверенность, что у подключения обязательно будет ID 1? В моде может быть и несколько подключений к разным БД.

Табуляция.

underwoker
26.07.2014, 01:36
Зачем это вообще нужно в мануале?!
Давно уже есть отдельные статьи (http://pro-pawn.ru/showthread.php?123), в которых описывается исправление проблемы с Kick/Ban/BanEx.



Пункт 1 дубль 2.



Что означает название "publics"? Несколько public-функций, объединённых в одну?
Содержимое макроса совсем не соответствует названию. Всё равно, что взять тапок и написать на нём "Таракан".




Вы уже определитесь, что будете использовать: оператор sizeof или подсчёт размера массива вручную. Первый вариант предпочтительнее.

Почему вместо хендла на подключение к БД передаётся число 1? Откуда вообще такая уверенность, что у подключения обязательно будет ID 1? В моде может быть и несколько подключений к разным БД.

Табуляция.

1. Я не собираюсь после отвечать новичкам о том, почему у них якобы не появляется сообщение перед киком.
2. Пункт, 1 дубль 2.
3. Ок, перепишу название макроса.
4. Исправил.
5. Я не могу переделывать, мануал под каждого из пользователей и их мод.
6. Табуляция нарушается каждый раз когда я переделываю код прямо на форуме. Вопросы к вашему форуму.

MR_BEN
26.07.2014, 11:37
Мне макрос понравился:)

Salvacore
26.07.2014, 12:24
#define Etot_macros_sozdan_dlya_togo_4tobi_ne_pisat_kazhdii_raz_forward_and_public:%0(%1) forward %0(%1); public %0(%1)
Что за тупость?
Нельзя сделать так что бы новички поняли, без макросов и прочей фигни?

MR_BEN
26.07.2014, 12:55
#define Etot_macros_sozdan_dlya_togo_4tobi_ne_pisat_kazhdii_raz_forward_and_public:%0(%1) forward %0(%1); public %0(%1)
Что за тупость?
Нельзя сделать так что бы новички поняли, без макросов и прочей фигни?

ну вообще макросы, это дело вкуса. Кому как удобнее писать, пусть так и пишут.

Daniel_Cortez
26.07.2014, 14:25
Я не собираюсь после отвечать новичкам о том, почему у них якобы не появляется сообщение перед киком.
Можно было просто сделать в самом начале мануала ссылку на уже существующую статью.



Я не могу переделывать, мануал под каждого из пользователей и их мод.
Не так уж это и сложно:


В самое начало мода:


// вместо "connection_handle" впишите название своей переменной с хендлом подключения
#define ban__connection_handle connection_handle


Затем вместо 1 передавать ban__connection_handle.



Табуляция нарушается каждый раз когда я переделываю код прямо на форуме.
Можно было сделать набросок статьи в блокноте и там же табулировать.



Ок, перепишу название макроса.


#define Etot_macros_sozdan_dlya_togo_4tobi_ne_pisat_kazhdii_raz_forward_and_public:
Вы так каждый раз реагируете на конструктивную критику?

Camelot
26.07.2014, 15:28
Ребят, не подскажите? Почему сервер неправильно время определяет? (на 6 часов вперёд)

Salvacore
26.07.2014, 15:36
Ребят, не подскажите? Почему сервер неправильно время определяет? (на 6 часов вперёд)
Где хостинг находится?

Camelot
26.07.2014, 16:37
Где хостинг находится?

Сервер на моём ПК находится. (Живу по МСК)

underwoker
26.07.2014, 21:30
Вы так каждый раз реагируете на конструктивную критику?
Нет. Я отреагировал так как будет понятно по-моему.

wAx
27.07.2014, 09:30
Нет. Я отреагировал так как будет понятно по-моему.

Из серии: запятые для слабаков. По делу, люди которые дают тебе советы (даже и обсирая параллельно код), они не делают тебе хуже, вы все этого не понимаете, а зря. Крики души нужно держать в себе и молча получать урок от человека, который знает побольше тебя в pawn. Я благодарен тем "троллерам", которые в свое время так обосрали мой код, что мне аж стыдно было.. Но это не сделало меня хуже..

MR_BEN
27.07.2014, 13:48
Сделал бы без макросов. Кому надо, сами добавят.

underwoker
27.07.2014, 15:33
Сделал бы без макросов. Кому надо, сами добавят.
Тоже самое можно сказать и про мануал Просто вырезанный с мода: "Кому надо сами переделают под себя"

underwoker
27.07.2014, 16:06
Из серии: запятые для слабаков. По делу, люди которые дают тебе советы (даже и обсирая параллельно код), они не делают тебе хуже, вы все этого не понимаете, а зря. Крики души нужно держать в себе и молча получать урок от человека, который знает побольше тебя в pawn. Я благодарен тем "троллерам", которые в свое время так обосрали мой код, что мне аж стыдно было.. Но это не сделало меня хуже..
Нет такой серии -_-.
Я все понимаю. Не было крика души, если вы видите ответ, который не угодил вам - это не значит что это крик души.
Какой смысл если я назову макрос fpublic? Ведь тоже не понятно. А так и правда понятно.

wAx
27.07.2014, 17:28
Нет такой серии -_-.
Я все понимаю. Не было крика души, если вы видите ответ, который не угодил вам - это не значит что это крик души.
Какой смысл если я назову макрос fpublic? Ведь тоже не понятно. А так и правда понятно.

C таким настроем тема никогда не будет одобрена! Так держать :good:

underwoker
27.07.2014, 19:12
C таким настроем, тема никогда не будет одобрена! Так держать :good:

:don-t_mention:

Daniel_Cortez
27.07.2014, 19:50
Какой смысл если я назову макрос fpublic? Ведь тоже не понятно.
На forum.sa-mp.com таки часто используют макрос "fpub" и всем всё понятно.

Camelot
28.07.2014, 00:27
Ребят, может поможете мне с определением времени? Живу по МСК. Время на сервере стоит правильное, только при выдачи бана он, почему-то, выдает на 6 часов вперёд.

Gressie
29.07.2014, 08:58
Ребят, может поможете мне с определением времени? Живу по МСК. Время на сервере стоит правильное, только при выдачи бана он, почему-то, выдает на 6 часов вперёд.

Хостинг какой?

Salvacore
29.07.2014, 12:36
Хостинг какой?
Он сказал что на компе запускает.

Gressie
30.07.2014, 19:12
Небольшой вопрос: А если заблокировать подсеть ip то она заблокируется?

underwoker
30.07.2014, 20:14
Небольшой вопрос: А если заблокировать подсеть ip то она заблокируется?
Если блокировать через ркон -да
Если через мускул, то придется делать проверку на первые цифры подсети.

anonimniy
16.10.2014, 12:41
D саму БД, запись даты анбана идет в ужасном числе, что-то типо 14123213 и т.д.
И как можно показать челу, которого забанил, его дату и время разбана прямо в диалоге? Все перепробовал, были два варианта ответа, или число по типу 48 или число по типу 141213123 и пр.

Как-то это можно исправить?