discord-vk-pythonbot/main.py

1603 lines
109 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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}")