mirror of
https://github.com/Xtao-Labs/misskey2telegram.git
synced 2024-11-28 23:55:17 +00:00
feat: chat message
This commit is contained in:
parent
df73cc1246
commit
9c3b55c3ff
151
defs/chat.py
Normal file
151
defs/chat.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from mipac import ChatMessage, File
|
||||||
|
from mipac.models.lite import LiteUser
|
||||||
|
from pyrogram.errors import MediaEmpty
|
||||||
|
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
from glover import misskey_host
|
||||||
|
from init import bot, request
|
||||||
|
from scheduler import add_delete_file_job, delete_file
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_link(user: LiteUser) -> str:
|
||||||
|
if user.host:
|
||||||
|
return f"https://{user.host}/@{user.username}"
|
||||||
|
return f"https://{misskey_host}/@{user.username}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_source_link(message: ChatMessage) -> str:
|
||||||
|
return (
|
||||||
|
f"https://{misskey_host}/my/messaging/{message.user.username}?cid={message.user.id}"
|
||||||
|
if not message.group and message.user
|
||||||
|
else f"https://{misskey_host}/my/messaging/group/{message.group.id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_button(message: ChatMessage):
|
||||||
|
author = get_user_link(message.user)
|
||||||
|
source = get_source_link(message)
|
||||||
|
first_line = [
|
||||||
|
InlineKeyboardButton(text="Chat", url=source),
|
||||||
|
InlineKeyboardButton(text="Author", url=author),
|
||||||
|
]
|
||||||
|
return InlineKeyboardMarkup([first_line])
|
||||||
|
|
||||||
|
|
||||||
|
def get_content(message: ChatMessage) -> str:
|
||||||
|
content = message.text or ""
|
||||||
|
content = content[:768]
|
||||||
|
user = f"<a href=\"{get_user_link(message.user)}\">{message.user.nickname}</a>"
|
||||||
|
if message.group:
|
||||||
|
group = f"<a href=\"{get_source_link(message)}\">{message.group.name}</a>"
|
||||||
|
user += f" ( {group} )"
|
||||||
|
return f"""<b>Misskey Message</b>
|
||||||
|
|
||||||
|
{user}: <code>{content}</code>"""
|
||||||
|
|
||||||
|
|
||||||
|
async def send_text(cid: int, message: ChatMessage, reply_to_message_id: int):
|
||||||
|
await bot.send_message(
|
||||||
|
cid,
|
||||||
|
get_content(message),
|
||||||
|
reply_to_message_id=reply_to_message_id,
|
||||||
|
reply_markup=gen_button(message),
|
||||||
|
disable_web_page_preview=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def deprecated_to_text(func):
|
||||||
|
async def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
return await func(*args, **kwargs)
|
||||||
|
except MediaEmpty:
|
||||||
|
return await send_text(args[0], args[2], args[3])
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated_to_text
|
||||||
|
async def send_photo(cid: int, url: str, message: ChatMessage, reply_to_message_id: int):
|
||||||
|
if not url:
|
||||||
|
return await send_text(cid, message, reply_to_message_id)
|
||||||
|
await bot.send_photo(
|
||||||
|
cid,
|
||||||
|
url,
|
||||||
|
reply_to_message_id=reply_to_message_id,
|
||||||
|
caption=get_content(message),
|
||||||
|
reply_markup=gen_button(message),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated_to_text
|
||||||
|
async def send_video(cid: int, url: str, message: ChatMessage, reply_to_message_id: int):
|
||||||
|
if not url:
|
||||||
|
return await send_text(cid, message, reply_to_message_id)
|
||||||
|
await bot.send_video(
|
||||||
|
cid,
|
||||||
|
url,
|
||||||
|
reply_to_message_id=reply_to_message_id,
|
||||||
|
caption=get_content(message),
|
||||||
|
reply_markup=gen_button(message),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated_to_text
|
||||||
|
async def send_audio(cid: int, url: str, message: ChatMessage, reply_to_message_id: int):
|
||||||
|
if not url:
|
||||||
|
return await send_text(cid, message, reply_to_message_id)
|
||||||
|
await bot.send_audio(
|
||||||
|
cid,
|
||||||
|
url,
|
||||||
|
reply_to_message_id=reply_to_message_id,
|
||||||
|
caption=get_content(message),
|
||||||
|
reply_markup=gen_button(message),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def fetch_document(file: File) -> Optional[str]:
|
||||||
|
file_name = f"downloads/{file.name}"
|
||||||
|
file_url = file.url
|
||||||
|
if file.size > 10 * 1024 * 1024:
|
||||||
|
return file_url
|
||||||
|
if not file_url:
|
||||||
|
return file_url
|
||||||
|
req = await request.get(file_url)
|
||||||
|
if req.status_code != 200:
|
||||||
|
return file_url
|
||||||
|
with open(file_name, "wb") as f:
|
||||||
|
f.write(req.content)
|
||||||
|
add_delete_file_job(file_name)
|
||||||
|
return file_name
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated_to_text
|
||||||
|
async def send_document(cid: int, file: File, message: ChatMessage, reply_to_message_id: int):
|
||||||
|
file = await fetch_document(file)
|
||||||
|
if not file:
|
||||||
|
return await send_text(cid, message, reply_to_message_id)
|
||||||
|
await bot.send_document(
|
||||||
|
cid,
|
||||||
|
file,
|
||||||
|
reply_to_message_id=reply_to_message_id,
|
||||||
|
caption=get_content(message),
|
||||||
|
reply_markup=gen_button(message),
|
||||||
|
)
|
||||||
|
await delete_file(file)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_chat_message(cid: int, message: ChatMessage, topic_id: int):
|
||||||
|
if not message.file:
|
||||||
|
return await send_text(cid, message, topic_id)
|
||||||
|
file_url = message.file.url
|
||||||
|
file_type = message.file.type
|
||||||
|
if file_type.startswith("image"):
|
||||||
|
await send_photo(cid, file_url, message, topic_id)
|
||||||
|
elif file_type.startswith("video"):
|
||||||
|
await send_video(cid, file_url, message, topic_id)
|
||||||
|
elif file_type.startswith("audio"):
|
||||||
|
await send_audio(cid, file_url, message, topic_id)
|
||||||
|
else:
|
||||||
|
await send_document(cid, message.file, message, topic_id)
|
@ -41,7 +41,51 @@ class ReadySend:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
await msg.edit(f"发送失败:{e}")
|
await msg.edit(f"发送失败:{e}")
|
||||||
else:
|
else:
|
||||||
await msg.edit("发送成功")
|
await msg.delete()
|
||||||
|
finally:
|
||||||
|
del ready_send[msg.id]
|
||||||
|
|
||||||
|
|
||||||
|
class ReadySendMessage:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
text: str,
|
||||||
|
group: bool = False,
|
||||||
|
uid: Optional[str] = None,
|
||||||
|
file_id: Optional[str] = None,
|
||||||
|
):
|
||||||
|
self.text = text
|
||||||
|
self.user_id = None if group else uid
|
||||||
|
self.group_id = uid if group else None
|
||||||
|
self.file_id = file_id
|
||||||
|
|
||||||
|
async def confirm(self, msg: Message):
|
||||||
|
msg = await msg.reply(
|
||||||
|
"确认发送?",
|
||||||
|
quote=True,
|
||||||
|
reply_markup=InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[
|
||||||
|
InlineKeyboardButton(text="发送", callback_data="chat_send"),
|
||||||
|
InlineKeyboardButton(text="拒绝", callback_data="delete")
|
||||||
|
]
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
ready_send[msg.id] = self
|
||||||
|
|
||||||
|
async def send(self, msg: Message):
|
||||||
|
try:
|
||||||
|
await misskey_bot.core.api.chat.action.send(
|
||||||
|
text=self.text,
|
||||||
|
user_id=self.user_id,
|
||||||
|
group_id=self.group_id,
|
||||||
|
file_id=self.file_id,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
await msg.edit(f"发送失败:{e}")
|
||||||
|
else:
|
||||||
|
await msg.delete()
|
||||||
finally:
|
finally:
|
||||||
del ready_send[msg.id]
|
del ready_send[msg.id]
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ async def send_group(cid: int, files: list[IDriveFile], note: Note, reply_to_mes
|
|||||||
await send_text(cid, note, msg.id if msg else None)
|
await send_text(cid, note, msg.id if msg else None)
|
||||||
|
|
||||||
|
|
||||||
async def send_update(cid: int, note: Note, topic_id: int = None):
|
async def send_update(cid: int, note: Note, topic_id: int):
|
||||||
files = list(note.files)
|
files = list(note.files)
|
||||||
if note.reply:
|
if note.reply:
|
||||||
files.extend(iter(note.reply.files))
|
files.extend(iter(note.reply.files))
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
from mipa.ext import commands
|
from mipa.ext import commands
|
||||||
from mipa.router import Router
|
from mipa.router import Router
|
||||||
from mipac import Note, NotificationFollow, NotificationFollowRequest
|
from mipac import Note, NotificationFollow, NotificationFollowRequest, ChatMessage
|
||||||
|
|
||||||
|
from defs.chat import send_chat_message
|
||||||
from defs.misskey import send_update
|
from defs.misskey import send_update
|
||||||
from defs.notice import send_user_followed, send_follow_request, send_follow_request_accept
|
from defs.notice import send_user_followed, send_follow_request, send_follow_request_accept
|
||||||
from glover import admin, topic_group_id, timeline_topic_id
|
from glover import admin, topic_group_id, timeline_topic_id, notice_topic_id
|
||||||
|
|
||||||
|
|
||||||
class MisskeyBot(commands.Bot):
|
class MisskeyBot(commands.Bot):
|
||||||
@ -29,5 +30,11 @@ class MisskeyBot(commands.Bot):
|
|||||||
async def on_follow_request_accept(self, notice: NotificationFollowRequest):
|
async def on_follow_request_accept(self, notice: NotificationFollowRequest):
|
||||||
await send_follow_request_accept(notice)
|
await send_follow_request_accept(notice)
|
||||||
|
|
||||||
|
async def on_chat(self, message: ChatMessage):
|
||||||
|
await send_chat_message(topic_group_id or admin, message, notice_topic_id)
|
||||||
|
|
||||||
|
async def on_chat_unread_message(self, message: ChatMessage):
|
||||||
|
await message.api.read()
|
||||||
|
|
||||||
|
|
||||||
misskey_bot = MisskeyBot()
|
misskey_bot = MisskeyBot()
|
||||||
|
69
modules/chat.py
Normal file
69
modules/chat.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import contextlib
|
||||||
|
from os import remove
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
from pyrogram import Client, filters, ContinuePropagation
|
||||||
|
from pyrogram.types import Message, CallbackQuery
|
||||||
|
|
||||||
|
from defs.confirm import ready_send, ReadySendMessage
|
||||||
|
from glover import admin
|
||||||
|
from init import notice_filter
|
||||||
|
from misskey_init import misskey_bot
|
||||||
|
|
||||||
|
|
||||||
|
def get_uid(message: Message) -> Tuple[bool, str]:
|
||||||
|
group, user, uid = False, None, None
|
||||||
|
if (
|
||||||
|
not message.reply_to_message
|
||||||
|
or not message.reply_to_message.reply_markup
|
||||||
|
):
|
||||||
|
raise ContinuePropagation
|
||||||
|
with contextlib.suppress(IndexError, AttributeError):
|
||||||
|
url = message.reply_to_message.reply_markup.inline_keyboard[0][0].url
|
||||||
|
user = url.split("/")[-1]
|
||||||
|
if "/my/messaging/group/" in url:
|
||||||
|
group = True
|
||||||
|
uid = user
|
||||||
|
else:
|
||||||
|
uid = user.split("?cid=")[1]
|
||||||
|
if not user:
|
||||||
|
raise ContinuePropagation
|
||||||
|
if not uid:
|
||||||
|
raise ContinuePropagation
|
||||||
|
return group, uid
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(filters.incoming & notice_filter & filters.text & filters.user(admin))
|
||||||
|
async def chat_command(_: Client, message: Message):
|
||||||
|
group, uid = get_uid(message)
|
||||||
|
text = message.text.strip()
|
||||||
|
if text.startswith("@"):
|
||||||
|
raise ContinuePropagation
|
||||||
|
need_send = ReadySendMessage(text, group, uid)
|
||||||
|
await need_send.confirm(message)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(filters.incoming & notice_filter & filters.photo & filters.user(admin))
|
||||||
|
async def chat_photo_command(_: Client, message: Message):
|
||||||
|
group, uid = get_uid(message)
|
||||||
|
text = message.caption.strip() if message.caption else ""
|
||||||
|
photo = await message.download()
|
||||||
|
try:
|
||||||
|
file_ = await misskey_bot.core.api.drive.file.action.upload_file(photo)
|
||||||
|
except Exception as e:
|
||||||
|
return await message.reply(f"上传文件失败:{e}", quote=True)
|
||||||
|
need_send = ReadySendMessage(text, group, uid, file_.id)
|
||||||
|
remove(photo)
|
||||||
|
await need_send.confirm(message)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_callback_query(filters.regex("^chat_send$"))
|
||||||
|
async def chat_send_callback(_: Client, callback_query: CallbackQuery):
|
||||||
|
"""
|
||||||
|
发送
|
||||||
|
"""
|
||||||
|
if need_send := ready_send.get(callback_query.message.id, None):
|
||||||
|
await need_send.send(callback_query.message)
|
||||||
|
return await callback_query.answer("发送成功")
|
||||||
|
else:
|
||||||
|
return await callback_query.answer("按钮已过期", show_alert=True)
|
@ -1,3 +1,4 @@
|
|||||||
|
import contextlib
|
||||||
from mipac.errors import InternalErrorError, AlreadyFollowingError, FolloweeIsYourselfError
|
from mipac.errors import InternalErrorError, AlreadyFollowingError, FolloweeIsYourselfError
|
||||||
from pyrogram import Client, filters
|
from pyrogram import Client, filters
|
||||||
from pyrogram.types import Message, CallbackQuery
|
from pyrogram.types import Message, CallbackQuery
|
||||||
@ -42,6 +43,8 @@ async def follow_user_callback(_: Client, callback_query: CallbackQuery):
|
|||||||
关注/取消关注用户
|
关注/取消关注用户
|
||||||
"""
|
"""
|
||||||
user_id = callback_query.matches[0].group(1)
|
user_id = callback_query.matches[0].group(1)
|
||||||
|
button = callback_query.message.reply_markup
|
||||||
|
follow = True
|
||||||
try:
|
try:
|
||||||
await misskey_bot.core.api.follow.action.add(user_id)
|
await misskey_bot.core.api.follow.action.add(user_id)
|
||||||
await callback_query.answer("关注成功", show_alert=True)
|
await callback_query.answer("关注成功", show_alert=True)
|
||||||
@ -51,12 +54,16 @@ async def follow_user_callback(_: Client, callback_query: CallbackQuery):
|
|||||||
try:
|
try:
|
||||||
await misskey_bot.core.api.follow.action.remove(user_id)
|
await misskey_bot.core.api.follow.action.remove(user_id)
|
||||||
await callback_query.answer("取消关注成功", show_alert=True)
|
await callback_query.answer("取消关注成功", show_alert=True)
|
||||||
|
follow = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await callback_query.answer("取消关注失败", show_alert=True)
|
await callback_query.answer("取消关注失败", show_alert=True)
|
||||||
await callback_query.message.reply(f"取消关注失败:{e}", quote=True)
|
await callback_query.message.reply(f"取消关注失败:{e}", quote=True)
|
||||||
return
|
|
||||||
except FolloweeIsYourselfError:
|
except FolloweeIsYourselfError:
|
||||||
await callback_query.answer("不能关注自己", show_alert=True)
|
await callback_query.answer("不能关注自己", show_alert=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await callback_query.answer("关注失败", show_alert=True)
|
await callback_query.answer("关注失败", show_alert=True)
|
||||||
await callback_query.message.reply(f"关注失败:{e}", quote=True)
|
await callback_query.message.reply(f"关注失败:{e}", quote=True)
|
||||||
|
if button:
|
||||||
|
with contextlib.suppress(Exception):
|
||||||
|
button.inline_keyboard[1][0].text = "➖" if follow else "➕"
|
||||||
|
await callback_query.message.edit_reply_markup(button)
|
||||||
|
2
requirements.git.txt
Normal file
2
requirements.git.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
git+https://github.com/yupix/MiPA.git
|
||||||
|
git+https://github.com/yupix/MiPAC.git
|
@ -1,5 +1,3 @@
|
|||||||
git+https://github.com/yupix/MiPA.git
|
|
||||||
git+https://github.com/yupix/MiPAC.git
|
|
||||||
Pyrogram==2.0.97
|
Pyrogram==2.0.97
|
||||||
tgCrypto==1.2.5
|
tgCrypto==1.2.5
|
||||||
httpx==0.23.3
|
httpx==0.23.3
|
||||||
|
Loading…
Reference in New Issue
Block a user