1603 lines
109 KiB
Python
1603 lines
109 KiB
Python
import datetime
|
||
from os import name
|
||
from typing import Text
|
||
|
||
from discord.ext.commands.core import cooldown
|
||
from requests.api import delete
|
||
START_TIME = datetime.datetime.utcnow()
|
||
import locale
|
||
locale.setlocale(locale.LC_NUMERIC, ('ru_RU', 'UTF-8'))
|
||
import sys
|
||
sys.tracebacklimit = 0
|
||
import discord
|
||
import discord_slash
|
||
import vk_api
|
||
import json
|
||
import random
|
||
import asyncio
|
||
import requests
|
||
import threading
|
||
import logging
|
||
import time
|
||
import re
|
||
from string import Template
|
||
from discord import utils
|
||
from vk_api.bot_longpoll import VkBotLongPoll, VkBotEventType
|
||
from discord_slash.utils.manage_commands import create_choice, create_option, create_permission
|
||
from PIL import Image, ImageDraw, ImageFont
|
||
|
||
root_logger = logging.getLogger()
|
||
factory = logging.getLogRecordFactory()
|
||
def add_secs(*args, **kwargs):
|
||
record = factory(*args, **kwargs)
|
||
record.secs = record.relativeCreated/1000
|
||
return record
|
||
logging.setLogRecordFactory(add_secs)
|
||
root_logger.setLevel(logging.INFO)
|
||
try:
|
||
log_path = f'logs/bot_log{str(START_TIME)}.log'
|
||
handler = logging.FileHandler(log_path, 'w', 'utf-8')
|
||
except:
|
||
log_path = 'bot.log'
|
||
handler = logging.FileHandler(log_path, 'w', 'utf-8')
|
||
ch = logging.StreamHandler()
|
||
f = logging.Formatter('[{secs:10.2f}] [{levelname:s}] {message:s} [{name:s}]', style="{")
|
||
handler.setFormatter(f)
|
||
ch.setFormatter(f)
|
||
root_logger.addHandler(handler)
|
||
root_logger.addHandler(ch)
|
||
def log(text):
|
||
logging.info(text)
|
||
log(f"Script started {START_TIME.strftime('%d.%m.%Y %H:%M:%S.%f UTC')}")
|
||
STRING_TRUE = ['true', '1', 't', 'y', 'yes', 'д', 'да', 'ага', 'тирания']
|
||
STRING_FALSE = ['false', '0', 'f', 'n', 'no', 'н', 'нет', 'неа', 'террор']
|
||
ACTIVE_TOTAL = 0
|
||
USERS_LAST_MESSAGE = {}
|
||
USERS_LAST_ACTIVE = {}
|
||
USERS_FLOOD_COUNTER = {}
|
||
INIT_SETUP_CHANNEL = {}
|
||
TO_VERIFY = {}
|
||
NEW_YEAR_STATS = {}
|
||
NEW_YEAR_NOTIFYED = {}
|
||
intents = discord.Intents.default()
|
||
intents.members = True
|
||
client = discord.Client(guild_subscriptions=True, chunk_guilds_at_startup=True, intents=intents)
|
||
slash = discord_slash.SlashCommand(client, sync_commands=True)
|
||
|
||
def num4(num):
|
||
"""Number in 4 symbols and postfix (5 symbols)"""
|
||
num = int(num)
|
||
if len(str(num)) <= 4:
|
||
return str(num)
|
||
postfixs = ["k", "M", "B", "T", "q", "Q", "s", "S"]
|
||
nl = len(str(num))-1
|
||
scale = min(int(nl / 3), len(postfixs))
|
||
num /= 10**(3*scale)
|
||
decimal_length = 2 - nl % 3 if int(nl / 3) <= len(postfixs) else 0
|
||
return f"{num:.{decimal_length}f}{postfixs[scale-1]}"
|
||
|
||
try:
|
||
with open("data.json", "r") as jsn:
|
||
data = json.load(jsn)
|
||
except Exception as e:
|
||
logging.critical(f"Some problem with 'data.json': {e}")
|
||
exit("Some problem with 'data.json'")
|
||
|
||
for g in data['bot-data']:
|
||
if g != "counters" and g != "new_year_event":
|
||
for m in data['bot-data'][g]['active']:
|
||
ACTIVE_TOTAL += data['bot-data'][g]['active'][m]
|
||
|
||
class Counters:
|
||
def __init__(self):
|
||
self.SESSION = {'vk_msg_recived': 0, 'vk_msg_sended': 0, 'exceptions': 0, 'dc_msg_recived': 0,
|
||
'dc_msg_sended': 0}
|
||
try:
|
||
self.COUNTERS = data['bot-data']['counters']
|
||
except:
|
||
self.COUNTERS = {'start_stats_timestamp': datetime.datetime.now().timestamp(), 'uptime_secs': 0,
|
||
'start_ups': 0, 'vk_msg_recived': 0, 'vk_msg_sended': 0, 'exceptions': 0,
|
||
'dc_msg_recived': 0, 'dc_msg_sended': 0}
|
||
self.uptime_from = self.COUNTERS['uptime_secs']
|
||
self.COUNTERS['start_ups'] += 1
|
||
|
||
def incriment(self, case: str):
|
||
if case == "e":
|
||
self.SESSION['exceptions'] += 1
|
||
self.COUNTERS['exceptions'] += 1
|
||
elif case == "vk-r":
|
||
self.SESSION['vk_msg_recived'] += 1
|
||
self.COUNTERS['vk_msg_recived'] += 1
|
||
elif case == "vk-s":
|
||
self.SESSION['vk_msg_sended'] += 1
|
||
self.COUNTERS['vk_msg_sended'] += 1
|
||
elif case == "dc-r":
|
||
self.SESSION['dc_msg_recived'] += 1
|
||
self.COUNTERS['dc_msg_recived'] += 1
|
||
elif case == "dc-s":
|
||
self.SESSION['dc_msg_sended'] += 1
|
||
self.COUNTERS['dc_msg_sended'] += 1
|
||
data['bot-data']['counters'] = self.COUNTERS
|
||
|
||
def show(self, which: str):
|
||
if which == "session":
|
||
return self.SESSION
|
||
elif which == "counters":
|
||
return self.COUNTERS
|
||
|
||
def incriment_uptime(self):
|
||
self.COUNTERS['uptime_secs'] = self.uptime_from + (
|
||
datetime.datetime.utcnow().timestamp() - START_TIME.timestamp())
|
||
data['bot-data']['counters'] = self.COUNTERS
|
||
|
||
counters = Counters()
|
||
|
||
class MyVkLongPoll(VkBotLongPoll):
|
||
def listen(self):
|
||
while True:
|
||
try:
|
||
for event in self.check():
|
||
yield event
|
||
except Exception as e:
|
||
counters.incriment("e")
|
||
err = "A problem with VK LongPull: " + str(e)
|
||
log(err)
|
||
continue
|
||
|
||
def debug():
|
||
numbers = counters.show("session")
|
||
return f"Последний запуск: {START_TIME.strftime('%d.%m.%Y %H:%M:%S.%f UTC')}\n\
|
||
Поймано исключений: {numbers['exceptions']}\n\n\
|
||
**ВК**\n\
|
||
- Отправлено сообщений: {numbers['vk_msg_sended']}\n\
|
||
- Получено сообщений: {numbers['vk_msg_recived']}\n\n\
|
||
**Дискорд**\n\
|
||
- Отправлено сообщений: {numbers['dc_msg_sended']}\n\
|
||
- Получено сообщений: {numbers['dc_msg_recived']}\n"
|
||
|
||
|
||
def counters_print():
|
||
numbers = counters.show("counters")
|
||
return f"**Значения накопительных счётчиков \
|
||
(созданы {datetime.datetime.fromtimestamp(numbers['start_stats_timestamp']).strftime('%d.%m.%Y %H:%M:%S UTC')})**\n\
|
||
Запусков: {numbers['start_ups']}\n\
|
||
Всего поймано исключений: {numbers['exceptions']}\n\n\
|
||
*ВК*\n\
|
||
Всего сообщений: {numbers['vk_msg_sended'] + numbers['vk_msg_recived']}\n\
|
||
- прослушано: {numbers['vk_msg_recived']}\n\
|
||
- отправлено: {numbers['vk_msg_sended']}\n\n\
|
||
*Discord*\n\
|
||
Всего сообщений: {numbers['dc_msg_recived'] + numbers['dc_msg_sended']}\n\
|
||
- прослушано: {numbers['dc_msg_recived']}\n\
|
||
- отправлено: {numbers['dc_msg_sended']}\n\
|
||
"
|
||
|
||
|
||
def uptime_rate():
|
||
now = datetime.datetime.utcnow()
|
||
session_up = datetime.datetime.utcnow() - START_TIME
|
||
start_time = datetime.datetime.fromtimestamp(counters.show("counters")['start_stats_timestamp'])
|
||
all_up = session_up + datetime.timedelta(seconds=counters.uptime_from)
|
||
time_from_init = now - start_time
|
||
uptime_r = (all_up.total_seconds() / time_from_init.total_seconds()) * 100
|
||
return f'Время работы бота: {strfdelta(datetime.datetime.utcnow(), START_TIME, True, "%D:%H:%M:%S")}\n\
|
||
Начиная с {start_time.strftime("%d.%m.%Y")}:\n\
|
||
- Проработал: {strfdelta(datetime.datetime.utcnow(), START_TIME - datetime.timedelta(seconds=counters.uptime_from), True, "%D:%H:%M:%S")}\n\
|
||
- Простаивал: {strfdelta(now, start_time + all_up, True, "%D:%H:%M:%S")}\n\n\
|
||
**UPTIME РЕЙТИНГ: {locale.format_string("%.6f", uptime_r, grouping=True)} %**'
|
||
|
||
|
||
class DeltaTemplate(Template):
|
||
delimiter = "%"
|
||
|
||
def strfdelta(zero:datetime.datetime, dtfrom:datetime.datetime, show_days:bool, temp=None) -> str:
|
||
if zero < dtfrom:
|
||
tdelta = dtfrom - zero
|
||
negative = True
|
||
else:
|
||
tdelta = zero - dtfrom
|
||
negative = False
|
||
if tdelta.days == 0 and temp is None: show_days = False
|
||
if show_days:
|
||
d = {"D": tdelta.days}
|
||
hours, rem = divmod(tdelta.seconds, 3600)
|
||
minutes, seconds = divmod(rem, 60)
|
||
d["H"] = '{:02d}'.format(hours)
|
||
d["M"] = '{:02d}'.format(minutes)
|
||
d["S"] = '{:02d}'.format(seconds)
|
||
if temp is None:
|
||
if negative:
|
||
t = DeltaTemplate('- %D дн. %H:%M:%S')
|
||
else:
|
||
t = DeltaTemplate('%D дн. %H:%M:%S')
|
||
else:
|
||
if negative:
|
||
t = DeltaTemplate('-'+temp)
|
||
else:
|
||
t = DeltaTemplate(temp)
|
||
return t.substitute(**d)
|
||
else:
|
||
d = {"D": tdelta.days}
|
||
hours, rem = divmod(tdelta.seconds, 3600)
|
||
minutes, seconds = divmod(rem, 60)
|
||
hours += d["D"]*24
|
||
d["H"] = hours
|
||
d["M"] = '{:02d}'.format(minutes)
|
||
d["S"] = '{:02d}'.format(seconds)
|
||
if temp is None:
|
||
if negative:
|
||
t = DeltaTemplate('-%H:%M:%S')
|
||
else:
|
||
t = DeltaTemplate('%H:%M:%S')
|
||
else:
|
||
if negative:
|
||
t = DeltaTemplate('-'+temp)
|
||
else:
|
||
t = DeltaTemplate(temp)
|
||
return t.substitute(**d)
|
||
|
||
def hi_msg_temp(user_mention, full_username, temp):
|
||
d = {"user_mention": user_mention, "full_username": full_username}
|
||
return DeltaTemplate(temp).substitute(**d)
|
||
|
||
def widget_temp(temp):
|
||
d = {"until_new_year": strfdelta(datetime.datetime(year=datetime.datetime.utcnow().year, month=12, day=31, hour=21, minute=0), datetime.datetime.utcnow(), False, "%Hч%Mм"),
|
||
"next_year": str(datetime.datetime.now().year + 1)}
|
||
return DeltaTemplate(temp).substitute(**d)
|
||
|
||
def can_use_it(dude, guild_id):
|
||
has_role = False
|
||
if data['bot-data'][str(guild_id)].get("role_access"):
|
||
for i in dude.roles:
|
||
if i.id == data['bot-data'][str(guild_id)]["role_access"]:
|
||
has_role = True
|
||
if dude.id == data['main-data']['owner_id'] or dude.id == data['bot-data'][str(guild_id)]['access'] or has_role:
|
||
return True
|
||
else:
|
||
return False
|
||
|
||
def count_active(dude_id, guild_id, len_of_message, len_of_attachment):
|
||
global ACTIVE_TOTAL
|
||
if not data['bot-data'][str(guild_id)]['active'].get(str(dude_id)):
|
||
data['bot-data'][str(guild_id)]['active'][str(dude_id)] = len_of_message + len_of_attachment*10
|
||
else:
|
||
message_limit = 30
|
||
if len_of_message > message_limit:
|
||
data['bot-data'][str(guild_id)]['active'][str(dude_id)] += message_limit + len_of_attachment*10
|
||
ACTIVE_TOTAL += message_limit + len_of_attachment*10
|
||
else:
|
||
data['bot-data'][str(guild_id)]['active'][str(dude_id)] += len_of_message + len_of_attachment*10
|
||
ACTIVE_TOTAL += len_of_message + len_of_attachment*10
|
||
|
||
async def get_image_stats(msg):
|
||
avatar = await msg.author.avatar_url_as(format="png", size=256).read()
|
||
image_file = open("av.png", "wb")
|
||
image_file.write(avatar)
|
||
image_file.close()
|
||
X = 1000
|
||
Y = 400
|
||
a = str(msg.author.id)
|
||
active_role_level = -1
|
||
if data['bot-data'][str(msg.guild.id)].get("roles") and data['bot-data'][str(msg.guild.id)].get("active_roles"):
|
||
if len(data['bot-data'][str(msg.guild.id)]['roles']) == len(data['bot-data'][str(msg.guild.id)]['active_roles']):
|
||
for i in msg.author.roles:
|
||
for ar in data['bot-data'][str(msg.guild.id)]["roles"]:
|
||
if i.id == ar:
|
||
active_role_level = data['bot-data'][str(msg.guild.id)]["roles"].index(ar)
|
||
show_progress_to_next_role = True
|
||
if active_role_level != len(data['bot-data'][str(msg.guild.id)]["roles"])-1:
|
||
string_next_role = f'До роли "{utils.get(msg.guild.roles, id=data["bot-data"][str(msg.guild.id)]["roles"][active_role_level+1]).name}"'
|
||
user_next_role_active = data['bot-data'][str(msg.guild.id)]["active_roles"][active_role_level+1]
|
||
if active_role_level == -1:
|
||
user_currect_role = "Неактивный"
|
||
user_currect_role_active = 0
|
||
else:
|
||
user_currect_role = utils.get(msg.guild.roles, id=data['bot-data'][str(msg.guild.id)]["roles"][active_role_level]).name
|
||
user_currect_role_active = data['bot-data'][str(msg.guild.id)]["active_roles"][active_role_level]
|
||
else:
|
||
show_progress_to_next_role = False
|
||
user_next_role_active = data['bot-data'][str(msg.guild.id)]["active"][a]
|
||
user_currect_role = utils.get(msg.guild.roles, id=data['bot-data'][str(msg.guild.id)]["roles"][active_role_level]).name
|
||
user_currect_role_active = 0
|
||
else:
|
||
show_progress_to_next_role = False
|
||
user_next_role_active = data['bot-data'][str(msg.guild.id)]["active"][a]
|
||
user_currect_role = f"Ролей: {len(data['bot-data'][str(msg.guild.id)]['roles'])}, требований: {len(data['bot-data'][str(msg.guild.id)]['active_roles'])}. Настройте бота!"
|
||
user_currect_role_active = 0
|
||
else:
|
||
show_progress_to_next_role = False
|
||
user_next_role_active = data['bot-data'][str(msg.guild.id)]["active"][a]
|
||
user_currect_role = ""
|
||
user_currect_role_active = 0
|
||
place = sorted(data['bot-data'][str(msg.guild.id)]["active"], key=lambda i: data['bot-data'][str(msg.guild.id)]["active"][i], reverse=True).index(a)+1
|
||
bar_offset = ((user_next_role_active - user_currect_role_active) - (data['bot-data'][str(msg.guild.id)]['active'][a] - user_currect_role_active)) / (user_next_role_active - user_currect_role_active) * (X - 100)
|
||
im = Image.new("RGB", (X, Y), (25, 25, 25))
|
||
draw = ImageDraw.Draw(im)
|
||
av_pil = Image.open("av.png")
|
||
av_r = av_pil.resize((164, 164))
|
||
font = ImageFont.truetype("19471.ttf", 50)
|
||
big_font = ImageFont.truetype("19471.ttf", 130)
|
||
small_font = ImageFont.truetype("19471.ttf", 30)
|
||
draw.line((50, Y - 50, X - 50, Y - 50), (0, 0, 0), 33)
|
||
draw.line((50, Y - 50, X - 50 - bar_offset, Y - 50), (255, 255, 255), 33)
|
||
draw.text((230, 50), msg.author.display_name, font=font)
|
||
draw.text((230, 160), user_currect_role, font=font)
|
||
draw.text((230, 100), f"#{place} на сервере {msg.guild.name}\nПрисоединился {strfdelta(datetime.datetime.utcnow(), msg.author.joined_at, data['bot-data'][str(msg.guild.id)]['days_in_timedelta'])} назад", font=small_font)
|
||
size3 = font.getsize(locale.format_string("%d", user_next_role_active - data['bot-data'][str(msg.guild.id)]['active'][a], grouping=True))
|
||
if show_progress_to_next_role:
|
||
size1 = small_font.getsize(string_next_role)
|
||
draw.text((X - size1[0] - 50 , Y-135), string_next_role, font=small_font, align="right")
|
||
draw.text((X - size3[0] - 50 , Y-110), locale.format_string("%d", user_next_role_active - data['bot-data'][str(msg.guild.id)]['active'][a], grouping=True), font=font, align="right")
|
||
im.paste(av_r, (50, 50, 214, 214))
|
||
draw.text((50, Y - 170), locale.format_string("%d", data['bot-data'][str(msg.guild.id)]['active'][a], grouping=True), font=big_font)
|
||
im.save("stats.png", "png")
|
||
|
||
async def get_image_stats_all(msg):
|
||
Y = 145
|
||
font = ImageFont.truetype("19471.ttf", 50)
|
||
lower_hat_font = ImageFont.truetype("19471.ttf", 30)
|
||
longest_name_size_x = font.getsize(msg.guild.name)[0]
|
||
for u in data['bot-data'][str(msg.guild.id)]["active"]:
|
||
try:
|
||
name = client.get_guild(msg.guild.id).get_member(int(u)).display_name
|
||
except Exception:
|
||
member = requests.get(f"https://discordapp.com/api/users/{u}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'})
|
||
if member.ok:
|
||
member = member.json()
|
||
name = f"{member['username']}#{member['discriminator']}"
|
||
else:
|
||
name = f"id{u}"
|
||
name_size_x = lower_hat_font.getsize(name)[0]
|
||
Y += 30
|
||
longest_name_size_x = max(longest_name_size_x, name_size_x)
|
||
X = longest_name_size_x + 140 + lower_hat_font.getsize("Актив")[0] + 10
|
||
im = Image.new("RGB", (X, Y), (25, 25, 25))
|
||
draw = ImageDraw.Draw(im)
|
||
title = msg.guild.name
|
||
draw.text((X / 2 - font.getsize(title)[0] / 2, 5), title, font=font)
|
||
draw.text((10, 60), "Пользователь", font=lower_hat_font)
|
||
draw.text((longest_name_size_x + 140, 60), "Актив", font=lower_hat_font)
|
||
start_table_y = 100
|
||
to_draw = sorted(data['bot-data'][str(msg.guild.id)]["active"], key=lambda i: data['bot-data'][str(msg.guild.id)]["active"][i], reverse=True)
|
||
all_a = 0
|
||
for u in to_draw:
|
||
try:
|
||
name = client.get_guild(msg.guild.id).get_member(int(u)).display_name
|
||
except Exception:
|
||
member = requests.get(f"https://discordapp.com/api/users/{u}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'})
|
||
if member.ok:
|
||
member = member.json()
|
||
name = f"{member['username']}#{member['discriminator']}"
|
||
else:
|
||
name = f"id{u}"
|
||
draw.text((10, start_table_y), name, font=lower_hat_font)
|
||
size_a = lower_hat_font.getsize(locale.format_string("%d", data['bot-data'][str(msg.guild.id)]["active"][u], grouping=True))
|
||
draw.text((longest_name_size_x + 140 + lower_hat_font.getsize("Актив")[0] - size_a[0], start_table_y), locale.format_string("%d", data['bot-data'][str(msg.guild.id)]["active"][u], grouping=True), font=lower_hat_font)
|
||
start_table_y += 30
|
||
all_a += data['bot-data'][str(msg.guild.id)]["active"][u]
|
||
start_table_y += 10
|
||
draw.text((10, start_table_y), "Весь сервер:", font=lower_hat_font)
|
||
size_a = lower_hat_font.getsize(locale.format_string("%d", all_a, grouping=True))
|
||
draw.text((longest_name_size_x + 140 + lower_hat_font.getsize("Актив")[0] - size_a[0], start_table_y), locale.format_string("%d", all_a, grouping=True), font=lower_hat_font)
|
||
im.save("stats_all.png", "png")
|
||
|
||
async def get_image_stats_all_guilds(msg):
|
||
Y = 145
|
||
font = ImageFont.truetype("19471.ttf", 50)
|
||
lower_hat_font = ImageFont.truetype("19471.ttf", 30)
|
||
longest_name_size_x = font.getsize("Актив всех серверов")[0]
|
||
guilds = {}
|
||
for g in data['bot-data']:
|
||
if g != "counters":
|
||
name = client.get_guild(int(g)).name
|
||
name_size_x = lower_hat_font.getsize(name)[0]
|
||
Y += 30
|
||
longest_name_size_x = max(longest_name_size_x, name_size_x)
|
||
active = sum(
|
||
data['bot-data'][g]["active"][m]
|
||
for m in data["bot-data"][g]["active"]
|
||
)
|
||
guilds[g] = {'name': name, 'active': active}
|
||
X = longest_name_size_x + 140 + lower_hat_font.getsize("Актив")[0] + 10
|
||
im = Image.new("RGB", (X, Y), (25, 25, 25))
|
||
draw = ImageDraw.Draw(im)
|
||
title = "Актив всех серверов"
|
||
draw.text((X / 2 - font.getsize(title)[0] / 2, 5), title, font=font)
|
||
draw.text((10, 60), "Сервер", font=lower_hat_font)
|
||
draw.text((longest_name_size_x + 140, 60), "Актив", font=lower_hat_font)
|
||
start_table_y = 100
|
||
to_draw = sorted(guilds, key=lambda i: guilds[i]["active"], reverse=True)
|
||
all_a = 0
|
||
for u in to_draw:
|
||
draw.text((10, start_table_y), guilds[u]["name"], font=lower_hat_font)
|
||
size_a = lower_hat_font.getsize(locale.format_string("%d", guilds[u]["active"], grouping=True))
|
||
draw.text((longest_name_size_x + 140 + lower_hat_font.getsize("Актив")[0] - size_a[0], start_table_y), locale.format_string("%d", guilds[u]["active"], grouping=True), font=lower_hat_font)
|
||
start_table_y += 30
|
||
all_a += guilds[u]["active"]
|
||
start_table_y += 10
|
||
draw.text((10, start_table_y), "Все сервера:", font=lower_hat_font)
|
||
size_a = lower_hat_font.getsize(locale.format_string("%d", all_a, grouping=True))
|
||
draw.text((longest_name_size_x + 140 + lower_hat_font.getsize("Актив")[0] - size_a[0], start_table_y), locale.format_string("%d", all_a, grouping=True), font=lower_hat_font)
|
||
im.save("stats_all_guilds.png", "png")
|
||
|
||
@client.event
|
||
async def on_ready():
|
||
log(f'Logged in Discord as {client.user}')
|
||
global NEW_YEAR_STATS
|
||
NEW_YEAR_STATS = data['bot-data']["new_year_event"]
|
||
for g in data['bot-data']:
|
||
if g != "counters" and g != "new_year_event":
|
||
if data['bot-data'][g]['state'] != 'normal':
|
||
data['bot-data'][g]['state'] = 'normal'
|
||
NEW_YEAR_NOTIFYED[g] = False
|
||
if not NEW_YEAR_STATS.get(g):
|
||
NEW_YEAR_STATS[g] = {'cooldown': 1638835200, "times_used": {}, "type_used":{"ban": 0, "not_ban": 0}, "victums": {}, "longest_mute":None, "shortest_mute":None}
|
||
|
||
|
||
@client.event
|
||
async def on_message(message):
|
||
if isinstance(message.channel, discord.TextChannel):
|
||
if message.author == client.user:
|
||
counters.incriment("dc-s")
|
||
m = message.content.replace("\n", "⁞")
|
||
log(f'Bot in {message.guild} #{message.channel}: "{m}", attachments: {message.attachments}')
|
||
else:
|
||
m = message.content.replace("\n", "⁞")
|
||
log(f'{message.author} in {message.guild} #{message.channel}: "{m}", attachments: {message.attachments}')
|
||
counters.incriment("dc-r")
|
||
if not data['bot-data'].get(str(message.guild.id)):
|
||
data['bot-data'][str(message.guild.id)] = {"active": {}, "muted": {}, "banned": {}, "count_channel": 1, "access": message.guild.owner_id, "state": "normal", "command_prefix": "$", 'can_ban': False, 'react_on_join_leave_members': False, 'days_in_timedelta': True, "days_for_spam": 1}
|
||
if not data.get("game"):
|
||
data['game'] = {}
|
||
if not USERS_LAST_ACTIVE.get(str(message.guild.id)):
|
||
USERS_LAST_ACTIVE[str(message.guild.id)] = {str(message.author.id): datetime.datetime(2020, 1, 1)}
|
||
if not USERS_LAST_MESSAGE.get(str(message.guild.id)):
|
||
USERS_LAST_MESSAGE[str(message.guild.id)] = {str(message.author.id): ""}
|
||
if not USERS_FLOOD_COUNTER.get(str(message.guild.id)):
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)] = {str(message.author.id): 0}
|
||
if not USERS_LAST_ACTIVE[str(message.guild.id)].get(str(message.author.id)):
|
||
USERS_LAST_ACTIVE[str(message.guild.id)][str(message.author.id)] = datetime.datetime(2020, 1, 1)
|
||
if not USERS_LAST_MESSAGE[str(message.guild.id)].get(str(message.author.id)):
|
||
USERS_LAST_MESSAGE[str(message.guild.id)][str(message.author.id)] = ""
|
||
if not USERS_FLOOD_COUNTER[str(message.guild.id)].get(str(message.author.id)):
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] = 0
|
||
|
||
if not message.author.bot and (message.content != "" or len(message.attachments) > 0) and (USERS_LAST_MESSAGE[str(message.guild.id)][str(message.author.id)] != message.content or len(message.attachments) > 0):
|
||
count_active(message.author.id, message.guild.id, len(message.content), len(message.attachments))
|
||
|
||
if data['bot-data'][str(message.guild.id)].get("mute_role") and data['bot-data'][str(message.guild.id)].get('flood_limit'):
|
||
invite_search = re.search(r"discord\.gg\/\w+", message.content)
|
||
if invite_search is not None and not can_use_it(message.author, message.guild.id):
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] = data['bot-data'][str(message.guild.id)]['flood_limit']
|
||
await message.delete()
|
||
elif 747797669648269364 in message.raw_role_mentions:
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] += 3
|
||
elif len(message.attachments) == 0 and (USERS_LAST_MESSAGE[str(message.guild.id)][str(message.author.id)] == message.content or (message.created_at - USERS_LAST_ACTIVE[str(message.guild.id)][str(message.author.id)]) < datetime.timedelta(0, 2,5)):
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] += 1
|
||
elif USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] > 0:
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] -= 1
|
||
if USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] >= data['bot-data'][str(message.guild.id)]['flood_limit']:
|
||
role = utils.get(message.guild.roles, id=data['bot-data'][str(message.guild.id)]['mute_role'])
|
||
await message.author.add_roles(role)
|
||
now = datetime.datetime.utcnow()
|
||
mute = datetime.timedelta(days=1)
|
||
mute_time = now + mute
|
||
data['bot-data'][str(message.guild.id)]['muted'][str(message.author.id)] = {"timestamp": mute_time.timestamp(), "reason": "Спам", "by_id": client.user.id, "done": datetime.datetime.utcnow().timestamp()}
|
||
emb = discord.Embed(description=f"От {client.user.mention} специально для {message.author.mention}\n**Срок молчалки:** {strfdelta(now+mute, now, data['bot-data'][str(message.guild.id)]['days_in_timedelta'])}", title=f"Молчалка за спам", timestamp=mute_time, colour=0x0000ff)
|
||
emb.set_author(name=f"{message.author.name} (Ник: {message.author.nick})", icon_url=message.author.avatar_url)
|
||
await message.channel.send(f"Ты в муте за спам {message.author.mention}", embed=emb)
|
||
USERS_FLOOD_COUNTER[str(message.guild.id)][str(message.author.id)] = 0
|
||
|
||
USERS_LAST_MESSAGE[str(message.guild.id)][str(message.author.id)] = message.content
|
||
USERS_LAST_ACTIVE[str(message.guild.id)][str(message.author.id)] = message.created_at
|
||
|
||
if data['bot-data'][str(message.guild.id)].get("roles") and data['bot-data'][str(message.guild.id)].get("active_roles") and not message.author.bot:
|
||
if len(data['bot-data'][str(message.guild.id)]['roles']) == len(data['bot-data'][str(message.guild.id)]['active_roles']):
|
||
active_role_level = -1
|
||
for i in message.author.roles:
|
||
for ar in data['bot-data'][str(message.guild.id)]["roles"]:
|
||
if i.id == ar:
|
||
active_role_level = data['bot-data'][str(message.guild.id)]["roles"].index(ar)
|
||
for ari in data['bot-data'][str(message.guild.id)]['roles']:
|
||
if active_role_level != len(data['bot-data'][str(message.guild.id)]['roles'])-1:
|
||
if data['bot-data'][str(message.guild.id)]["active"][str(message.author.id)] >= int(data['bot-data'][str(message.guild.id)]['active_roles'][data['bot-data'][str(message.guild.id)]['roles'].index(ari)]) and active_role_level < data['bot-data'][str(message.guild.id)]['roles'].index(ari):
|
||
role = utils.get(message.guild.roles, id=ari)
|
||
await message.author.add_roles(role)
|
||
text = f"{message.author.mention}, вы проявили достаточно актива для получения роли \"{role.name}\", поздравляю"
|
||
if data['bot-data'][str(message.guild.id)].get('notify_channel'):
|
||
await message.guild.get_channel(data['bot-data'][str(message.guild.id)]['notify_channel']).send(text)
|
||
else:
|
||
await message.channel.send(text)
|
||
role = utils.get(message.guild.roles, id=data['bot-data'][str(message.guild.id)]['roles'][active_role_level])
|
||
await message.author.remove_roles(role)
|
||
|
||
if data['bot-data'][str(message.guild.id)].get("count_log"):
|
||
if message.channel.id == data['bot-data'][str(message.guild.id)]["count_log"] and message.author != client.user:
|
||
try:
|
||
if int(message.content) == data['bot-data'][str(message.guild.id)]["count_channel"]:
|
||
data['bot-data'][str(message.guild.id)]["count_channel"] += 1
|
||
if data['bot-data'][str(message.guild.id)].get("roles_count"):
|
||
if (data['bot-data'][str(message.guild.id)]["count_channel"]-1) % 10000 == 0:
|
||
role = utils.get(message.guild.roles, id=data['bot-data'][str(message.guild.id)]["roles_count"][3])
|
||
await message.author.add_roles(role)
|
||
await message.pin()
|
||
elif (data['bot-data'][str(message.guild.id)]["count_channel"]-1) % 1000 == 0:
|
||
role = utils.get(message.guild.roles, id=data['bot-data'][str(message.guild.id)]["roles_count"][2])
|
||
await message.author.add_roles(role)
|
||
await message.pin()
|
||
elif (data['bot-data'][str(message.guild.id)]["count_channel"]-1) == 500:
|
||
role = utils.get(message.guild.roles, id=data['bot-data'][str(message.guild.id)]["roles_count"][1])
|
||
await message.author.add_roles(role)
|
||
await message.pin()
|
||
elif (data['bot-data'][str(message.guild.id)]["count_channel"]-1) == 100:
|
||
role = utils.get(message.guild.roles, id=data['bot-data'][str(message.guild.id)]["roles_count"][0])
|
||
await message.author.add_roles(role)
|
||
await message.pin()
|
||
else:
|
||
if (data['bot-data'][str(message.guild.id)]["count_channel"]-1) % 10000 == 0:
|
||
await message.pin()
|
||
elif (data['bot-data'][str(message.guild.id)]["count_channel"]-1) % 1000 == 0:
|
||
await message.pin()
|
||
elif (data['bot-data'][str(message.guild.id)]["count_channel"]-1) == 500:
|
||
await message.pin()
|
||
elif (data['bot-data'][str(message.guild.id)]["count_channel"]-1) == 100:
|
||
await message.pin()
|
||
else:
|
||
await message.delete()
|
||
except ValueError:
|
||
await message.delete()
|
||
if message.content.lower() == "бот дай денег":
|
||
await message.channel.send("Иди нахуй")
|
||
with open("data.json", "w") as jsn:
|
||
json.dump(data, jsn)
|
||
elif isinstance(message.channel, discord.DMChannel):
|
||
log(f'Message in {message.channel} by "{message.author}": "{message.content}", attachments: {message.attachments}')
|
||
if message.content == "reboot" and message.author.id == data['main-data']['owner_id']:
|
||
await message.channel.send(f"Перезагружаюсь")
|
||
exit("Got command to exit")
|
||
if message.content == "ъ":
|
||
await message.channel.send(f"ь")
|
||
else:
|
||
log(message)
|
||
|
||
@client.event
|
||
async def on_error(event, *args, **kwargs):
|
||
counters.incriment("e")
|
||
exc = sys.exc_info()
|
||
logging.error(f"Exception {exc[0]} in {event}: {exc[1]}", exc_info=exc)
|
||
|
||
@client.event
|
||
async def on_guild_join(guild):
|
||
log(f"We joined to {guild}")
|
||
data['bot-data'][str(guild.id)] = {"active": {}, "muted": {}, "banned": {}, "count_channel": 1, "access": guild.owner_id, "state": "normal", 'can_ban': False, 'react_on_join_leave_members': False, 'days_in_timedelta': True, "days_for_spam": 1}
|
||
await guild.system_channel.send(f"Доброго времени суток. Спасибо, что пригласили меня на свой сервер. Используйте команду /help, чтобы узнать о моих возможностях")
|
||
with open("data.json", "w") as jsn:
|
||
json.dump(data, jsn)
|
||
|
||
@client.event
|
||
async def on_member_join(member):
|
||
log(f"Joined member {member} to guild {member.guild}")
|
||
muted = False
|
||
banned = False
|
||
for u in data['bot-data'][str(member.guild.id)]["muted"]:
|
||
if u == str(member.id):
|
||
role = utils.get(member.guild.roles, id=data['bot-data'][str(member.guild.id)]['mute_role'])
|
||
await member.add_roles(role)
|
||
muted = True
|
||
for u in data['bot-data'][str(member.guild.id)]["banned"]:
|
||
if u == str(member.id):
|
||
banned = True
|
||
if banned:
|
||
mesg = await member.guild.system_channel.send(f'Персонаж из бан листа {member.name}#{member.discriminator} осмелился ступить на сервер. Что-ж, банхаммер на готове.')
|
||
await member.ban(reason=data['bot-data'][str(member.guild.id)]["banned"][str(member.id)]['reason'])
|
||
elif muted:
|
||
strtimediff = strfdelta(datetime.datetime.fromtimestamp(data["bot-data"][str(member.guild.id)]["muted"][str(member.id)]["timestamp"]), datetime.datetime.utcnow(), data['bot-data'][str(member.guild.id)]['days_in_timedelta'])
|
||
mesg = await member.guild.system_channel.send(f'Ку, {member.mention}. На этом сервере ты получил мут от <@{data["bot-data"][str(member.guild.id)]["muted"][str(member.id)]["by_id"]}> за "{data["bot-data"][str(member.guild.id)]["muted"][str(member.id)]["reason"]}" и он истекает через {strtimediff}')
|
||
elif data['bot-data'][str(member.guild.id)].get("role_for_verification"):
|
||
if not data['bot-data'][str(member.guild.id)].get('hi_msg'):
|
||
mesg = await member.guild.system_channel.send(f'Добро пожаловать, {member.mention}. Чтобы получить роль участника "{utils.get(member.guild.roles, id=data["bot-data"][str(member.guild.id)]["role_for_verification"]).name}" и получить доступ к серверу, поставьте реакцию на это сообщение.')
|
||
else:
|
||
mesg = await member.guild.system_channel.send(hi_msg_temp(member.mention, f"{member.name}#{member.discriminator}", data['bot-data'][str(member.guild.id)]['hi_msg']) + f'\nЧтобы получить роль участника "{utils.get(member.guild.roles, id=data["bot-data"][str(member.guild.id)]["role_for_verification"]).name}" и получить доступ к серверу, поставьте реакцию на это сообщение.')
|
||
elif data['bot-data'][str(member.guild.id)]["react_on_join_leave_members"]:
|
||
if not data['bot-data'][str(member.guild.id)].get('hi_msg'):
|
||
await member.guild.system_channel.send(f'Добро пожаловать, {member.mention}')
|
||
else:
|
||
await member.guild.system_channel.send(hi_msg_temp(member.mention, f"{member.name}#{member.discriminator}", data['bot-data'][str(member.guild.id)]['hi_msg']))
|
||
if data['bot-data'][str(member.guild.id)].get("role_for_verification"):
|
||
await mesg.add_reaction("✅")
|
||
if not TO_VERIFY.get(str(member.guild.id)):
|
||
TO_VERIFY[str(member.guild.id)] = []
|
||
TO_VERIFY[str(member.guild.id)].append(member.id)
|
||
if data['bot-data'][str(member.guild.id)].get("admin_log"):
|
||
emb = discord.Embed(description=f"**Дата регистрации:** {member.created_at.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**Cуществует уже:** {strfdelta(datetime.datetime.utcnow(), member.created_at, data['bot-data'][str(member.guild.id)]['days_in_timedelta'])}", title=f"Новый пользователь на сервере", timestamp=member.joined_at, colour=0xd1e9ef)
|
||
emb.set_author(name=f"{member.name}#{member.discriminator}", icon_url=member.avatar_url)
|
||
emb.set_footer(text=f"User ID: {member.id}, Bot: {member.bot}")
|
||
await client.get_channel(data['bot-data'][str(member.guild.id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_member_remove(member):
|
||
log(f"Removed member {member} from guild {member.guild}")
|
||
if data['bot-data'][str(member.guild.id)].get("admin_log"):
|
||
emb = discord.Embed(description=f"**Дата регистрации:** {member.created_at.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**Cуществует уже:** {strfdelta(datetime.datetime.utcnow(), member.created_at, data['bot-data'][str(member.guild.id)]['days_in_timedelta'])}\n**Пробыл на сервере**: {strfdelta(datetime.datetime.utcnow(), member.joined_at, data['bot-data'][str(member.guild.id)]['days_in_timedelta'])}", title=f"Пользователь покинул сервер", timestamp=member.joined_at, colour=0xff0000)
|
||
emb.set_author(name=f"{member.name}#{member.discriminator}", icon_url=member.avatar_url)
|
||
emb.set_footer(text=f"User ID: {member.id}, Bot: {member.bot}")
|
||
await client.get_channel(data['bot-data'][str(member.guild.id)]['admin_log']).send(embed=emb)
|
||
if data['bot-data'][str(member.guild.id)]["react_on_join_leave_members"]:
|
||
await member.guild.system_channel.send(f'{member} покинул сервер. Он пробыл здесь всего {strfdelta(datetime.datetime.utcnow(), member.joined_at, data["bot-data"][str(member.guild.id)]["days_in_timedelta"])}')
|
||
|
||
@client.event
|
||
async def on_raw_reaction_add(payload):
|
||
if TO_VERIFY.get(str(payload.guild_id)) and data['bot-data'][str(payload.guild_id)].get("role_for_verification"):
|
||
for i in TO_VERIFY[str(payload.guild_id)]:
|
||
if i == payload.user_id:
|
||
TO_VERIFY[str(payload.guild_id)].remove(i)
|
||
await payload.member.add_roles(utils.get(client.get_guild(payload.guild_id).roles, id=data['bot-data'][str(payload.guild_id)]["role_for_verification"]))
|
||
|
||
@client.event
|
||
async def on_raw_message_delete(payload):
|
||
if data['bot-data'][str(payload.guild_id)].get("admin_log"):
|
||
if payload.cached_message:
|
||
emb = discord.Embed(title="Было удалено сообщение", description=payload.cached_message.content, timestamp=payload.cached_message.created_at, colour=0xff0000)
|
||
emb.set_author(name=f"{payload.cached_message.author.name} (Ник: {payload.cached_message.author.nick}) #{payload.cached_message.channel}", icon_url=payload.cached_message.author.avatar_url)
|
||
if payload.cached_message.attachments:
|
||
for i in payload.cached_message.attachments:
|
||
emb.add_field(name="Прикреплено", value=i.filename, inline=False)
|
||
if payload.cached_message.reactions:
|
||
reactions = ""
|
||
for i in payload.cached_message.reactions:
|
||
if reactions == "":
|
||
reactions += f"{i.emoji} **{i.count}**"
|
||
else:
|
||
reactions += f", {i.emoji} **{i.count}**"
|
||
emb.add_field(name=f"Реакций: {len(payload.cached_message.reactions)}", value=reactions, inline=False)
|
||
else:
|
||
emb = discord.Embed(title="Было удалено сообщение", description="Сообщения не было в кеше бота", colour=0xff0000)
|
||
await client.get_channel(data['bot-data'][str(payload.guild_id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_member_update(before, after):
|
||
if data['bot-data'][str(before.guild.id)].get("admin_log"):
|
||
if after.nick != before.nick:
|
||
emb = discord.Embed(title="Пользователь изменил свой ник на сервере", colour=0x00ff00)
|
||
if before.nick is not None:
|
||
emb.add_field(name="Старый ник", value=before.nick)
|
||
else:
|
||
emb.add_field(name="Старый ник", value="**Нет ника**")
|
||
if after.nick is not None:
|
||
emb.add_field(name="Новый ник", value=after.nick)
|
||
else:
|
||
emb.add_field(name="Новый ник", value="**Нет ника**")
|
||
emb.set_author(name=after.name, icon_url=after.avatar_url)
|
||
await client.get_channel(data['bot-data'][str(before.guild.id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_member_ban(guild, user):
|
||
log(f"Banned in {guild}: {user}")
|
||
if data['bot-data'][str(guild.id)].get("admin_log"):
|
||
emb = discord.Embed(title="Пользователь был забанен", description=f"**Дата регистрации:** {user.created_at.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**Cуществует уже:** {strfdelta(datetime.datetime.utcnow(), user.created_at, data['bot-data'][str(guild.id)]['mute_role'])}\n**Пробыл на сервере**: {strfdelta(datetime.datetime.utcnow(), user.joined_at, data['bot-data'][str(guild.id)]['mute_role'])}", colour=0xff0000)
|
||
emb.set_author(name=f"{user.name}#{user.discriminator}", icon_url=user.avatar_url)
|
||
emb.set_footer(text=f"User ID: {user.id}, Bot: {user.bot}")
|
||
await client.get_channel(data['bot-data'][str(guild.id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_member_unban(guild, user):
|
||
log(f"Unbanned in {guild}: {user}")
|
||
if data['bot-data'][str(guild.id)].get("admin_log"):
|
||
emb = discord.Embed(title="Пользователь был разбанен", description=f"**Дата регистрации:** {user.created_at.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**Cуществует уже:** {strfdelta(datetime.datetime.utcnow(), user.created_at, data['bot-data'][str(guild.id)]['mute_role'])}", colour=0x00ff00)
|
||
emb.set_author(name=f"{user.name}#{user.discriminator}", icon_url=user.avatar_url)
|
||
emb.set_footer(text=f"User ID: {user.id}, Bot: {user.bot}")
|
||
await client.get_channel(data['bot-data'][str(guild.id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_invite_create(invite):
|
||
if data['bot-data'][str(invite.guild.id)].get("admin_log"):
|
||
emb = discord.Embed(title="Была создана ссылка-приглашение", description=invite.url, timestamp=invite.created_at, colour=0x0000ff)
|
||
emb.add_field(name="Канал", value=invite.channel.mention)
|
||
if invite.max_age > 0 and invite.max_age != None:
|
||
emb.add_field(name="Срок действия", value=f"{strfdelta(invite.created_at+datetime.timedelta(0, invite.max_age), invite.created_at, data['bot-data'][str(invite.guild.id)]['mute_role'])}\n(до {(invite.created_at+datetime.timedelta(0, invite.max_age)).strftime('%d.%m.%Y %H:%M:%S UTC')})")
|
||
else:
|
||
emb.add_field(name="Срок действия", value="Вечная ссылка")
|
||
if invite.max_uses > 0 and invite.max_uses != None:
|
||
emb.add_field(name="Лимит на использование", value=f"{invite.max_uses} раз")
|
||
if invite.temporary:
|
||
emb.add_field(name="Ссылка предоставляет временное членство", value="Если временным учасникам не выдадут роль, они автоматически будут кикнуты")
|
||
emb.set_author(name=invite.inviter.display_name, icon_url=invite.inviter.avatar_url)
|
||
await client.get_channel(data['bot-data'][str(invite.guild.id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_invite_delete(invite):
|
||
if data['bot-data'][str(invite.guild.id)].get("admin_log"):
|
||
emb = discord.Embed(title="Была удалена ссылка-приглашение", description=invite.url, colour=0xff0000)
|
||
emb.add_field(name="Канал", value=invite.channel.mention)
|
||
await client.get_channel(data['bot-data'][str(invite.guild.id)]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_raw_message_edit(payload):
|
||
if data['bot-data'][payload.data['guild_id']].get("admin_log"):
|
||
emb = discord.Embed(title="Было отредактировано сообщение", description=f"**Отредактировано:** {datetime.datetime.strptime(payload.data['edited_timestamp'], '%Y-%m-%dT%H:%M:%S.%f%z').strftime('%d.%m.%Y %H:%M:%S UTC')}", timestamp=datetime.datetime.strptime(payload.data['timestamp'], "%Y-%m-%dT%H:%M:%S.%f%z"), colour=0x0000ff)
|
||
if payload.cached_message:
|
||
emb.set_author(name=f"{payload.cached_message.author.name} (Ник: {payload.cached_message.author.nick}) #{payload.cached_message.channel}", icon_url=payload.cached_message.author.avatar_url)
|
||
emb.add_field(name="Старый текст", value=payload.cached_message.content, inline=True)
|
||
else:
|
||
emb.set_author(name=f"{payload.data['author']['username']}")
|
||
emb.add_field(name="Сообщения не было в кеше бота", value="Невозможно показать разницу", inline=True)
|
||
emb.add_field(name="Новый текст", value=payload.data['content'], inline=True)
|
||
await client.get_channel(data['bot-data'][payload.data['guild_id']]['admin_log']).send(embed=emb)
|
||
|
||
@client.event
|
||
async def on_guild_remove(guild):
|
||
log(f"We left from {guild}")
|
||
global ACTIVE_TOTAL
|
||
for m in data['bot-data'][str(guild.id)]['active']:
|
||
ACTIVE_TOTAL -= data['bot-data'][str(guild.id)]['active'][m]
|
||
del data['bot-data'][str(guild.id)]
|
||
|
||
@slash.slash(name="help", description="Справочный материал с описанием команд бота")
|
||
async def help(ctx):
|
||
emb = discord.Embed(title="Справочный материал с описанием команд бота", description="Эта справка призвана помочь разобраться в командах бота")
|
||
emb.add_field(name=f"/random *X* *Y*", value="Генерирует рандомное число от *X* до *Y*. Если *Y* нету, то тогда от 0 до *X*. Если и *X* нет, то тогда от 0 до 10")
|
||
emb.add_field(name=f"/stats *choice*", value="Посмотреть актив, который насчитал бот для вас, а если после команды написать *all*, то можно посмотреть актив, который насчитал бот для всего сервера")
|
||
#emb.add_field(name=f"{data['bot-data'][str(ctx.guild.id)]['command_prefix']}кнб *камень/ножницы/бумага/стат*", value='Сыграть в "Камень, ножницы, бумага" с ботом, если приписать аргумент *стат*, можно увидеть количесво побед, поражений и ничей')
|
||
emb.add_field(name=f"/slap *@user*", value='Шлёпнуть *@user* или рандомного персонажа на сервере, если не упомянут')
|
||
if can_use_it(ctx.author, ctx.guild.id):
|
||
emb.add_field(name=f"/settings", value="Даёт возможность перенастроить бота")
|
||
if data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
emb.add_field(name=f"/mute *@user* *<int>[s, m, h, d, w]/DD.MM.YYYY* *reason*", value="Выдать молчалку пользователю. Команда имеет 2 обязательных аргумента: *@user* - упоминание персоны; *<int>[s, m, h, d, w]/DD.MM.YYYY* - либо срок в относительном формате (30m - 30 минут, 7d - 7 дней), либо дата. Есть также 3-ий необязательный аргумент: *reason* - причина мута.")
|
||
emb.add_field(name=f"/unmute *@user*", value="Cнять молчалку с пользователя. *@user* - упоминание персоны")
|
||
emb.add_field(name=f"/mute_list", value="Показать активные на сервере молчалки")
|
||
if data['bot-data'][str(ctx.guild.id)]["can_ban"]:
|
||
emb.add_field(name=f"/ban *@user* *<int>[s, m, h, d, w]/DD.MM.YYYY* *reason*", value="Забанить пользователя. Команда имеет 2 обязательных аргумента: *@user* - упоминание персоны; *<int>[s, m, h, d, w]/DD.MM.YYYY* - либо срок в относительном формате (30m - 30 минут, 7d - 7 дней), либо дата. Есть также 3-ий необязательный аргумент: *reason* - причина бана.")
|
||
emb.add_field(name=f"/unban *id<int>*", value="Разбанить пользователя, которого забанили командой /ban. *id<int>* - его цифровой id")
|
||
emb.add_field(name=f"/ban_list", value="Показать активные на сервере баны")
|
||
await ctx.send(embed=emb)
|
||
|
||
@slash.slash(name="random", description="Отправляет рандомное число от X до Y",
|
||
options=[create_option(name="x_int", description="Наименьшее число если используется вместе с y_int, иначе число больше нуля", option_type=4, required=False),
|
||
create_option(name="y_int", description="Наибольшее число", option_type=4, required=False)])
|
||
async def randon(ctx, **kwargs):
|
||
if "y_int" in kwargs and "x_int" in kwargs:
|
||
emb = discord.Embed(title="Рандомное число")
|
||
emb.add_field(name="От", value=kwargs["x_int"], inline=True)
|
||
emb.add_field(name="До", value=kwargs["y_int"], inline=True)
|
||
emb.add_field(name="**Результат**", value=locale.format_string('**%d**', random.randint(kwargs["x_int"], kwargs["y_int"]), grouping=True), inline=False)
|
||
elif "x_int" in kwargs:
|
||
emb = discord.Embed(title="Рандомное число")
|
||
emb.add_field(name="От", value="0", inline=True)
|
||
emb.add_field(name="До", value=kwargs["x_int"], inline=True)
|
||
emb.add_field(name="**Результат**", value=locale.format_string('**%d**', random.randint(0, kwargs["x_int"]), grouping=True), inline=False)
|
||
else:
|
||
emb = discord.Embed(title="Рандомное число")
|
||
emb.add_field(name="От", value="0", inline=True)
|
||
emb.add_field(name="До", value="10", inline=True)
|
||
emb.add_field(name="**Результат**", value=locale.format_string('**%d**', random.randint(0, 10), grouping=True), inline=False)
|
||
|
||
await ctx.send(embed=emb)
|
||
|
||
# , permissions={
|
||
# 747583006322983053:[
|
||
# create_permission(747583006322983053, discord_slash.model.SlashCommandPermissionType.ROLE, False),
|
||
# create_permission(747879784364769331, discord_slash.model.SlashCommandPermissionType.ROLE, True)
|
||
# ]
|
||
#}
|
||
@slash.slash(name="debug", description="Позволяет узнать состояние бота", options=[
|
||
create_option(name="applet", description="Название конкретной штуки, информацию о которой надо узнать", option_type=3, required=True, choices=[
|
||
create_choice(name="Общая информация", value="default"),
|
||
create_choice(name="Антиспам система", value="spam"),
|
||
create_choice(name="Cчётчики", value="counters"),
|
||
create_choice(name="Время работы бота", value="uptime")
|
||
])
|
||
])
|
||
async def deb(ctx, applet):
|
||
if applet == "default":
|
||
await ctx.send(debug())
|
||
elif applet == "spam":
|
||
answer = f"**Работа антиспам системы**\nДанный массив - то, как видит ситуацию антиспам система бота. На уровне *{data['bot-data'][str(ctx.guild.id)]['flood_limit']}* или выше - выдаёт мут на 1 день.\n"
|
||
for u in USERS_FLOOD_COUNTER[str(ctx.guild.id)]:
|
||
member = ctx.guild.get_member(u)
|
||
answer += f"\n{member} - {USERS_FLOOD_COUNTER[str(ctx.guild.id)][u]}"
|
||
await ctx.send(answer)
|
||
elif applet == "counters":
|
||
await ctx.send(counters_print())
|
||
elif applet == "uptime":
|
||
await ctx.send(uptime_rate())
|
||
|
||
@slash.slash(name="stats", description="Бот отправит информацию о набранных очках актива", options=[
|
||
create_option(name="choice", description=" Количество очков актива чего вам нужно узнать?", option_type=3, required=True, choices=[
|
||
create_choice(name="Обо мне", value="me"),
|
||
create_choice(name="О сервере", value="server"),
|
||
create_choice(name="Таблица серверов", value="all servers")
|
||
])
|
||
])
|
||
async def stats(ctx, choice):
|
||
if choice == "me":
|
||
await get_image_stats(ctx)
|
||
await ctx.send(file=discord.File("stats.png"))
|
||
elif choice == "server":
|
||
await get_image_stats_all(ctx)
|
||
await ctx.send(file=discord.File("stats_all.png"))
|
||
elif choice == "all servers":
|
||
await get_image_stats_all_guilds(ctx)
|
||
await ctx.send(file=discord.File("stats_all_guilds.png"))
|
||
|
||
@slash.slash(name="slap", description="Шлёпнуть кого-нибудь))))))", options=[
|
||
create_option(name="user", description="Выберите пользователя для шлепка, иначе будет выбран рандомный", option_type=6, required=False)
|
||
])
|
||
async def slap(ctx, **kwargs):
|
||
guy = kwargs['user'] if "user" in kwargs else random.choice(ctx.guild.members)
|
||
await ctx.send(f"{ctx.author.mention} шлёпнул {guy.mention}")
|
||
|
||
@slash.slash(name="gift", description="Подарить либо мешочек с нихуя, либо мут от 1 секунды до 2 часов")
|
||
async def new_year_present(ctx):
|
||
START_TIME = 1638835200
|
||
END_TIME = 1641513600
|
||
dt_now = datetime.datetime.utcnow()
|
||
now = dt_now.timestamp()
|
||
global NEW_YEAR_STATS
|
||
global NEW_YEAR_NOTIFYED
|
||
if not NEW_YEAR_STATS.get(str(ctx.guild.id)):
|
||
NEW_YEAR_STATS[str(ctx.guild.id)] = {'cooldown': START_TIME, "times_used": {}, "type_used":{"ban": 0, "not_ban": 0}, "victums": {}, "longest_mute":None, "shortest_mute":None}
|
||
if NEW_YEAR_STATS[str(ctx.guild.id)]["cooldown"] <= now:
|
||
victim = random.choice(ctx.guild.members)
|
||
mute = random.randint(0, 1)
|
||
if mute:
|
||
reason = "Новогодний подарок"
|
||
for_ban = victim
|
||
if data['bot-data'][str(ctx.guild.id)].get('mute_role'):
|
||
role = utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['mute_role'])
|
||
await for_ban.add_roles(role)
|
||
mute_time = random.randint(1, 7200)
|
||
data['bot-data'][str(ctx.guild.id)]['muted'][str(for_ban.id)] = {"timestamp": now + mute_time, "reason": reason, "by_id": ctx.author.id, "done": now}
|
||
emb = discord.Embed(description=f"От <@{ctx.author.id}> рандомному персонажу на сервере, которым оказался <@{for_ban.id}>\n**Подарок:** молчалка сроком {strfdelta(datetime.datetime.utcfromtimestamp(now + mute_time), dt_now, False)}", title=f"Новогодний подарок", timestamp=datetime.datetime.fromtimestamp(now + mute_time), colour=0x0000ff)
|
||
emb.set_author(name=f"{for_ban.name} (Ник: {for_ban.nick})", icon_url=for_ban.avatar_url)
|
||
emb.set_footer(text="Действует до")
|
||
else:
|
||
emb = discord.Embed(description=f"От <@{ctx.author.id}> рандомному персонажу на сервере, которым оказался <@{victim.id}>\n**Подарок:** мешочек с нихуя", title=f"Новогодний подарок", colour=0x0000ff, image="https://sun9-41.userapi.com/impf/c849128/v849128784/b0a1/GXEDUAUp-3A.jpg?size=200x200&quality=96&sign=3bb33aaba78a34581f46ed63e11c4725&type=album")
|
||
emb.set_author(name=f"{victim.name} (Ник: {victim.nick})", icon_url=victim.avatar_url)
|
||
|
||
if not NEW_YEAR_STATS[str(ctx.guild.id)]["times_used"].get(str(ctx.author.id)):
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["times_used"][str(ctx.author.id)] = 1
|
||
else:
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["times_used"][str(ctx.author.id)] += 1
|
||
if not NEW_YEAR_STATS[str(ctx.guild.id)]["victums"].get(str(victim.id)):
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["victums"][str(victim.id)] = 1
|
||
else:
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["victums"][str(victim.id)] += 1
|
||
if mute:
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["type_used"]["ban"] += 1
|
||
if NEW_YEAR_STATS[str(ctx.guild.id)]["longest_mute"] == None or NEW_YEAR_STATS[str(ctx.guild.id)]["longest_mute"][0] < mute_time:
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["longest_mute"] = [mute_time, victim.id, ctx.author.id]
|
||
if NEW_YEAR_STATS[str(ctx.guild.id)]["shortest_mute"] == None or NEW_YEAR_STATS[str(ctx.guild.id)]["shortest_mute"][0] > mute_time:
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["shortest_mute"] = [mute_time, victim.id, ctx.author.id]
|
||
else:
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["type_used"]["not_ban"] += 1
|
||
|
||
if (dt_now.day == 31 and dt_now.month == 12) or (dt_now.day == 1 and dt_now.month == 1):
|
||
cooldown = now + 900
|
||
text_cd = "Команда снова будет доступна через 15 минут"
|
||
elif dt_now.day == 30 and dt_now.month == 12:
|
||
cooldown = now + 3600
|
||
text_cd = "Команда снова будет доступна через 60 минут"
|
||
elif dt_now.day >= 25 and dt_now.month == 12:
|
||
cooldown = now + 7200
|
||
text_cd = "Команда снова будет доступна через 2 часа"
|
||
elif dt_now.day >= 20 and dt_now.month == 12:
|
||
cooldown = now + 10800
|
||
text_cd = "Команда снова будет доступна через 3 часа"
|
||
elif dt_now.day >= 15 and dt_now.month == 12:
|
||
cooldown = now + 14400
|
||
text_cd = "Команда снова будет доступна через 4 часа"
|
||
elif dt_now.day >= 10 and dt_now.month == 12:
|
||
cooldown = now + 18000
|
||
text_cd = "Команда снова будет доступна через 5 часов"
|
||
elif dt_now.day >= 7 and (dt_now.month == 12 or dt_now.month == 1):
|
||
cooldown = now + 21600
|
||
text_cd = "Команда снова будет доступна через 6 часов"
|
||
if cooldown >= END_TIME:
|
||
text_cd += ". Это будет последний подарок"
|
||
else:
|
||
cooldown = datetime.datetime(dt_now.year, 12, 7).timestamp()
|
||
text_cd = f'Ивент завершён. Статистика за {dt_now.year-1}-{dt_now.year} года:\nВсего было подарков: {NEW_YEAR_STATS[str(ctx.guild.id)]["type_used"]["ban"]+NEW_YEAR_STATS[str(ctx.guild.id)]["type_used"]["not_ban"]}, из которых было молчалок: {NEW_YEAR_STATS[str(ctx.guild.id)]["type_used"]["ban"]}, мешочков с нихуя: {NEW_YEAR_STATS[str(ctx.guild.id)]["type_used"]["not_ban"]}'
|
||
NEW_YEAR_STATS[str(ctx.guild.id)]["cooldown"] = cooldown
|
||
await ctx.send(f"Держи, {victim.mention}. {text_cd}", embed=emb)
|
||
data['bot-data']["new_year_event"] = NEW_YEAR_STATS
|
||
with open("data.json", "w") as jsn:
|
||
json.dump(data, jsn)
|
||
NEW_YEAR_NOTIFYED[str(ctx.guild.id)] = False
|
||
else:
|
||
await ctx.send(f"Новый сюрприз можно будет устроить через {strfdelta(datetime.datetime.fromtimestamp(NEW_YEAR_STATS[str(ctx.guild.id)]['cooldown']), dt_now, False)}", delete_after=15)
|
||
|
||
@slash.slash(name="settings", description="Настройте бота на вашем сервере", options=[
|
||
create_option(name="setting", description="Выберите необходимую настройку", option_type=3, required=True, choices=[
|
||
create_choice(name="Роль доступа к боту", value="access_role"),
|
||
create_choice(name="Канал уведомлений", value="notify_channel"),
|
||
create_choice(name="Дни в отображении разницы времени", value="days_in_timedelta"),
|
||
create_choice(name="Роль мута", value="mute_role"),
|
||
create_choice(name="Лимит антифлуд системы", value="flood_limit"),
|
||
create_choice(name="Бан командой", value="can_ban"),
|
||
create_choice(name="Реагировать на приход/уход участников", value="join_leave"),
|
||
create_choice(name="Шаблон приветствия нового пользователя", value="hi_msg"),
|
||
create_choice(name="Роль верификации", value="role_for_verification"),
|
||
create_choice(name="Канал для лога событий сервера", value="admin_log"),
|
||
create_choice(name="Список ролей за актив", value="active_roles"),
|
||
create_choice(name="Список требований за роли актива", value="active_for_roles"),
|
||
create_choice(name="Канал для счёта", value="counting"),
|
||
create_choice(name="Список ролей в канале счёта", value="roles_for_count")
|
||
]),
|
||
create_option(name="value", description="Укажите, чтобы изменить настройку, иначе бот отправит значение настройки", option_type=3, required=False)
|
||
])
|
||
async def sett(ctx, **kwargs): # sourcery skip: merge-else-if-into-elif
|
||
if can_use_it(ctx.author, ctx.guild.id):
|
||
if kwargs['setting'] == "access_role":
|
||
if "value" in kwargs:
|
||
if kwargs['value'].lower() == "clear":
|
||
if data['bot-data'][str(ctx.guild.id)].get("role_access"):
|
||
del data['bot-data'][str(ctx.guild.id)]['role_access']
|
||
await ctx.send(f"Особый доступ к боту будете иметь только вы")
|
||
else:
|
||
try:
|
||
data['bot-data'][str(ctx.guild.id)]['role_access'] = int(kwargs['value'])
|
||
await ctx.send(f"Роль {utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['role_access']).mention} будет использоваться для доступа к боту.")
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("role_access"):
|
||
await ctx.send(f"Особый доступ к боту есть только у {ctx.author}\nЧтобы установить роль с особым доступом, напишите её id в аргументе *value*")
|
||
else:
|
||
await ctx.send(f"Особый досуп к боту имеют все, у кого есть роль \"{utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['role_access'])}\"\nЧтобы установить роль с особым доступом, напишите её id в аргументе *value*\n Чтобы удалить роль, в аргументе *value* напишите \"clear\"")
|
||
elif kwargs["setting"] == "notify_channel":
|
||
if "value" in kwargs:
|
||
if kwargs["value"].lower() == "clear":
|
||
del data['bot-data'][str(ctx.guild.id)]['notify_channel']
|
||
await ctx.send(f"Уведомления о размуте, разбане и повышении роли выключены")
|
||
else:
|
||
try:
|
||
data['bot-data'][str(ctx.guild.id)]['notify_channel'] = int(kwargs['value'])
|
||
await ctx.send(f"Канал {utils.get(ctx.guild.channels, id=data['bot-data'][str(ctx.guild.id)]['notify_channel'])} будет использоваться для уведомлений о размуте, разбане и повышении роли")
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("notify_channel"):
|
||
await ctx.send(f"Канал для уведомлений о размуте, разбане и повышении роли не указан\nЧтобы включить, напишите его id в аргументе *value*")
|
||
else:
|
||
await ctx.send(f"Канал для уведомлений о размуте, разбане и повышении роли: {utils.get(ctx.guild.channels, id=data['bot-data'][str(ctx.guild.id)]['notify_channel'])}\nЧтобы изменить канал для админ-лога, напишите его id в аргументе *value*\nЧтобы выключить админ-лог, в аргументе *value* напишите \"clear\"")
|
||
elif kwargs["setting"] == "days_in_timedelta":
|
||
if "value" in kwargs:
|
||
if kwargs["value"] in STRING_TRUE:
|
||
data['bot-data'][str(ctx.guild.id)]['days_in_timedelta'] = True
|
||
await ctx.send(f"Формат разницы времени: *дни* дн. *часы*:*минуты*:*секунды*")
|
||
elif kwargs["value"] in STRING_FALSE:
|
||
data['bot-data'][str(ctx.guild.id)]['days_in_timedelta'] = False
|
||
await ctx.send(f"Формат разницы времени: *дни в часах+часы*:*минуты*:*секунды*")
|
||
else:
|
||
await ctx.send(f"Некорректное значение", delete_after=10)
|
||
else:
|
||
await ctx.send(f"Флаг формата разницы времени: {data['bot-data'][str(ctx.guild.id)]['days_in_timedelta']}\nЧтобы изменить, укажите в аргументе *value* булево значение (True или False)")
|
||
elif kwargs["setting"] == "mute_role":
|
||
if "value" in kwargs:
|
||
if kwargs['value'].lower() == "clear":
|
||
if data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
del data['bot-data'][str(ctx.guild.id)]['mute_role']
|
||
await ctx.send(f"Молчалка отключена")
|
||
else:
|
||
try:
|
||
data['bot-data'][str(ctx.guild.id)]['mute_role'] = int(kwargs['value'])
|
||
await ctx.send(f"Роль {utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['mute_role']).mention} будет использоваться для молчалки.")
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
await ctx.send(f"Молчалка отключена\nЧтобы включить, напишите id роли, которая запрещает отправлять сообщения, в аргументе *value*")
|
||
else:
|
||
await ctx.send(f"Роль молчалки: \"{utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['mute_role'])}\"\nЧтобы изменить роль молчалки, напишите id роли, которая запрещает отправлять сообщения, в аргументе *value*\n Чтобы удалить роль, в аргументе *value* напишите \"clear\"")
|
||
elif kwargs["setting"] == "flood_limit":
|
||
if not data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
await ctx.send("Молчалка отключена\nОна нужна в качестве наказания за флуд")
|
||
elif "value" in kwargs:
|
||
try:
|
||
if int(kwargs['value']) > 0:
|
||
data['bot-data'][str(ctx.guild.id)]['flood_limit'] = int(kwargs['value'])
|
||
await ctx.send(f"Лимит на флуд: {data['bot-data'][str(ctx.guild.id)]['flood_limit']} одинаковых/быстро отправленных сообщений подряд")
|
||
elif int(kwargs['value']) == 0:
|
||
del data['bot-data'][str(ctx.guild.id)]['flood_limit']
|
||
await ctx.send("Лимит на флуд выключен")
|
||
else:
|
||
await ctx.send("Лимит должен быть больше нуля или ноль, если хотите выключить", delete_after=10)
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get('flood_limit'):
|
||
await ctx.send("Наказание отключено\nЧтобы включить, укажите в аргументе *value*, сколько сообщений флуда можно написать перед полученем наказания")
|
||
else:
|
||
await ctx.send(f"Лимит анти-флуд системы: {data['bot-data'][str(ctx.guild.id)]['flood_limit']} одинаковых/быстро отправленных сообщений\nЧтобы изменить, укажите в аргументе *value*, сколько сообщений флуда можно написать перед полученем наказания, или 0, чтобы отключить систему")
|
||
elif kwargs["setting"] == "can_ban":
|
||
if "value" in kwargs:
|
||
if kwargs["value"] in STRING_TRUE:
|
||
data['bot-data'][str(ctx.guild.id)]['can_ban'] = True
|
||
await ctx.send(f"Теперь можно банить людей через команду `/ban`")
|
||
elif kwargs["value"] in STRING_FALSE:
|
||
data['bot-data'][str(ctx.guild.id)]['can_ban'] = False
|
||
await ctx.send(f"Команда `/ban` выключена")
|
||
else:
|
||
await ctx.send(f"Некорректное значение", delete_after=10)
|
||
else:
|
||
await ctx.send(f"Можно банить через команду бота: {data['bot-data'][str(ctx.guild.id)]['can_ban']}\nЧтобы изменить, укажите в аргументе *value* булево значение (True или False)")
|
||
elif kwargs["setting"] == "join_leave":
|
||
if "value" in kwargs:
|
||
if kwargs["value"] in STRING_TRUE:
|
||
data['bot-data'][str(ctx.guild.id)]['react_on_join_leave_members'] = True
|
||
await ctx.send(f"Бот будет реагировать на приход/уход участников")
|
||
elif kwargs["value"] in STRING_FALSE:
|
||
data['bot-data'][str(ctx.guild.id)]['react_on_join_leave_members'] = False
|
||
await ctx.send(f"Бот не будет реагировать на приход/уход участников")
|
||
else:
|
||
await ctx.send(f"Некорректное значение", delete_after=10)
|
||
else:
|
||
await ctx.send(f"Реагировать на приход на сервер и уход с него участников: {data['bot-data'][str(ctx.guild.id)]['react_on_join_leave_members']}\nЧтобы изменить, укажите в аргументе *value* булево значение (True или False)")
|
||
elif kwargs["setting"] == "hi_msg":
|
||
if "value" in kwargs:
|
||
if kwargs["value"].lower() == "clear":
|
||
del data['bot-data'][str(ctx.guild.id)]['hi_msg']
|
||
await ctx.send("Будет использоваться стандартный шаблон приветствия")
|
||
else:
|
||
data['bot-data'][str(ctx.guild.id)]['hi_msg'] = kwargs["value"]
|
||
await ctx.send(f"Новый шаблон приветствия: {data['bot-data'][str(ctx.guild.id)]['hi_msg']}")
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get('hi_msg'):
|
||
await ctx.send(f"Используется стандартный шаблон приветствия\nЧтобы изменить, в аргументе *value* напишите шаблон сообщения. В нём могут быть такие элементы, как `%user_mention` (упоминание новичка) и `%full_username` (полный ник новичка)")
|
||
else:
|
||
await ctx.send(f"Шаблон приветствия: {data['bot-data'][str(ctx.guild.id)]['hi_msg']}\nЧтобы изменить, в аргументе *value* напишите шаблон сообщения. В нём могут быть такие элементы, как `%user_mention` (упоминание новичка) и `%full_username` (полный ник новичка)\nЕсли он больше не нужен, после аргумента напишите \"clear\"")
|
||
elif kwargs["setting"] == "role_for_verification":
|
||
if "value" in kwargs:
|
||
if kwargs['value'].lower() == "clear":
|
||
if data['bot-data'][str(ctx.guild.id)].get("role_for_verification"):
|
||
del data['bot-data'][str(ctx.guild.id)]['role_for_verification']
|
||
await ctx.send(f"Верификация отключена")
|
||
else:
|
||
try:
|
||
data['bot-data'][str(ctx.guild.id)]['role_for_verification'] = int(kwargs['value'])
|
||
await ctx.send(f"Роль {utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['role_for_verification'])} будет использоваться для верификации.")
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("role_for_verification"):
|
||
await ctx.send(f"Верификация отключена\nЧтобы включить, напишите id роли верификации в аргументе *value*")
|
||
else:
|
||
await ctx.send(f"Роль верификации: \"{utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['role_for_verification']).name}\"\nЧтобы изменить роль верификации, напишите её id в аргументе *value*\nЧтобы выключить верификацию, в аргументе *value* напишите \"clear\"")
|
||
elif kwargs["setting"] == "admin_log":
|
||
if "value" in kwargs:
|
||
if kwargs["value"].lower() == "clear":
|
||
del data['bot-data'][str(ctx.guild.id)]['admin_log']
|
||
await ctx.send(f"Уведомления о размуте, разбане и повышении роли выключены")
|
||
else:
|
||
try:
|
||
data['bot-data'][str(ctx.guild.id)]['admin_log'] = int(kwargs['value'])
|
||
await ctx.send(f"Канал {utils.get(ctx.guild.channels, id=data['bot-data'][str(ctx.guild.id)]['admin_log'])} будет использоваться для уведомлений о размуте, разбане и повышении роли")
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("admin_log"):
|
||
await ctx.send(f"Канал админ-лога не указан\nЧтобы включить, напишите id канала для админ-лога в аргументе *value*")
|
||
else:
|
||
await ctx.send(f"Канал админ-лога: \"{utils.get(ctx.guild.channels, id=data['bot-data'][str(ctx.guild.id)]['admin_log'])}\"\nЧтобы изменить канал для админ-лога, напишите его id в аргументе *value*\nЧтобы выключить админ-лог, в аргументе *value* напишите \"clear\"")
|
||
elif kwargs["setting"] == "active_roles":
|
||
if "value" in kwargs:
|
||
lst = kwargs["value"].split(" ")
|
||
try:
|
||
for l in lst:
|
||
int(l)
|
||
data['bot-data'][str(ctx.guild.id)]['roles'] = lst
|
||
answer = "Новый порядок ролей:"
|
||
for role in data['bot-data'][str(ctx.guild.id)]['roles']:
|
||
answer += f" <@&{role}>"
|
||
if data['bot-data'][str(ctx.guild.id)].get('active_roles'):
|
||
if len(data['bot-data'][str(ctx.guild.id)]['roles']) != len(data['bot-data'][str(ctx.guild.id)]['active_roles']):
|
||
answer += "\nРекомендую также изменить требуемый актив за роли, так как кол-во ролей и требований за них не совпадает"
|
||
else:
|
||
answer += "\nРекомендую также изменить награды за актив, так как они не назначены"
|
||
await ctx.send(answer)
|
||
except Exception as e:
|
||
await ctx.send(f"Ошибка\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("roles"):
|
||
await ctx.send("Роли за актив не установлены\nЧтобы это сделать, в аргументе *value* напишите id ролей по очереди, от самой менее значимой до самой крутой роли за актив через пробел")
|
||
else:
|
||
answer = "Порядок ролей:"
|
||
for role in data['bot-data'][str(ctx.guild.id)]['roles']:
|
||
answer += f" <@&{role}>"
|
||
answer +="\nЧтобы изменить, в аргументе *value* напишите id ролей по очереди, от самой менее значимой до самой крутой роли за актив через пробел\nЛибо после аргумента напишите \"clear\""
|
||
await ctx.send(answer)
|
||
elif kwargs["setting"] == "active_for_roles":
|
||
if not data['bot-data'][str(ctx.guild.id)].get("roles"):
|
||
await ctx.send("Роли за актив не установлены\nИспользуйте `/settings setting:Список ролей за актив` чтобы узнать подробнее")
|
||
elif "value" in kwargs:
|
||
lst = kwargs["value"].split(" ")
|
||
try:
|
||
for l in lst:
|
||
int(l)
|
||
data['bot-data'][str(ctx.guild.id)]['active_roles'] = lst
|
||
answer = "Требуемый вами актив:"
|
||
for n in data['bot-data'][str(ctx.guild.id)]['active_roles']:
|
||
answer += f" {n}"
|
||
await ctx.send(answer)
|
||
except Exception as e:
|
||
await ctx.send(f"Ошибка\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("active_roles"):
|
||
await ctx.send("Требования для ролей за актив не установлены\nЧтобы это сделать, напишите в аргументе *value* требуемый актив за роли по очереди через пробел, от самой менее значимой до самой крутой роли за актив")
|
||
else:
|
||
answer = "Требуемый актив за роли:"
|
||
for role in data['bot-data'][str(ctx.guild.id)]['active_roles']:
|
||
answer += f" {role}"
|
||
answer +="\nЧтобы изменить, напишите в аргументе *value* требуемый актив за роли по очереди через пробел, от самой менее значимой до самой крутой роли за актив\nЛибо после аргумента напишите \"clear\""
|
||
await ctx.send(answer)
|
||
elif kwargs["setting"] == "counting":
|
||
if "value" in kwargs:
|
||
if kwargs["value"].lower() == "clear":
|
||
del data['bot-data'][str(ctx.guild.id)]['count_log']
|
||
await ctx.send(f"Бот теперь не следит за счётом в этом канале")
|
||
else:
|
||
try:
|
||
data['bot-data'][str(ctx.guild.id)]['count_log'] = int(kwargs['value'])
|
||
await ctx.send(f"Канал {utils.get(ctx.guild.channels, id=data['bot-data'][str(ctx.guild.id)]['count_log'])} будет использоваться для счёта\nСледующее число: {data['bot-data'][str(ctx.guild.id)]['count_channel']}")
|
||
except Exception as e:
|
||
await ctx.send(f"Некорректное значение\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("count_log"):
|
||
await ctx.send(f"Канал для счёта не установлен.\nЧтобы включить, напишите id канала для админ-лога в аргументе *value*")
|
||
else:
|
||
await ctx.send(f"Канал для счёта: \"{utils.get(ctx.guild.channels, id=data['bot-data'][str(ctx.guild.id)]['count_log'])}\"\nЧтобы изменить канал для админ-лога, напишите его id в аргументе *value*\nЧтобы выключить админ-лог, в аргументе *value* напишите \"clear\"")
|
||
elif kwargs["setting"] == "roles_for_count":
|
||
if not data['bot-data'][str(ctx.guild.id)].get("count_log"):
|
||
await ctx.send("Канал для счёта не установлен.\nИспользуйте `/settings setting:Канал для счёта` чтобы узнать подробнее")
|
||
elif "value" in kwargs:
|
||
lst = kwargs["value"].split(" ")
|
||
try:
|
||
for l in lst:
|
||
int(l)
|
||
data['bot-data'][str(ctx.guild.id)]['roles'] = lst
|
||
answer = "Новый порядок ролей:"
|
||
for role in data['bot-data'][str(ctx.guild.id)]['roles']:
|
||
answer += f" <@&{role}>"
|
||
await ctx.send(answer)
|
||
except Exception as e:
|
||
await ctx.send(f"Ошибка\n\n`{e}`", delete_after=10)
|
||
else:
|
||
if not data['bot-data'][str(ctx.guild.id)].get("active_roles"):
|
||
await ctx.send("Роли для канала счёта не установлны\nЧтобы это сделать, напишите в аргументе *value* id ролей по порядку за число 100, 500, круглое число с 3 нолями на конце и круглое число с 4 нолями на конце")
|
||
else:
|
||
answer = "Требуемый актив за роли:"
|
||
for role in data['bot-data'][str(ctx.guild.id)]['active_roles']:
|
||
answer += f" {role}"
|
||
answer +="\nЧтобы изменить, напишите в аргументе *value* id ролей по порядку за число 100, 500, круглое число с 3 нолями на конце и круглое число с 4 нолями на конце\nЛибо после аргумента напишите \"clear\""
|
||
await ctx.send(answer)
|
||
else:
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
|
||
|
||
@slash.slash(name="mute", description="Лишить кого-нибудь права отправлять сообщения на определённый срок", options=[
|
||
create_option(name="user", description="Пользователь, в отношении которого будет применена санкция", option_type=6, required=True),
|
||
create_option(name="term", description="Либо срок в формате <int>[s, m, h, d, w], либо дата в формате DD.MM.YYYY", option_type=3, required=True),
|
||
create_option(name="reason", description="Причина приминения санкции", option_type=3, required=False)
|
||
])
|
||
async def mute(ctx, **kwargs):
|
||
if not can_use_it(ctx.author, ctx.guild.id):
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
return
|
||
if not data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
await ctx.send("Команда отключена", delete_after=10)
|
||
return
|
||
try:
|
||
if re.search(r"\d\d\.\d\d.\d\d\d\d", kwargs["term"]) and datetime.datetime.strptime(kwargs["term"], "%d.%m.%Y") >= datetime.datetime.utcnow():
|
||
mute_time = datetime.datetime.strptime(kwargs["term"], "%d.%m.%Y")
|
||
elif (
|
||
kwargs["term"][-1:] in ["s", "m", "h", "d", "w"]
|
||
and int(kwargs["term"][:-1]) > 0
|
||
):
|
||
valve_time_ban = int(kwargs["term"][:-1])
|
||
type_time_ban = kwargs["term"][-1:]
|
||
now = datetime.datetime.utcnow()
|
||
if type_time_ban == "s":
|
||
mute = datetime.timedelta(seconds=valve_time_ban)
|
||
elif type_time_ban == "m":
|
||
mute = datetime.timedelta(minutes=valve_time_ban)
|
||
elif type_time_ban == "h":
|
||
mute = datetime.timedelta(hours=valve_time_ban)
|
||
elif type_time_ban == "d":
|
||
mute = datetime.timedelta(days=valve_time_ban)
|
||
elif type_time_ban == "w":
|
||
mute = datetime.timedelta(weeks=valve_time_ban)
|
||
mute_time = now + mute
|
||
else:
|
||
await ctx.send(f"Неправильное значения аргумента `term`: `{kwargs['term']}`", delete_after=10)
|
||
return
|
||
reason = kwargs["reason"] if "reason" in kwargs else "Не указана"
|
||
for_ban = kwargs["user"]
|
||
role = utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['mute_role'])
|
||
await for_ban.add_roles(role)
|
||
data['bot-data'][str(ctx.guild.id)]['muted'][str(for_ban.id)] = {"timestamp": mute_time.timestamp(), "reason": reason, "by_id": ctx.author.id, "done": datetime.datetime.utcnow().timestamp()}
|
||
emb = discord.Embed(description=f"От <@{ctx.author.id}> специально для <@{for_ban.id}>\n**Причина:** {reason}\n**Срок молчалки:** {strfdelta(now+mute, now, data['bot-data'][str(ctx.guild.id)]['days_in_timedelta'])}", title=f"Молчалка", timestamp=mute_time, colour=0x0000ff)
|
||
emb.set_author(name=f"{for_ban.name} (Ник: {for_ban.nick})", icon_url=for_ban.avatar_url)
|
||
emb.set_footer(text="Действует до")
|
||
await ctx.send(embed=emb)
|
||
except Exception as e:
|
||
await ctx.send(f"Я сломался: `{e}`", delete_after=10)
|
||
|
||
|
||
@slash.slash(name="ban", description="Лишить кого-нибудь права быть на этом сервере на определённый срок", options=[
|
||
create_option(name="user", description="Пользователь, в отношении которого будет применена санкция", option_type=6, required=True),
|
||
create_option(name="term", description="Либо срок в формате <int>[s, m, h, d, w], либо дата в формате DD.MM.YYYY", option_type=3, required=True),
|
||
create_option(name="reason", description="Причина приминения санкции", option_type=3, required=False)
|
||
])
|
||
async def ban(ctx, **kwargs):
|
||
if not can_use_it(ctx.author, ctx.guild.id):
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
return
|
||
if not data['bot-data'][str(ctx.guild.id)]["can_ban"]:
|
||
await ctx.send("Команда отключена", delete_after=10)
|
||
return
|
||
try:
|
||
if re.search(r"\d\d\.\d\d.\d\d\d\d", kwargs["term"]) and datetime.datetime.strptime(kwargs["term"], "%d.%m.%Y") >= datetime.datetime.utcnow():
|
||
mute_time = datetime.datetime.strptime(kwargs["term"], "%d.%m.%Y")
|
||
elif (
|
||
kwargs["term"][-1:] in ["s", "m", "h", "d", "w"]
|
||
and int(kwargs["term"][:-1]) > 0
|
||
):
|
||
valve_time_ban = int(kwargs["term"][:-1])
|
||
type_time_ban = kwargs["term"][-1:]
|
||
now = datetime.datetime.utcnow()
|
||
if type_time_ban == "s":
|
||
mute = datetime.timedelta(seconds=valve_time_ban)
|
||
elif type_time_ban == "m":
|
||
mute = datetime.timedelta(minutes=valve_time_ban)
|
||
elif type_time_ban == "h":
|
||
mute = datetime.timedelta(hours=valve_time_ban)
|
||
elif type_time_ban == "d":
|
||
mute = datetime.timedelta(days=valve_time_ban)
|
||
elif type_time_ban == "w":
|
||
mute = datetime.timedelta(weeks=valve_time_ban)
|
||
mute_time = now + mute
|
||
else:
|
||
await ctx.send(f"Неправильное значения аргумента `term`: `{kwargs['term']}`", delete_after=10)
|
||
return
|
||
reason = kwargs["reason"] if "reason" in kwargs else "Не указана"
|
||
for_ban = kwargs["user"]
|
||
await for_ban.ban(reason=reason)
|
||
data['bot-data'][str(ctx.guild.id)]['banned'][str(for_ban.id)] = {"timestamp": mute_time.timestamp(), "reason": reason, "by_id": ctx.author.id, "done": datetime.datetime.utcnow().timestamp()}
|
||
emb = discord.Embed(description=f"<@{ctx.author.id}> бьёт <@{for_ban.id}> банхаммером\n**Причина:** {reason}\n**Срок бана:** {strfdelta(now+mute, now, data['bot-data'][str(ctx.guild.id)]['days_in_timedelta'])}", title="Бан", timestamp=mute_time, colour=0x0000ff)
|
||
emb.set_author(name=f"{for_ban.name} (Ник: {for_ban.nick})", icon_url=for_ban.avatar_url)
|
||
emb.set_footer(text="Действует до")
|
||
await ctx.send(embed=emb)
|
||
except Exception as e:
|
||
await ctx.send(f"Я сломался: `{e}`", delete_after=10)
|
||
|
||
|
||
@slash.slash(name="unmute", description="Вернуть кому-нибудь право отправлять сообщения", options=[
|
||
create_option(name="user", description="Пользователь, в отношении которого будет снята санкция", option_type=6, required=True)
|
||
])
|
||
async def unmute(ctx, user):
|
||
if not can_use_it(ctx.author, ctx.guild.id):
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
return
|
||
if not data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
await ctx.send("Команда отключена", delete_after=10)
|
||
return
|
||
try:
|
||
for u in data['bot-data'][str(ctx.guild.id)]['muted']:
|
||
if int(u) == user.id:
|
||
role = utils.get(ctx.guild.roles, id=data['bot-data'][str(ctx.guild.id)]['mute_role'])
|
||
await user.remove_roles(role)
|
||
await ctx.send(f"Молчалка снята с {user.mention}")
|
||
del data['bot-data'][str(ctx.guild.id)]['muted'][u]
|
||
return
|
||
await ctx.send(f"У пользователя нет молчалки", delete_after=10)
|
||
except Exception as e:
|
||
await ctx.send(f"Я сломался: `{e}`", delete_after=10)
|
||
|
||
|
||
@slash.slash(name="unban", description="Вернуть кому-нибудь право быть на этом сервере", options=[
|
||
create_option(name="userid", description="ID пользователя, в отношении которого будет снята санкция", option_type=4, required=True)
|
||
])
|
||
async def unban(ctx, userID):
|
||
if not can_use_it(ctx.author, ctx.guild.id):
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
return
|
||
if not data['bot-data'][str(ctx.guild.id)]["can_ban"]:
|
||
await ctx.send("Команда отключена", delete_after=10)
|
||
return
|
||
try:
|
||
for_ban = str(userID)
|
||
for u in data['bot-data'][str(ctx.guild.id)]['banned']:
|
||
if u == for_ban:
|
||
ban_list = await ctx.guild.bans()
|
||
for i in ban_list:
|
||
if i.user.id == int(u):
|
||
unban = i.user
|
||
await ctx.guild.unban(unban)
|
||
await ctx.send(f"{unban} разбанен")
|
||
del data['bot-data'][str(ctx.guild.id)]['banned'][u]
|
||
return
|
||
await ctx.send("Пользователь не найден", delete_after=10)
|
||
except Exception as e:
|
||
await ctx.send(f"Я сломался: `{e}`", delete_after=10)
|
||
|
||
|
||
@slash.slash(name="mute_list", description="Посмотреть список активных на сервере молчалок")
|
||
async def mute_list(ctx):
|
||
if not can_use_it(ctx.author, ctx.guild.id):
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
return
|
||
if not data['bot-data'][str(ctx.guild.id)].get("mute_role"):
|
||
await ctx.send("Команда отключена", delete_after=10)
|
||
return
|
||
if len(data['bot-data'][str(ctx.guild.id)]['muted']) > 0:
|
||
desc_text = f"**Активных молчалок**: {len(data['bot-data'][str(ctx.guild.id)]['muted'])}"
|
||
if len(data['bot-data'][str(ctx.guild.id)]['muted']) > 25:
|
||
desc_text += f"\n**Embed может показать только 25 строк**"
|
||
emb = discord.Embed(title="Действующие молчалки", description=desc_text, color=0x0000ff)
|
||
for_cout = sorted(data['bot-data'][str(ctx.guild.id)]['muted'], key=lambda i:data['bot-data'][str(ctx.guild.id)]['muted'][i]["timestamp"])
|
||
for u in for_cout:
|
||
unmute_time = datetime.datetime.fromtimestamp(data['bot-data'][str(ctx.guild.id)]['muted'][u]["timestamp"])
|
||
mute_time = datetime.datetime.fromtimestamp(data['bot-data'][str(ctx.guild.id)]['muted'][u]["done"])
|
||
strtimediff = strfdelta(unmute_time, datetime.datetime.utcnow(), data["bot-data"][str(ctx.guild.id)]["days_in_timedelta"])
|
||
nick = ctx.guild.get_member(int(u))
|
||
bnick = ctx.guild.get_member(int(data['bot-data'][str(ctx.guild.id)]['muted'][u]['by_id']))
|
||
if nick is None:
|
||
try:
|
||
member = requests.get(f"https://discordapp.com/api/users/{u}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'}).json()
|
||
nick = f"{member['username']}#{member['discriminator']}"
|
||
except:
|
||
nick = f"id{u}"
|
||
else:
|
||
nick = nick.display_name
|
||
if bnick is None:
|
||
try:
|
||
muted_by = requests.get(f"https://discordapp.com/api/users/{data['bot-data'][str(ctx.guild.id)]['muted'][u]['by_id']}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'}).json()
|
||
bnick = f"{muted_by['username']}#{muted_by['discriminator']}"
|
||
except:
|
||
bnick = f"id{data['bot-data'][str(ctx.guild.id)]['muted'][u]['by_id']}"
|
||
else:
|
||
bnick = bnick.display_name
|
||
emb.add_field(name=nick, value=f"**От**: {mute_time.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**До**: {unmute_time.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**Ост. срок**: {strtimediff}\n**Причина**: {data['bot-data'][str(ctx.guild.id)]['muted'][u]['reason']}\n**Выдал**: {bnick}")
|
||
await ctx.send(embed=emb)
|
||
else:
|
||
await ctx.send("Нет действующих молчалок")
|
||
|
||
|
||
@slash.slash(name="ban_list", description="Посмотреть список активныx на сервере временных банов")
|
||
async def ban_list(ctx):
|
||
if not can_use_it(ctx.author, ctx.guild.id):
|
||
await ctx.send("Вам нельзя использовать эту команду", delete_after=10)
|
||
return
|
||
if not data['bot-data'][str(ctx.guild.id)]["can_ban"]:
|
||
await ctx.send("Команда отключена", delete_after=10)
|
||
return
|
||
if len(data['bot-data'][str(ctx.guild.id)]['banned']) > 0:
|
||
emb = discord.Embed(title="Действующие баны", description=f"**Активных банов**: {len(data['bot-data'][str(ctx.guild.id)]['banned'])}", color=0x0000ff)
|
||
for u in data['bot-data'][str(ctx.guild.id)]['banned']:
|
||
unmute_time = datetime.datetime.utcfromtimestamp(data['bot-data'][str(ctx.guild.id)]['banned'][u]["timestamp"])
|
||
mute_time = datetime.datetime.fromtimestamp(data['bot-data'][str(ctx.guild.id)]['banned'][u]["done"])
|
||
strtimediff = strfdelta(unmute_time, datetime.datetime.utcnow(), data["bot-data"][str(ctx.guild.id)]["days_in_timedelta"])
|
||
nick = ctx.guild.get_member(int(u))
|
||
bnick = ctx.guild.get_member(int(data['bot-data'][str(ctx.guild.id)]['banned'][u]['by_id']))
|
||
if nick is None:
|
||
try:
|
||
member = requests.get(f"https://discordapp.com/api/users/{u}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'}).json()
|
||
nick = f"{member['username']}#{member['discriminator']}"
|
||
except:
|
||
nick = f"id{u}"
|
||
else:
|
||
nick = nick.display_name
|
||
if bnick is None:
|
||
try:
|
||
muted_by = requests.get(f"https://discordapp.com/api/users/{data['bot-data'][str(ctx.guild.id)]['banned'][u]['by_id']}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'}).json()
|
||
bnick = f"{muted_by['username']}#{muted_by['discriminator']}"
|
||
except:
|
||
bnick = f"id{data['bot-data'][str(ctx.guild.id)]['banned'][u]['by_id']}"
|
||
else:
|
||
bnick = bnick.display_name
|
||
emb.add_field(name=nick, value=f"**От**: {mute_time.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**До**: {unmute_time.strftime('%d.%m.%Y %H:%M:%S UTC')}\n**Ост. срок**: {strtimediff}\n**Причина**: {data['bot-data'][str(ctx.guild.id)]['banned'][u]['reason']}\n**Выдал**: {bnick}")
|
||
await ctx.send(embed=emb)
|
||
else:
|
||
await ctx.send("Нет действующих банов")
|
||
|
||
|
||
async def time_unmute(member_id, guild_id):
|
||
response = requests.delete(f'https://discordapp.com/api/guilds/{guild_id}/members/{member_id}/roles/{data["bot-data"][guild_id]["mute_role"]}', headers={'Authorization': f'Bot {data["main-data"]["token"]}'})
|
||
log(f"Discord API answer: {response.status_code} {response.reason}")
|
||
if response.ok and data['bot-data'][guild_id].get('notify_channel'):
|
||
await client.get_channel(data['bot-data'][guild_id]['notify_channel']).send(f"Молчалка снята с <@{member_id}>: Срок молчалки истёк")
|
||
|
||
async def ny_notif(g):
|
||
await client.get_channel(data['bot-data'][g]['notify_channel']).send(f"Новый сюрприз готов. Жду того, кто готов его вручить (/gift)")
|
||
|
||
async def time_unban(member_id, guild_id):
|
||
try:
|
||
ban_list = await client.get_guild(guild_id).bans()
|
||
for i in ban_list:
|
||
if i.user.id == int(member_id):
|
||
unban = i.user
|
||
await client.get_guild(int(guild_id)).unban(unban)
|
||
if data['bot-data'][guild_id].get('notify_channel'):
|
||
await client.get_channel(data['bot-data'][guild_id]['notify_channel']).send(f"{unban} разбанен: Срок бана истёк")
|
||
except:
|
||
member = requests.get(f"https://discordapp.com/api/users/{member_id}", headers={'Authorization': f'Bot {data["main-data"]["token"]}'})
|
||
if member.ok:
|
||
member = member.json()
|
||
if data['bot-data'][guild_id].get('notify_channel'):
|
||
await client.get_channel(data['bot-data'][guild_id]['notify_channel']).send(
|
||
f"{member['username']}#{member['discriminator']} вычеркнут из бан-листа: срок бана истёк")
|
||
else:
|
||
if data['bot-data'][guild_id].get('notify_channel'):
|
||
await client.get_channel(data['bot-data'][guild_id]['notify_channel']).send(f"id{member_id} вычеркнут из бан-листа: срок бана истёк")
|
||
|
||
vk = vk_api.VkApi(token="redacted")
|
||
vk_mda = vk_api.VkApi(token="redacted")
|
||
longpoll = VkBotLongPoll(vk, 190322075)
|
||
vkcall = vk.get_api()
|
||
|
||
async def new_post(vk_event):
|
||
group = vkcall.groups.getById(group_id=str(vk_event.object.from_id)[1:], fields='photo_200')
|
||
emb = discord.Embed(description=vk_event.object.text, url=f"https://vk.com/{group[0]['screen_name']}?w=wall-{group[0]['id']}_{vk_event.object.id}", title="Вышел новый пост", timestamp=datetime.datetime.fromtimestamp(vk_event.object.date), colour=0xF0A020)
|
||
emb.set_author(name=group[0]['name'], url=f"https://vk.com/{group[0]['screen_name']}", icon_url=group[0]['photo_200'])
|
||
if vk_event.object.attachments:
|
||
photo = False
|
||
attachments = ""
|
||
for i in vk_event.object.attachments:
|
||
try:
|
||
if i['type'] == 'photo':
|
||
attachments += f"🖼 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
if not photo:
|
||
emb.set_image(url=i['photo']['sizes'][-1]['url'])
|
||
photo = True
|
||
elif i['type'] == 'wall':
|
||
attachments += f"📰 {i['type']}{i[i['type']]['from_id']}_{i[i['type']]['id']}\n"
|
||
elif i['type'] == 'link':
|
||
attachments += f"🔗 {i['type']} {i[i['type']]['title']}\n"
|
||
elif i['type'] == 'doc':
|
||
attachments += f"📄 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
elif i['type'] == 'poll':
|
||
attachments += f"📊 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
elif i['type'] == 'album':
|
||
attachments += f"🎨 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
elif i['type'] == 'video':
|
||
attachments += f"🎞 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
elif i['type'] == 'audio':
|
||
attachments += f"🎵 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
else:
|
||
attachments += f"🎩 {i['type']}{i[i['type']]['owner_id']}_{i[i['type']]['id']}\n"
|
||
except:
|
||
attachments += f"🎩 {i['type']}\n"
|
||
emb.add_field(name="Прикреплено", value=attachments)
|
||
emb.set_footer(text=f"wall{str(vk_event.object['from_id'])}_{str(vk_event.object['id'])}")
|
||
await client.get_channel(747588017543446568).send(embed=emb)
|
||
|
||
def send(to, message=None, attachment=None):
|
||
try:
|
||
random_id = random.randint(-9223372036854775808,
|
||
9223372036854775807)
|
||
message = vk.method('messages.send',
|
||
{'peer_id': int(to), 'message': message, 'random_id': random_id,
|
||
'attachment': attachment})
|
||
counters.incriment("vk-s")
|
||
except Exception as e:
|
||
counters.incriment("e")
|
||
logging.error(f'Failed to send VK message: {str(e)}')
|
||
|
||
def vk_longpull():
|
||
for event in MyVkLongPoll.listen(longpoll):
|
||
try:
|
||
if event.type == VkBotEventType.MESSAGE_NEW:
|
||
counters.incriment("vk-r")
|
||
if event.message.text.lower() == "бот дай денег":
|
||
send(event.message.peer_id, "Иди нахуй")
|
||
if event.message.text.lower() == "бот дай денег":
|
||
send(event.message.peer_id, "Иди нахуй")
|
||
if event.message.text.lower() == "бот дай":
|
||
send(event.message.peer_id, "Мне денег")
|
||
if event.message.text.lower() == "бот иди":
|
||
send(event.message.peer_id, "Ты нахуй")
|
||
if event.message.text.lower() == "бот нахуй":
|
||
send(event.message.peer_id, "Ты иди")
|
||
if event.message.text.lower() == "бот деньги":
|
||
send(event.message.peer_id, "Мне дай")
|
||
if event.message.text.lower() == "бот иди нахуй":
|
||
from_obj = vk.method("users.get", {'user_ids': event.message.from_id})
|
||
send(event.message.peer_id, f"{from_obj[0]['first_name']}, дай денег")
|
||
if event.message.text == "!debug" and event.message.from_id == 276193568:
|
||
send(event.message.peer_id, debug())
|
||
elif event.type == VkBotEventType.WALL_POST_NEW:
|
||
if event.object.post_type == "post":
|
||
log(f"New post! id{event.object['id']}")
|
||
post = f"wall{str(event.object['from_id'])}_{str(event.object['id'])}"
|
||
send(2000000003, f"Вышел новый пост", post)
|
||
coro = new_post(event)
|
||
fut = asyncio.run_coroutine_threadsafe(coro, client.loop)
|
||
try:
|
||
fut.result()
|
||
except:
|
||
counters.incriment("e")
|
||
continue
|
||
except Exception as kek:
|
||
log(f"Беды с ботом: {str(kek)}")
|
||
continue
|
||
|
||
def bot_status():
|
||
while True:
|
||
try:
|
||
time.sleep(1)
|
||
l = round(client.latency*1000)
|
||
up = strfdelta(datetime.datetime.utcnow(), START_TIME, False, "%Hч%Mм")
|
||
asyncio.run_coroutine_threadsafe(client.change_presence(activity=discord.Game(name=f"{num4(ACTIVE_TOTAL)} актива на {len(client.guilds)} серверах (пинг {l} мс, проработал {up})")), client.loop).result()
|
||
if datetime.datetime.utcnow().second == 0:
|
||
vk_widget = {"title": "Discord бот dan63047Bot#0924",
|
||
"title_counter": ACTIVE_TOTAL,
|
||
"text": widget_temp(data['main-data']['vk_widget_text']),
|
||
"descr": f"Обслуживает серверов: {len(client.guilds)}\nАптайм: {up}\nПинг до Discord API: {l} мс."}
|
||
vk_mda.method("appWidgets.update", {"type": "text", "code": f'return {json.dumps(vk_widget, ensure_ascii=False)};'})
|
||
global NEW_YEAR_NOTIFYED
|
||
global NEW_YEAR_STATS
|
||
for g in NEW_YEAR_NOTIFYED:
|
||
if NEW_YEAR_NOTIFYED[g] is False and datetime.datetime.utcnow().timestamp() >= NEW_YEAR_STATS[g]["cooldown"]:
|
||
# coro = ny_notif(g)
|
||
# fut = asyncio.run_coroutine_threadsafe(coro, client.loop)
|
||
try:
|
||
# fut.result()
|
||
NEW_YEAR_NOTIFYED[g] = True
|
||
except:
|
||
counters.incriment("e")
|
||
continue
|
||
except Exception as e:
|
||
logging.error(f"Some activity tread shit {e}")
|
||
time.sleep(1)
|
||
continue
|
||
counters.incriment_uptime()
|
||
|
||
def bot_bans():
|
||
while True:
|
||
try:
|
||
time.sleep(1)
|
||
now = datetime.datetime.utcnow()
|
||
for g in data['bot-data']:
|
||
if g != "counters" and g != "new_year_event":
|
||
for b in data['bot-data'][g]['banned']:
|
||
if data['bot-data'][g]['banned'][b]['timestamp'] < now.timestamp():
|
||
try:
|
||
asyncio.run_coroutine_threadsafe(time_unban(b, g), client.loop).result()
|
||
del data['bot-data'][g]['banned'][b]
|
||
except:
|
||
log("Time unban shit")
|
||
except:
|
||
logging.error("Some unban tread shit")
|
||
time.sleep(1)
|
||
continue
|
||
|
||
def bot_muts():
|
||
while True:
|
||
try:
|
||
time.sleep(1)
|
||
now = datetime.datetime.utcnow()
|
||
for g in data['bot-data']:
|
||
if g != "counters" and g != "new_year_event":
|
||
for m in data['bot-data'][g]['muted']:
|
||
if data['bot-data'][g]['muted'][m]['timestamp'] < now.timestamp():
|
||
try:
|
||
asyncio.run_coroutine_threadsafe(time_unmute(m, g), client.loop).result()
|
||
del data['bot-data'][g]['muted'][m]
|
||
except:
|
||
log("Time unmute shit")
|
||
except:
|
||
logging.error("Some unmute tread shit")
|
||
time.sleep(1)
|
||
continue
|
||
|
||
try:
|
||
threading.Thread(target=vk_longpull, name=vk_longpull, daemon=True).start()
|
||
threading.Thread(target=bot_status, name=bot_status, daemon=True).start()
|
||
threading.Thread(target=bot_bans, name=bot_bans, daemon=True).start()
|
||
threading.Thread(target=bot_muts, name=bot_muts, daemon=True).start()
|
||
client.run(data['main-data']['token'])
|
||
finally:
|
||
with open("data.json", "w") as jsn:
|
||
json.dump(data, jsn)
|
||
up = strfdelta(datetime.datetime.utcnow(), START_TIME, True, "%D:%H:%M:%S")
|
||
log(f"Data saved, script ended, uptime: {up}") |