Compare commits

...

4 Commits

Author SHA1 Message Date
a56a6506d6 [+] .rcon - MultiServer support 2024-01-16 01:00:59 +03:00
6fc868e48d [+] MultiServer support
[+] .bot hosts list [-a | --all]
[+] .bot hosts list
[+] .bot hosts reload
[>] Checks to bot.py
[-] LuckPerms
[~] All files in modules
[~] Config now yml
2024-01-16 00:40:01 +03:00
8a03911814 Plugins? 2024-01-15 16:34:55 +03:00
b5a982923a config/ 2024-01-15 16:34:45 +03:00
14 changed files with 561 additions and 264 deletions

1
.gitignore vendored
View File

@ -136,3 +136,4 @@ count*
version.txt
*.exe
logs/
config/

1
src/core/__init__.py Normal file
View File

@ -0,0 +1 @@
from .bot import Bot

188
src/core/bot.py Normal file
View File

@ -0,0 +1,188 @@
from pathlib import Path
import requests
import vk
from loguru import logger
import modules
from modules import config, is_new_version
from modules.perms import Permissions
from .hosts import Hosts
class Bot:
def __init__(self):
self.hosts: Hosts
self.perms: Permissions
self._test()
self.vk = vk.API(access_token=config["vk_token"], v=5.199)
print("Получение GroupID..", end="")
self.group_id = self.vk.groups.getById()['groups'][0]['id']
with open(config["help_file"], encoding="utf-8") as f:
self.help_message = f.read()
logger.info(f"[BOT] ID группы: {self.group_id}")
def _test(self):
Permissions.perm_file = Path(config["perms_file"])
self.perms = Permissions.load()
self.hosts = Hosts.load()
# Check token
if not config["vk_token"]:
logger.error("Токен ВК не найден.")
modules.enter_to_exit()
def get_lp_server(self):
lp = self.vk.groups.getLongPollServer(group_id=self.group_id)
return lp.get('server'), lp.get('key'), lp.get('ts')
def write(self, peer_id, message):
if len(message) > 4095:
messages = (len(message) // 4095)
for i in range(1, messages + 1):
if i > 30:
logger.error("[BOT] Сообщение слишком длинное...")
return
self.write(peer_id, message[:4095 * i])
else:
self.vk.messages.send(message=message, peer_id=peer_id, random_id=0)
def _handle_rcon(self, message, _write=True, allow=False):
"""Проверка прав и выполнение RCON команды"""
from_id = message['from_id']
peer_id = message['peer_id']
text = message['text']
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
tsplit = text.split(" ")
if allow:
role = "console"
else:
if tsplit[1] in self.hosts.hosts:
props = {"cmd": " ".join(tsplit[2:]), "server": tsplit[1]}
else:
props = {"cmd": " ".join(tsplit[1:])}
allow, role = self.perms.is_allowed(from_id, props['cmd'])
if allow:
answer, _ = self.hosts.rcon(**props)
if not answer:
answer = "Выполнено без ответа."
logger.info(f"[BOT] User: {from_id}({role}) in Chat: {peer_id} use RCON cmd: \"{props['cmd']}\", "
f"with answer: \"{answer}\"")
if _write:
self.write(peer_id, ("" if not props.get("server") else f"Ответ от {self.hosts._hosts_meta[props["server"]].get("name", props["server"])}:\n") + answer)
else:
return answer
else:
logger.info(f"[BOT] User: {from_id}({role}) in Chat: {peer_id} no have rights RCON cmd: \"{props['cmd']}\".")
if self.perms.no_rights: # Если есть текст
self.write(peer_id, self.perms.no_rights)
def _handle_bot(self, message):
from_id = message['from_id']
if self.perms.is_allowed(from_id, "bot"):
peer_id = message['peer_id']
text = message['text']
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
tsplit = text.split(" ")
cmds = ("Доступные команды:\n"
" .bot help - Вывести это сообщение.\n"
" .bot info - Выводит краткую информацию о боте.\n"
" .bot hosts list - Список доступных хостов\n"
" .bot hosts reload - Перезагружает hosts.yml\n"
# " .bot perms user [add | del] <group> - не реализовано \n"
# " .bot perms list - Выводит список групп \n"
" .bot perms reload - Перезагружает permissions.yml")
if len(tsplit) == 1:
self.write(peer_id, cmds)
return
match tsplit[1]:
case "hosts":
match tsplit[2] if len(tsplit) > 2 else None:
case "list":
s = ""
for host in self.hosts.hosts:
ping = 0
r, e = self.hosts.mine(host, True)
if not e:
ping = r.latency
_, e = self.hosts.rcon("list", host, True)
meta = self.hosts._hosts_meta[host]
name = meta.get("name")
rcon_ok = meta.get('rcon_ok')
mine_ok = meta.get('mine_ok')
if (not rcon_ok and meta['rcon'] > 0) or (not mine_ok and meta['online'] > 0):
s += f"\nㅤ⛔ {host} ({name})"
else:
s += f"\nㅤ✅ {host} ({name})"
if "-a" in tsplit or "--all" in tsplit:
# noinspection SpellCheckingInspection
s += (f":\n"
f"important: {meta['important']}\n"
f"rcon_default: {meta['rcon'] == 1}\n"
f"mine_default: {meta['online'] == 1}\n"
f"rcon: {not bool(e)}\n"
f"ping: {ping:.4f}ms\n"
f"rcon_ok: {rcon_ok}\n"
f"mine_ok: {mine_ok}")
self.write(peer_id, "Список хостов:" + s)
case "reload":
self.hosts = Hosts.load()
self.write(peer_id, "hosts.yml - Загружен")
case _:
self.write(peer_id, ".bot hosts [list | reload]")
case "perms":
match tsplit[2] if len(tsplit) > 2 else None:
case "reload":
self.perms = Permissions.load()
self.write(peer_id, "permissions.yml - Загружен")
case _:
self.write(peer_id, ".bot perms [reload]")
case "info":
self.write(peer_id, f"RconVkBot\n"
f"Версия бота: {modules.__version__}, последняя: {not is_new_version}")
case _:
self.write(peer_id, cmds)
def message_handle(self, message):
from_id = message['from_id']
peer_id = message['peer_id']
text = message['text']
match text:
case i if i.startswith(".rcon "):
self._handle_rcon(message)
case i if i.startswith(".bot"):
self._handle_bot(message)
case "!help":
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
self.write(peer_id, self.help_message)
case "!online":
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
server, _ = self.hosts.mine()
players = server.players
self.write(peer_id, f"На сервере сейчас {players.online}/{players.max}")
case "!id":
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
self.write(peer_id,
f"Твой ID: {from_id}\n"
f"Роль: {self.perms.get_role(from_id)}\n"
f"Ник: {self.perms.get_nick(from_id)}")
def listen(self):
server, key, ts = self.get_lp_server()
logger.info("[BOT] Начинаю получать сообщения..")
while True:
lp = requests.get(f'{server}?act=a_check&key={key}&ts={ts}&wait=25').json()
try:
if lp.get('failed') is not None:
key = self.get_lp_server()[1]
if ts != lp.get('ts') and lp.get('updates'):
updates = lp['updates'][0]
if updates['type'] == "message_new":
self.message_handle(updates['object']['message'])
ts = lp.get('ts')
except Exception as i:
ts = lp.get('ts')
logger.exception(i)
def stop(self):
self.hosts.unload()

124
src/core/hosts.py Normal file
View File

@ -0,0 +1,124 @@
import os
import re
from pathlib import Path
from loguru import logger
from mcrcon import MCRcon
from mcstatus import JavaServer, BedrockServer
from modules import yaml, raw_config_hosts, enter_to_exit
class Hosts:
hosts_config = Path("config/hosts.yml")
def __init__(self, **kwargs):
self._hosts = kwargs["hosts"]
self.hosts = set()
self._hosts_rcon = {}
self._hosts_mine = {}
self._hosts_meta = {}
self._connect()
logger.info("[HOSTS] Хосты загружены")
def rcon(self, cmd: str, server: str = "default", update=False) -> tuple[str | None, Exception | None]:
if not update and not self._hosts_meta[server].get('rcon_ok', True):
return ("Сервер в листе нерабочих.\nЕсли это не так, обновить можно этой командой\n.bot hosts list",
Exception("Сервер в листе нерабочих"))
if server not in self._hosts_rcon:
return "Сервер не найден", Exception("Сервер не найден")
try:
with MCRcon(**self._hosts_rcon[server]) as mcr:
text = mcr.command(cmd)
self._hosts_meta[server]['rcon_ok'] = True
return re.sub(r'§.', '', text), None
except Exception as e:
self._hosts_meta[server]['rcon_ok'] = False
logger.error(f"[RCON] Сервер: {server}; Команда: {cmd}")
logger.error(e)
return f"error: \"{e}\"", e
def mine(self, server: str = "default", update=False) -> tuple[JavaServer.lookup, Exception | None]:
if not update and not self._hosts_meta[server].get('mine_ok', True):
return ("Сервер в листе нерабочих.\nЕсли это не так, обновить можно этой командой\n.bot hosts list",
Exception("Сервер в листе нерабочих"))
if server not in self._hosts_mine:
return None, Exception("Сервер не найден")
s = self._hosts_mine[server]
try:
if self._hosts_meta[server]["java"]:
srv = JavaServer.lookup(f'{s["host"]}:{s["port"]}').status()
else:
# noinspection PyArgumentList
srv = BedrockServer.lookup(f'{s["host"]}:{s["port"]}').status()
self._hosts_meta[server]['mine_ok'] = True
return srv, None
except Exception as e:
self._hosts_meta[server]['mine_ok'] = False
logger.error(f"[MINE] Сервер не отвечает: {server} {s}")
logger.exception(e)
self._hosts_meta["connected"] = False
return None, e
def _connect(self) -> None:
if self._hosts is None or len(self._hosts) == 0:
logger.error("[HOSTS] Не найдено ни одного хоста.")
enter_to_exit()
self._hosts_meta['default'] = {}
# Test RCON
for name in self._hosts:
self.hosts.add(name)
server = self._hosts[name]
meta = self._hosts_meta[name] = server['meta']
if meta['rcon'] > 0:
rcon = self._hosts_rcon[name] = server['rcon']
print(f"Проверка RCON {name}..", end="")
srv, e = self.rcon("list", name)
if srv:
if meta['rcon'] == 1:
if self._hosts_rcon.get('default'):
logger.warning(f"[RCON] hosts.{name}.meta.rcon = 1 - Хотя уже есть дефолтный.")
self._hosts_rcon['default'] = rcon
self._hosts_meta['default']['rcon_ok'] = True
logger.info(f"[RCON] {name} доступен.")
else:
if meta["important"]:
logger.error(f"[RCON] Важный хост не доступен: {name}")
enter_to_exit()
if meta["online"] > 0:
mine = self._hosts_mine[name] = server['mine']
print(f"Проверка MINE {name}..", end="")
srv, e = self.mine(name)
if srv:
if meta['online'] == 1:
if self._hosts_mine.get('default'):
logger.warning(f"[RCON] hosts.{name}.meta.online = 1 - Хотя уже есть дефолтный.")
self._hosts_mine['default'] = mine
self._hosts_meta['default']['java'] = meta['java']
self._hosts_meta['default']['mine_ok'] = True
players = srv.players
logger.info(f"[MINE] {name} доступен. {players.online}/{players.max} {srv.latency:.3f}ms")
else:
if meta["important"]:
logger.error(f"[MINE] Важный хост не доступен: {name}")
enter_to_exit()
@classmethod
def load(cls) -> "Hosts":
if os.path.exists(cls.hosts_config):
data = yaml.load(cls.hosts_config)
if not data:
os.remove(cls.hosts_config)
return cls.load()
else:
data = yaml.load(raw_config_hosts)
with open(cls.hosts_config, mode="w", encoding="utf-8") as f:
yaml.dump(data, f)
logger.info(f"[HOSTS] {cls.hosts_config} - загружен")
return Hosts(**data)
def unload(self):
return

View File

@ -1,40 +1,19 @@
import sys
from pathlib import Path
from loguru import logger
from modules import config, rcon, get_server_status, enter_to_exit
from modules.bot import Bot
from modules.perms import Permissions
from core import Bot
from modules import enter_to_exit
if __name__ == '__main__':
Permissions.perm_file = Path(config.permissions_file)
perms = Permissions.load()
# Check token
if not config.vk.token:
logger.error("Токен ВК не найден.")
enter_to_exit()
bot = Bot(perms)
# Test RCON
print("Проверка RCON..", end="")
if rcon("list").startswith("Rcon error"):
logger.error("RCON не отвечает. Проверьте блок \"rcon\" в config.json")
enter_to_exit()
logger.info("RCON доступен.")
# Test Minecraft Server
print("Проверка сервера..", end="")
try:
st = get_server_status()
players = st.players
logger.info(f"Сервер доступен. Пинг: {st.latency:.3f}ms, Онлайн: {players.online}/{players.max}")
except Exception as e:
logger.exception(e)
logger.info("Сервер не отвечает. Проверьте блок \"minecraft\" в config.json")
enter_to_exit()
bot = Bot()
try:
bot.listen()
except KeyboardInterrupt:
logger.info("Exited.")
sys.exit(0)
except Exception as e:
logger.exception(e)
enter_to_exit()
finally:
bot.stop()

View File

@ -1,15 +1,11 @@
import glob
import json
import os
import re
import sys
import zipfile
from collections import namedtuple
from datetime import datetime
import requests
from loguru import logger
from mcrcon import MCRcon
from ruamel.yaml import YAML
yaml = YAML()
@ -18,24 +14,118 @@ IN_DOCKER = "DOCKER_CONTAINER" in os.environ
__version__ = '1.3.1'
raw_config = """\
{
"vk": {
"token": "",
"help_file": "help_message.txt"
},
"rcon": {
"host": "127.0.0.1",
"port": 25575,
"password": "P@ssw0rd"
},
"minecraft": {
"host": "127.0.0.1",
"port": 25565,
"java": true
},
"permissions_file": "permissions.yml"
}"""
raw_config_main = """\
vk_token: ""
help_file: config/help_message.txt
perms_file: config/permissions.yml
hosts_file: config/hosts.yml
"""
raw_config_perms = """\
noRole: Нет роли
noRights: Нет прав # null для отключения
noNick: Не указан # Используется для !id
# Таблица соответствия vkID к нику в Майнкрафте
# Ник будет передаваться в плагины (Плагины бота)
nicks:
370926160: Rick
583018016: SantaSpeen
perms:
admin: # Имя группы
name: Админ # Имя группы, которое будет отображаться в боте
ids: # вк ИД входящих в состав группы
- 370926160
parent: # Наследование прав
- helper
allow: # Какие команды разрешены, "*" - все
- '*'
helper:
name: Хелпер
ids:
- 583018016
allow:
- bot.rcon.* # См. host.yml
- say
- mute
- warn
default:
name: Игрок
allow:
- bot.online.* # См. host.yml
- bot.history.* # См. host.yml
"""
raw_config_hosts = """\
hosts:
survival: # Название сервера (имя), может быть любым, может быть сколько угодно
meta:
name: Выживание # Это имя будет выводиться в ответе, или статистике (имя для бота)
java: true # Это JAVA сервер?
important: true # Если да, то бот не включится, если не подключится
# 0 - выключен
# 1 - Доступно без имени (!! Такое значение может быть только у 1 хоста !!) (.rcon <cmd>)
# 2 - Доступно с именем (.rcon <name> <cmd>)
# Разрешение: bot.rcon.<name>; bot.online.<name>; bot.history.<name>
# При запуске бота будет проверка доступности всего
rcon: 2 # RCON будет доступен по команде .rcon lobby <cmd> (разрешение: bot.rcon.lobby)
online: 2 # !online будет доступен по команде !online lobby (разрешение: bot.online.lobby)
history: 2 # !history будет доступен по команде !history lobby (разрешение: bot.history.lobby)
rcon: # RCON подключение
host: 192.168.0.31
port: 15101
password: rconPass1
mine: # Minecraft подключение (нужно для !online и !history)
host: 192.168.0.31
port: 15001
lobby:
meta:
name: Лобби
important: true
java: true
rcon: 1
online: 2
history: 2
rcon:
host: 192.168.0.31
port: 15100
password: rconPass2
mine:
host: 192.168.0.31
port: 15000
devlobby:
meta:
name: Лобби
important: false
java: true
rcon: 2
online: 2
history: 0
rcon:
host: 192.168.0.31
port: 15108
password: rconPass3
mine:
host: 192.168.0.31
port: 15008
proxy-local:
meta:
name: Proxy-Local
java: true
important: true
rcon: 0
online: 1
history: 1
rcon: null
mine:
host: 192.168.0.31
port: 15009
"""
raw_help = """\
Тебе не нужна помощь, ты и так беспомощный, кожаный ублюдок. Так уж и быть, подскажу пару команд...
@ -44,6 +134,11 @@ raw_help = """\
Бот сделан кожанным петухом - админом, все вопросы к нему, я не причём.
"""
config_dir = "./config/"
config_file_main = config_dir + "bot.yml"
if not os.path.exists(config_dir):
os.makedirs(config_dir)
def init_logger():
log_file = "./logs/latest.log"
@ -71,45 +166,21 @@ def init_logger():
init_logger()
if not os.path.exists("config.json"):
logger.info("Создание: config.json...")
with open("config.json", "w") as f:
f.write(raw_config)
if not os.path.exists(config_file_main):
logger.info(f"Создание: {config_file_main}...")
c = yaml.load(raw_config_main)
with open(config_file_main, "w") as f:
yaml.dump(c, f)
with open('config.json') as f:
config = json.load(f, object_hook=lambda x: namedtuple('X', x.keys())(*x.values()))
with open(config_file_main) as f:
config = yaml.load(f)
logger.info("Запуск..")
if not os.path.exists(config.vk.help_file):
logger.info(f"Создание: {config.vk.help_file}...")
if not os.path.exists(config["help_file"]):
logger.info(f"Создание: {config["help_file"]}...")
with open(config.vk.help_file, "w", encoding="utf-8") as f:
f.write(raw_help)
if config.minecraft.java:
from mcstatus import JavaServer as MineServer
else:
from mcstatus import BedrockServer as MineServer
host = config.rcon.host
port = config.rcon.port
password = config.rcon.password
def rcon(cmd):
try:
with MCRcon(host, password, port) as mcr:
text = mcr.command(cmd)
return re.sub(r'§.', '', text)
except Exception as e:
logger.error(f"[RCON] ERROR with command: {cmd}")
logger.exception(e)
return f"Rcon error: {e}"
def get_server_status():
server = MineServer.lookup(config.minecraft.host, config.minecraft.port)
return server.status()
def enter_to_exit(exit_code=1):
logger.info("Выход..")
@ -127,8 +198,8 @@ def new_version():
if ver and ver != __version__:
logger.info("Обнаружена новая версия: {} -> {}", __version__, ver)
return True
except:
logger.error("Не получилось проверить обновления.")
except Exception as e:
logger.error(f"Не получилось проверить обновления: {e}")
else:
logger.info("У вас актуальная версия")
return False

View File

@ -1,121 +0,0 @@
import requests
import vk
from loguru import logger
import modules
from modules import config, rcon, get_server_status, is_new_version
from modules.perms import Permissions
class Bot:
def __init__(self, perms: Permissions):
self.perms: Permissions = perms
self.vk = vk.API(access_token=config.vk.token, v=5.199)
print("Получение GroupID..", end="")
self.group_id = self.vk.groups.getById()['groups'][0]['id']
with open('help_message.txt', encoding="utf-8") as f:
self.help_message = f.read()
logger.info(f"[BOT] ID группы: {self.group_id}")
def get_lp_server(self):
lp = self.vk.groups.getLongPollServer(group_id=self.group_id)
return lp.get('server'), lp.get('key'), lp.get('ts')
def write(self, peer_id, message):
if len(message) > 4095:
messages = (len(message) // 4095)
for i in range(1, messages + 1):
if i > 30:
logger.error("[BOT] Сообщение слишком длинное...")
break
self.write(peer_id, message[:4095 * i])
else:
self.vk.messages.send(message=message, peer_id=peer_id, random_id=0)
def rcon_cmd_handle(self, cmd, from_id, peer_id, _write=True, _allow=False):
a, r = self.perms.is_allowed(from_id, cmd.split()[0])
if _allow:
r = cmd
if a or _allow:
answer = rcon(cmd)
logger.info(f"[BOT] User: {from_id}({r}) in Chat: {peer_id} use RCON cmd: \"{cmd}\", "
f"with answer: \"{answer}\"")
if _write:
self.write(peer_id, f"RCON:\n{answer}")
else:
return answer
else:
logger.info(f"[BOT] User: {from_id}({r}) in Chat: {peer_id} no have rights RCON cmd: \"{cmd}\".")
def _bot_handle(self, message):
from_id = message['from_id']
if self.perms.is_allowed(from_id, "bot"):
peer_id = message['peer_id']
text = message['text']
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
tsplit = text.split(" ")
cmds = ("Доступные команды:\n"
" .bot help - Вывести это сообщение.\n"
" .bot info - Выводит краткую информацию о боте.\n"
" .bot perm user <> - Добавить пользователя \n"
" .bot perm reload - Перезагружает пермишины")
if len(tsplit) == 1:
self.write(peer_id, cmds)
return
match tsplit[1]:
case "perm":
match tsplit[2] if len(tsplit) > 2 else None:
case "reload":
self.perms = Permissions.load()
self.write(peer_id, "Права перезагружены")
case _:
self.write(peer_id, ".bot perm ?")
case "info":
st = get_server_status()
self.write(peer_id, f"RconVkBot\n"
f"Версия бота: {modules.__version__}, последняя: {not is_new_version}\n"
f"Пинг до сервера: {st.latency:.3f}ms\n"
f"Бедрок: {st.motd.bedrock} ({st.version.protocol})\n")
case _:
self.write(peer_id, cmds)
def message_handle(self, message):
from_id = message['from_id']
peer_id = message['peer_id']
text = message['text']
match text:
case i if i.startswith(".rcon "):
self.rcon_cmd_handle(i[6:], from_id, peer_id)
case i if i.startswith(".bot"):
self._bot_handle(message)
case "!help":
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
self.write(peer_id, self.help_message)
case "!online":
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
players = get_server_status().players
self.write(peer_id, f"На сервере сейчас {players.online}/{players.max}")
case "!id":
logger.info(f"[BOT] {peer_id}:{from_id}:{text}")
self.write(peer_id,
f"Твой ID: {from_id}\n"
f"Роль: {self.perms.get_role(from_id)}\n"
f"Ник: {self.perms.get_nick(from_id)}")
def listen(self):
server, key, ts = self.get_lp_server()
logger.info("[BOT] Начинаю получать сообщения..")
while True:
lp = requests.get(f'{server}?act=a_check&key={key}&ts={ts}&wait=25').json()
try:
if lp.get('failed') is not None:
key = self.get_lp_server()[1]
if ts != lp.get('ts') and lp.get('updates'):
updates = lp['updates'][0]
if updates['type'] == "message_new":
self.message_handle(updates['object']['message'])
ts = lp.get('ts')
except Exception as i:
ts = lp.get('ts')
logger.exception(i)

View File

@ -1,10 +1,9 @@
import os.path
import sys
from pathlib import Path
from loguru import logger
from modules import yaml
from modules import yaml, raw_config_perms
class Permissions:
@ -15,14 +14,10 @@ class Permissions:
self._no_nick = kwargs.get("noNick")
self.no_rights = kwargs.get("noRights")
self._perms = kwargs['perms']
self._nicks = kwargs['nicks']
self._members = {}
if kwargs['useLuckPerms']:
logger.info("[PERMS] Поддержка LuckPerms всё ещё в разработке. ")
print(kwargs['LuckPerms']['nicks'])
sys.exit(1)
self._luck_perms = kwargs['LuckPerms']
logger.info(f"[PERMS] {self.perm_file} - загружен")
self.__handle_members()
logger.info(f"[PERMS] Права загружены")
def __handle_members(self):
for role, role_data in self._perms.items():
@ -37,7 +32,7 @@ class Permissions:
self._members[member] = {
"role": role,
"friendly": role_data.get("name", role),
"nick": self._luck_perms['nicks'].get(member) or self._no_nick,
"nick": self._nicks.get(member) or self._no_nick,
"allow": allow
}
@ -71,59 +66,12 @@ class Permissions:
os.remove(cls.perm_file)
return Permissions.load()
else:
logger.info(f"Generating permissions file: {cls.perm_file}")
import textwrap
raw = textwrap.dedent("""\
noRole: Нет роли
noRights: Нет прав # null для отключения
noNick: Не указан # Используется для !id, ник берётся из LuckPerms.nicks независимо от useLuckPerms
perms:
admins: # Имя группы
name: Админ # Имя группы, которое будет отображаться в боте
ids: # вк ИД входящих в состав группы
- 370926160
allow: # Какие команды разрешены, "*" - все
- '*'
# Пример настройки
helpers:
name: Хелпер
ids:
- 583018016
allow:
- say
- mute
- warn
# Находится в режиме тестирования
# Интеграция с базой данных LuckPerms (Нужна именно внешняя база данных)
useLuckPerms: false
LuckPerms:
# Таблица соответствия vkID к нику в Майнкрафте
nicks:
370926160: Rick
583018016: SantaSpeen
# Разрешенные варианты: MySQL, MariaDB, PostgreSQL
storage-method: PostgreSQL
data:
# Указывайте host:port
address: 127.0.0.1:5432
# База данных в которой хранятся настройки LuckPerms
database: minecraftDB
# Логин и пароль для доступа к БД
username: user
password: user
# Смотрите настройку LuckPerms
table-prefix: luckperms_
server: global
""")
data = yaml.load(raw)
logger.info(f"Создание: {cls.perm_file}...")
data = yaml.load(raw_config_perms)
with open(cls.perm_file, mode="w", encoding="utf-8") as f:
yaml.dump(data, f)
logger.info(f"[PERMS] {cls.perm_file} - загружен")
return Permissions(**data)

View File

View File

@ -0,0 +1,20 @@
try:
import Bot
import logger
except ImportError:
Bot = object
class Plugin(Bot):
ac_dir = "./perms"
def __init__(self):
super(Plugin, self).__init__()
logger.info(f"Инициализация {self.name} v{self.version}")
async def load(self):
pass
async def unload(self):
pass

View File

@ -0,0 +1,16 @@
LuckPerms:
# Разрешенные варианты: MySQL, MariaDB, PostgreSQL
storage-method: PostgreSQL
data:
# Указывайте host:port
address: 127.0.0.1:5432
# База данных в которой хранятся настройки LuckPerms
database: minecraftDB
# Логин и пароль для доступа к БД
username: user
password: user
# Смотрите настройку LuckPerms
table-prefix: luckperms_
server: global

View File

@ -0,0 +1,61 @@
# /cmd cmd: perm - Можно только <perm>
# /cmd cmd: noOne - Команду нельзя использовать из под бота
enabled: false
pluginName: AuthMeReloaded 5.6.0-beta2
data:
/authme register: authme.admin.register
/authme unregister: authme.admin.unregister
/authme forcelogin: authme.admin.forcelogin
/authme password: authme.admin.changepassword
/authme lastlogin: authme.admin.lastlogin
/authme accounts: authme.admin.accounts
/authme email: authme.admin.getemail
/authme setemail: authme.admin.changemail
/authme getip: authme.admin.getip
/authme totp: authme.admin.totpviewstatus
/authme disabletotp: authme.admin.totpdisable
/authme spawn: authme.admin.spawn
/authme setspawn: authme.admin.setspawn
/authme firstspawn: authme.admin.firstspawn
/authme setfirstspawn: authme.admin.setfirstspawn
/authme purge: authme.admin.purge
/authme purgeplayer: authme.admin.purgeplayer
/authme backup: authme.admin.backup
/authme resetpos: authme.admin.purgelastpos
/authme purgebannedplayers: authme.admin.purgebannedplayers
/authme switchantibot: authme.admin.switchantibot
/authme reload: authme.admin.reload
/authme version: authme.admin # Вставил так как стандартно есть у всех
/authme converter: authme.admin.converter
/authme messages: authme.admin.updatemessages
/authme recent: authme.admin.seerecent
/authme debug: authme.debug.command
/authme help: noOne
/email: noOne
/email show: noOne
/email add: noOne
/email change: noOne
/email recover: noOne
/email code: noOne
/email setpassword: noOne
/email help: noOne
/login: noOne
/login help: noOne
/logout: noOne
/logout help: noOne
/register: noOne
/register help: noOne
/unregister: noOne
/unregister help: noOne
/changepassword: noOne
/changepassword help: noOne
/totp: noOne
/totp code: noOne
/totp add: noOne
/totp confirm: noOne
/totp remove: noOne
/totp help: noOne
/captcha: noOne
/captcha help: noOne
/verification: noOne
/verification help: noOne

View File

@ -0,0 +1,5 @@
enabled: false
version: 0.1
name: LuckPerms Integration
dependencies:
- bot >1.3 # Это сам бот

4
src/plugins/readme.md Normal file
View File

@ -0,0 +1,4 @@
# Поддержка плагинов
Пока ещё в работе