Skip to content

Commit

Permalink
Approve VK
Browse files Browse the repository at this point in the history
  • Loading branch information
dyakovri committed Apr 27, 2024
1 parent 3f138d5 commit 330337c
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 27 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build_and_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ jobs:
--env DB_DSN='${{ secrets.DB_DSN }}' \
--env AUTH_URL='https://api.profcomff.com/auth' \
--env TELEGRAM_BOT_TOKEN='${{ secrets.TELEGRAM_BOT_TOKEN }}' \
--env VK_BOT_GROUP_ID='{{ secrets.VK_BOT_GROUP_ID }}' \
--env VK_BOT_TOKEN='{{ secrets.VK_BOT_TOKEN }}' \
--env GITHUB_APP_ID='${{ secrets.GH_APP_ID }}' \
--env GITHUB_PRIVATE_KEY='${{ secrets.GH_PRIVATE_KEY }}' \
--env DISCORD_PUBLIC_KEY='${{ secrets.DISCORD_PUBLIC_KEY }}' \
Expand Down
Empty file added social/handlers_vk/__init__.py
Empty file.
35 changes: 35 additions & 0 deletions social/handlers_vk/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import logging
from collections.abc import Callable

from social.utils.events import EventProcessor
from social.utils.vk_groups import approve_vk_chat


logger = logging.getLogger(__name__)
EVENT_PROCESSORS: list[EventProcessor] = []


def event(**filters: str):
"""Помечает функцию как обработчик событий, задает фильтры для запуска"""

def deco(func: Callable):
EVENT_PROCESSORS.append(EventProcessor(filters, func))
return func

return deco


def process_event(event: dict):
for processor in EVENT_PROCESSORS:
if processor.check_and_process(event):
break
else:
logger.debug("Event without processor")


@event(
type="message_new",
object=lambda i: i.get("message", {}).get("text", "").startswith("/validate"),
)
def validate_group(event: dict):
approve_vk_chat(event)
2 changes: 1 addition & 1 deletion social/models/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Group(Base):
owner_id: Mapped[int | None]

is_deleted: Mapped[bool] = mapped_column(default=False)
last_active_ts: Mapped[datetime]
last_active_ts: Mapped[datetime] = mapped_column(default=lambda: datetime.now(UTC))

create_ts: Mapped[datetime] = mapped_column(default=lambda: datetime.now(UTC))
update_ts: Mapped[datetime] = mapped_column(default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))
Expand Down
32 changes: 7 additions & 25 deletions social/routes/vk.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import logging
from datetime import UTC, datetime

from auth_lib.fastapi import UnionAuth
from fastapi import APIRouter, Depends, Request
from fastapi import APIRouter, BackgroundTasks, Depends, Request
from fastapi.responses import PlainTextResponse
from fastapi_sqlalchemy import db
from pydantic import BaseModel, ConfigDict

from social.models.group import VkChat, VkGroup
from social.handlers_vk.base import process_event
from social.models.group import VkGroup
from social.models.webhook_storage import WebhookStorage, WebhookSystems
from social.settings import get_settings
from social.utils.string import random_string
from social.utils.vk_groups import create_vk_chat


router = APIRouter(prefix="/vk", tags=['vk'])
Expand All @@ -31,7 +32,7 @@ class VkGroupCreateResponse(BaseModel):


@router.post('', tags=["webhooks"])
async def vk_webhook(request: Request) -> str:
async def vk_webhook(request: Request, background_tasks: BackgroundTasks) -> str:
"""Принимает любой POST запрос от VK"""
request_data = await request.json()
logger.debug(request_data)
Expand All @@ -53,27 +54,8 @@ async def vk_webhook(request: Request) -> str:
)
db.session.commit()

if request_data.get("type") == "message_new":
# Получение сообщения в чате ВК
try:
peer_id = request_data["object"]["message"]["peer_id"]
obj = db.session.query(VkChat).where(VkChat.peer_id == peer_id).one_or_none()
if obj is None:
# Надо будет добавлять название группы
# conversation = requests.post("https://api.vk.com/method/messages.getConversationsById", json={
# "peer_ids": peer_id,
# "group_id": 222099060,
# "access_token": settings.VK_BOT_TOKEN,
# "v": 5.199,
# })
# chat_title = conversation["response"]["items"][0]["chat_settings"]["title"]
obj = VkChat(chat_id=peer_id)
db.session.add(obj)
obj.last_active_ts = datetime.now(UTC)
db.session.commit()
except Exception as exc:
logger.exception(exc)

