discord-vk-pythonbot/main.py

1603 lines
109 KiB
Python
Raw Normal View History

2024-05-13 13:02:44 +00:00
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, "%%"),
"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, "%%")
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}")