feat: add karkas_lite

This commit is contained in:
Maxim Slipenko 2024-10-03 19:59:23 +03:00
parent 0881fe02d5
commit 9ac88652e0
No known key found for this signature in database
GPG Key ID: 6DEA9FA7DE98C7D6
20 changed files with 2650 additions and 18 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ __pycache__
Karkas.db Karkas.db
config.yaml config.yaml
dist dist
*.py[cod]

View File

@ -23,6 +23,10 @@
{ {
"name": "ALT Linux", "name": "ALT Linux",
"path": "src/altlinux" "path": "src/altlinux"
},
{
"name": "Karkas Lite",
"path": "src/karkas_lite"
} }
], ],
"extensions": { "extensions": {

View File

@ -5,18 +5,22 @@ from karkas_core.modules_system.public_api import set_my_commands
commands = dict() commands = dict()
def register_command(command, description, role="USER"): def register_command(command, description, long_description=None, role="USER"):
if long_description is None:
long_description = description
if role not in commands: if role not in commands:
commands[role] = dict() commands[role] = dict()
commands[role][command] = { commands[role][command] = {
"description": description, "description": description,
"long_description": long_description,
} }
async def set_user_commands(): async def set_commands(role="USER"):
bot_commands = [] bot_commands = []
if "USER" in commands: if role in commands:
user_commands = commands["USER"] user_commands = commands[role]
for command in user_commands: for command in user_commands:
bot_commands.append( bot_commands.append(
BotCommand( BotCommand(
@ -25,18 +29,24 @@ async def set_user_commands():
) )
) )
# log(bot_commands)
await set_my_commands( await set_my_commands(
bot_commands, bot_commands,
) )
def get_user_commands(): def get_commands(role="USER"):
if "USER" in commands: if role in commands:
return commands["USER"].copy() return commands[role].copy()
return {} return {}
async def set_user_commands():
await set_commands("USER")
def get_user_commands():
return get_commands("USER")
async def module_late_init(): async def module_late_init():
await set_user_commands() await set_user_commands()

View File

@ -2,6 +2,7 @@ from .filters import (
ChatIDFilter, ChatIDFilter,
ChatModerOrAdminFilter, ChatModerOrAdminFilter,
ChatNotInApproveFilter, ChatNotInApproveFilter,
SimpleAdminFilter,
chat_not_in_approve, chat_not_in_approve,
module_init, module_init,
) )

View File

@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict
from aiogram import BaseMiddleware, Bot from aiogram import BaseMiddleware, Bot
from aiogram.filters import BaseFilter from aiogram.filters import BaseFilter
from aiogram.types import Message, TelegramObject from aiogram.types import Message, TelegramObject
from aiogram.utils.chat_member import ADMINS
from typing_extensions import deprecated from typing_extensions import deprecated
from karkas_core.modules_system.public_api import ( from karkas_core.modules_system.public_api import (
@ -121,3 +122,9 @@ class ChatModerOrAdminFilter(BaseFilter):
or await roles.check_moderator_permission(user_id) or await roles.check_moderator_permission(user_id)
or any(user_id == admin.user.id for admin in admins) or any(user_id == admin.user.id for admin in admins)
) )
class SimpleAdminFilter(BaseFilter):
async def __call__(self, message: Message, bot: Bot) -> bool:
member = await bot.get_chat_member(message.chat.id, message.from_user.id)
return isinstance(member, ADMINS)

View File

@ -42,7 +42,7 @@ FOOTER = """===============
def format_commands(commands_dict): def format_commands(commands_dict):
formatted_commands = [] formatted_commands = []
for command, details in commands_dict.items(): for command, details in commands_dict.items():
formatted_commands.append(f"/{command} - {details['description']}") formatted_commands.append(f"/{command} - {details['long_description']}")
return "\n".join(formatted_commands) return "\n".join(formatted_commands)

View File

@ -0,0 +1,29 @@
from piccolo.apps.migrations.auto.migration_manager import MigrationManager
ID = "2024-10-03T19:24:33:522177"
VERSION = "1.16.0"
DESCRIPTION = ""
async def forwards():
manager = MigrationManager(
migration_id=ID, app_name="standard.spam", description=DESCRIPTION
)
manager.drop_column(
table_class_name="SpamLog",
tablename="spam_log",
column_name="chat_id",
db_column_name="chat_id",
schema=None,
)
manager.drop_column(
table_class_name="SpamLog",
tablename="spam_log",
column_name="user_id",
db_column_name="user_id",
schema=None,
)
return manager

View File

@ -1,10 +1,8 @@
from piccolo.columns import JSON, Date, Integer, Text from piccolo.columns import JSON, Date, Text
from piccolo.table import Table from piccolo.table import Table
class SpamLog(Table): class SpamLog(Table):
chat_id = Integer()
user_id = Integer()
message_text = Text(null=True) message_text = Text(null=True)
attachments = JSON() attachments = JSON()
created_at = Date() created_at = Date()

View File

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Type
from aiogram import Bot, Router from aiogram import Bot, Router
from aiogram.filters import Command from aiogram.filters import Command
@ -17,6 +17,8 @@ except Exception:
if TYPE_CHECKING: if TYPE_CHECKING:
from aiogram.types import Message from aiogram.types import Message
from karkas_blocks.standard.filters import SimpleAdminFilter as ISimpleAdminFilter
async def spam(message: "Message", bot: "Bot"): async def spam(message: "Message", bot: "Bot"):
if not message.reply_to_message: if not message.reply_to_message:
@ -41,8 +43,6 @@ async def spam(message: "Message", bot: "Bot"):
} }
spam_log = SpamLog( spam_log = SpamLog(
chat_id=chat_id,
user_id=spam_message.from_user.id,
message_text=spam_message.text, message_text=spam_message.text,
attachments=attachments, attachments=attachments,
) )
@ -67,15 +67,23 @@ async def spam(message: "Message", bot: "Bot"):
def module_init(): def module_init():
register_app_config = get_module("standard.database", "register_app_config") register_app_config = get_module("standard.database", "register_app_config")
SimpleAdminFilter: "Type[ISimpleAdminFilter]" = get_module(
"standard.filters", "SimpleAdminFilter"
)
from .db import APP_CONFIG from .db import APP_CONFIG
register_app_config(APP_CONFIG) register_app_config(APP_CONFIG)
router = Router() router = Router()
router.message.register(spam, Command("spam")) router.message.register(spam, SimpleAdminFilter(), Command("spam"))
register_router(router) register_router(router)
if COMMAND_HELPER_MODULE_LOADED: if COMMAND_HELPER_MODULE_LOADED:
register_command("spam", "Спам", role="ADMIN") register_command(
"spam",
"Удалить спам и забанить пользователя",
long_description="Удалить спам и забанить пользователя. "
"Собирает обезличенные данные для дальнейшего создания алгоритма",
)

View File

@ -0,0 +1,38 @@
FROM python:3.12-slim AS dependencies_installer
RUN pip install poetry
WORKDIR /app
COPY ./src/karkas_core/poetry* ./src/karkas_core/pyproject.toml /app/src/karkas_core/
COPY ./src/karkas_blocks/poetry* ./src/karkas_blocks/pyproject.toml /app/src/karkas_blocks/
COPY ./src/karkas_piccolo/poetry* ./src/karkas_piccolo/pyproject.toml /app/src/karkas_piccolo/
COPY ./src/karkas_lite/poetry* ./src/karkas_lite/pyproject.toml /app/src/karkas_lite/
WORKDIR /app/src/karkas_lite
RUN poetry install --no-root --no-directory
FROM python:3.12-slim AS src
COPY ./src/karkas_core /app/src/karkas_core
COPY ./src/karkas_blocks /app/src/karkas_blocks
COPY ./src/karkas_piccolo /app/src/karkas_piccolo
COPY ./src/karkas_lite /app/src/karkas_lite
FROM python:3.12-slim AS local_dependencies_installer
RUN pip install poetry
COPY --from=dependencies_installer /app/src/karkas_lite/.venv /app/src/karkas_lite/.venv
COPY --from=src /app/src/ /app/src/
WORKDIR /app/src/karkas_lite
RUN poetry install
FROM python:3.12-slim AS base
COPY --from=local_dependencies_installer /app/src/karkas_lite/.venv /app/src/karkas_lite/.venv
COPY --from=src /app/src/ /app/src/
WORKDIR /app/src/karkas_lite
ENV PATH="/app/.venv/bin:$PATH"
CMD ["/bin/bash", "-c", ". .venv/bin/activate && python -m karkas_lite"]

View File

@ -0,0 +1,14 @@
**/Dockerfile
**/*.dockerignore
**/docker-compose.yml
**/.git
**/.gitignore
**/.venv
**/.mypy_cache
**/__pycache__/
src/karkas_lite/config.yaml
src/karkas_lite/database/*

View File

View File

@ -0,0 +1,3 @@
core:
mode: LONG_POLLING
token: xxx

View File

View File

@ -0,0 +1,10 @@
services:
app:
build:
context: ../..
dockerfile: src/karkas_lite/Dockerfile
ports:
- 9000:9000
volumes:
- ./config.yaml:/app/src/karkas_lite/config.yaml
- ./database:/app/database

View File

View File

@ -0,0 +1,24 @@
import asyncio
from karkas_blocks import block_loader
from karkas_core import Karkas
async def main():
ocab = Karkas()
await ocab.init_app(
[
block_loader("standard", "config", safe=False),
block_loader("standard", "filters", safe=False),
block_loader("standard", "database", safe=False),
block_loader("standard", "command_helper"),
block_loader("standard", "spam", safe=False),
block_loader("standard", "report"),
block_loader("standard", "welcome", safe=False),
block_loader("standard", "help"),
]
)
await ocab.start()
asyncio.run(main())

2465
src/karkas_lite/poetry.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
[virtualenvs]
in-project = true

View File

@ -0,0 +1,18 @@
[tool.poetry]
name = "karkas-lite"
version = "0.1.0"
description = ""
authors = [
"Maxim Slipenko <maxim@slipenko.com>"
]
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.10,<3.13"
karkas-core = { extras=["webhook"], path = "../karkas_core", develop = true }
karkas-blocks = { path = "../karkas_blocks", develop = true }
karkas-piccolo = { path = "../karkas_piccolo", develop = true }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"