background_tasks.add_task(create_vk_chat, request_data)
background_tasks.add_task(process_event, request_data)
return PlainTextResponse('ok')


Expand Down
1 change: 1 addition & 0 deletions social/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Settings(BaseSettings):

TELEGRAM_BOT_TOKEN: str | None = None

VK_BOT_GROUP_ID: int | None = None
VK_BOT_TOKEN: str | None = None

GITHUB_APP_ID: int | None = None
Expand Down
4 changes: 3 additions & 1 deletion social/utils/telegram_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@


def create_telegram_group(update: Update):
"""Создает запись о телеграмм группе в внутренней БД приложения или возвращает существующий"""
chat = update.effective_chat
obj = None
if chat.type in ['group', 'supergroup']:
Expand All @@ -33,6 +34,7 @@ def create_telegram_group(update: Update):


def approve_telegram_group(update: Update):
"""Если получено сообщение команды /validate, то за группой закрепляется владелец"""
logger.debug("Validation started")
group = create_telegram_group(update)
text = update.effective_message.text
Expand All @@ -41,7 +43,7 @@ def approve_telegram_group(update: Update):
return
text = text.removeprefix('/validate').removeprefix('@ViribusSocialBot').strip()
request = db.session.query(CreateGroupRequest).where(CreateGroupRequest.secret_key == text).one_or_none()
request.mapped_group_id=group.id
request.mapped_group_id = group.id
group.owner_id = request.owner_id
db.session.commit()
logger.info("Telegram group %d validated (secret=%s)", group.id, text)
66 changes: 66 additions & 0 deletions social/utils/vk_groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import logging
from datetime import UTC, datetime

import requests
from fastapi_sqlalchemy import db

from social.models import CreateGroupRequest, VkChat
from social.settings import get_settings


logger = logging.getLogger(__name__)
settings = get_settings()


def get_chat_name(peer_id):
"""Получить название чата ВК"""
conversation = requests.post(
"https://api.vk.com/method/messages.getConversationsById",
json={
"peer_ids": peer_id,
"group_id": settings.VK_BOT_GROUP_ID,
"access_token": settings.VK_BOT_TOKEN,
"v": 5.199,
},
)
try:
return conversation["response"]["items"][0]["chat_settings"]["title"]
except Exception as exc:
logger.exception(exc)
return None


def create_vk_chat(request_data: dict[str]):
"""Создает запись о вк чате в внутренней БД приложения или возвращает существующий"""
if (
request_data.get("group_id") == settings.VK_BOT_GROUP_ID # peer_id чатов уникальные для каждого пользователя ВК
and request_data.get("type") == "message_new"
):
# Получение сообщения в чате ВК
try:
peer_id = request_data["object"]["message"]["peer_id"]
obj = db.session.query(VkChat).where(VkChat.peer_id == peer_id).one_or_none()
if obj is None:
obj = VkChat(peer_id=peer_id)
db.session.add(obj)
obj.last_active_ts = datetime.now(UTC)
db.session.commit()
except Exception as exc:
logger.exception(exc)
return obj
return None


def approve_vk_chat(request_data: dict[str]):
"""Если получено сообщение команды /validate, то за группой закрепляется владелец"""
logger.debug("Validation started")
group = create_vk_chat(request_data)
text = request_data.get("object", {}).get("message", {}).get("text", "").removeprefix("/validate").strip()
if not text or not group or group.owner_id is not None:
logger.error("Telegram group not validated (secret=%s, group=%s)", text, group)
return
request = db.session.query(CreateGroupRequest).where(CreateGroupRequest.secret_key == text).one_or_none()
request.mapped_group_id = group.id
group.owner_id = request.owner_id
db.session.commit()
logger.info("VK group %d validated (secret=%s)", group.id, text)

0 comments on commit 330337c

Please sign in to comment.