mirror of
https://github.com/Xtao-Labs/misskey2telegram.git
synced 2024-11-25 14:55:19 +00:00
perf: support mipac v0.6.0
This commit is contained in:
parent
e3146b44ba
commit
83b52128bf
@ -7,7 +7,7 @@ from typing import Optional, List
|
|||||||
import aiofiles as aiofiles
|
import aiofiles as aiofiles
|
||||||
from httpx import AsyncClient
|
from httpx import AsyncClient
|
||||||
from mipac import Note, File
|
from mipac import Note, File
|
||||||
from mipac.models.lite import LiteUser
|
from mipac.models.lite import PartialUser
|
||||||
from pyrogram.enums import ParseMode
|
from pyrogram.enums import ParseMode
|
||||||
from pyrogram.errors import MediaEmpty, FloodWait
|
from pyrogram.errors import MediaEmpty, FloodWait
|
||||||
from pyrogram.types import (
|
from pyrogram.types import (
|
||||||
@ -59,15 +59,15 @@ def gen_button(host: str, note: Note, author: str, show_second: bool):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_user_link(host: str, user: LiteUser) -> str:
|
def get_user_link(host: str, user: PartialUser) -> str:
|
||||||
if user.host:
|
if user.host:
|
||||||
return f"https://{host}/@{user.username}@{user.host}"
|
return f"https://{host}/@{user.username}@{user.host}"
|
||||||
return f"https://{host}/@{user.username}"
|
return f"https://{host}/@{user.username}"
|
||||||
|
|
||||||
|
|
||||||
def get_user_alink(host: str, user: LiteUser) -> str:
|
def get_user_alink(host: str, user: PartialUser) -> str:
|
||||||
return '<a href="{}">{}</a>'.format(
|
return '<a href="{}">{}</a>'.format(
|
||||||
get_user_link(host, user), user.nickname or f"@{user.username}"
|
get_user_link(host, user), user.name or f"@{user.username}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ def format_at(host: str, content: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def get_content(host: str, note: Note) -> str:
|
def get_content(host: str, note: Note) -> str:
|
||||||
content = note.content or ""
|
content = note.text or ""
|
||||||
action = "发表"
|
action = "发表"
|
||||||
origin = ""
|
origin = ""
|
||||||
show_note = note
|
show_note = note
|
||||||
@ -95,21 +95,21 @@ def get_content(host: str, note: Note) -> str:
|
|||||||
if content:
|
if content:
|
||||||
action = "引用"
|
action = "引用"
|
||||||
content = (
|
content = (
|
||||||
f"> {note.renote.content or ''}\n\n=====================\n\n{content}"
|
f"> {note.renote.text or ''}\n\n=====================\n\n{content}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
content = note.renote.content or ""
|
content = note.renote.text or ""
|
||||||
origin = (
|
origin = (
|
||||||
f"\n{get_user_alink(host, note.renote.author)} "
|
f"\n{get_user_alink(host, note.renote.user)} "
|
||||||
f"发表于 {get_post_time(note.renote.created_at)}"
|
f"发表于 {get_post_time(note.renote.created_at)}"
|
||||||
)
|
)
|
||||||
if note.reply:
|
if note.reply:
|
||||||
show_note = note.reply
|
show_note = note.reply
|
||||||
action = "回复"
|
action = "回复"
|
||||||
if note.reply.content:
|
if note.reply.text:
|
||||||
content = f"> {note.reply.content}\n\n=====================\n\n{content}"
|
content = f"> {note.reply.text}\n\n=====================\n\n{content}"
|
||||||
origin = (
|
origin = (
|
||||||
f"\n{get_user_alink(host, note.reply.author)} "
|
f"\n{get_user_alink(host, note.reply.user)} "
|
||||||
f"发表于 {get_post_time(note.reply.created_at)}"
|
f"发表于 {get_post_time(note.reply.created_at)}"
|
||||||
)
|
)
|
||||||
content = format_at(host, content[:768] + " ").strip()
|
content = format_at(host, content[:768] + " ").strip()
|
||||||
@ -117,7 +117,7 @@ def get_content(host: str, note: Note) -> str:
|
|||||||
|
|
||||||
{content}
|
{content}
|
||||||
|
|
||||||
{get_user_alink(host, note.author)} {action}于 {get_post_time(note.created_at)}{origin}
|
{get_user_alink(host, note.user)} {action}于 {get_post_time(note.created_at)}{origin}
|
||||||
点赞: {sum(show_note.reactions.values())} | 回复: {show_note.replies_count} | 转发: {show_note.renote_count}"""
|
点赞: {sum(show_note.reactions.values())} | 回复: {show_note.replies_count} | 转发: {show_note.renote_count}"""
|
||||||
|
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ async def send_text(
|
|||||||
get_content(host, note),
|
get_content(host, note),
|
||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
reply_markup=gen_button(
|
reply_markup=gen_button(
|
||||||
host, note, get_user_link(host, note.author), show_second
|
host, note, get_user_link(host, note.user), show_second
|
||||||
),
|
),
|
||||||
disable_web_page_preview=True,
|
disable_web_page_preview=True,
|
||||||
)
|
)
|
||||||
@ -225,7 +225,7 @@ async def send_photo(
|
|||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
caption=get_content(host, note),
|
caption=get_content(host, note),
|
||||||
reply_markup=gen_button(
|
reply_markup=gen_button(
|
||||||
host, note, get_user_link(host, note.author), show_second
|
host, note, get_user_link(host, note.user), show_second
|
||||||
),
|
),
|
||||||
has_spoiler=spoiler,
|
has_spoiler=spoiler,
|
||||||
)
|
)
|
||||||
@ -250,7 +250,7 @@ async def send_gif(
|
|||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
caption=get_content(host, note),
|
caption=get_content(host, note),
|
||||||
reply_markup=gen_button(
|
reply_markup=gen_button(
|
||||||
host, note, get_user_link(host, note.author), show_second
|
host, note, get_user_link(host, note.user), show_second
|
||||||
),
|
),
|
||||||
has_spoiler=spoiler,
|
has_spoiler=spoiler,
|
||||||
)
|
)
|
||||||
@ -275,7 +275,7 @@ async def send_video(
|
|||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
caption=get_content(host, note),
|
caption=get_content(host, note),
|
||||||
reply_markup=gen_button(
|
reply_markup=gen_button(
|
||||||
host, note, get_user_link(host, note.author), show_second
|
host, note, get_user_link(host, note.user), show_second
|
||||||
),
|
),
|
||||||
has_spoiler=spoiler,
|
has_spoiler=spoiler,
|
||||||
)
|
)
|
||||||
@ -299,7 +299,7 @@ async def send_audio(
|
|||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
caption=get_content(host, note),
|
caption=get_content(host, note),
|
||||||
reply_markup=gen_button(
|
reply_markup=gen_button(
|
||||||
host, note, get_user_link(host, note.author), show_second
|
host, note, get_user_link(host, note.user), show_second
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ async def send_document(
|
|||||||
reply_to_message_id=reply_to_message_id,
|
reply_to_message_id=reply_to_message_id,
|
||||||
caption=get_content(host, note),
|
caption=get_content(host, note),
|
||||||
reply_markup=gen_button(
|
reply_markup=gen_button(
|
||||||
host, note, get_user_link(host, note.author), show_second
|
host, note, get_user_link(host, note.user), show_second
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from json import load
|
from json import load
|
||||||
|
|
||||||
from mipac import Note
|
from mipac import Note
|
||||||
from mipac.models.lite.user import LiteUser
|
from mipac.models.lite.user import PartialUser
|
||||||
from mipac.models.notification import (
|
from mipac.models.notification import (
|
||||||
NotificationFollow,
|
NotificationFollow,
|
||||||
NotificationFollowRequest,
|
NotificationFollowRequest,
|
||||||
@ -21,15 +21,15 @@ with open("gen/achievement.json", "r", encoding="utf-8") as f:
|
|||||||
achievement_map = load(f)
|
achievement_map = load(f)
|
||||||
|
|
||||||
|
|
||||||
def get_user_link(host: str, user: LiteUser) -> str:
|
def get_user_link(host: str, user: PartialUser) -> str:
|
||||||
if user.host:
|
if user.host:
|
||||||
return f"https://{host}/@{user.username}@{user.host}"
|
return f"https://{host}/@{user.username}@{user.host}"
|
||||||
return f"https://{host}/@{user.username}"
|
return f"https://{host}/@{user.username}"
|
||||||
|
|
||||||
|
|
||||||
def get_user_alink(host: str, user: LiteUser) -> str:
|
def get_user_alink(host: str, user: PartialUser) -> str:
|
||||||
return '<a href="{}">{}</a>'.format(
|
return '<a href="{}">{}</a>'.format(
|
||||||
get_user_link(host, user), user.nickname or f"@{user.username}"
|
get_user_link(host, user), user.name or f"@{user.username}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ def get_note_link(host: str, note: Note) -> str:
|
|||||||
return f"https://{host}/notes/{note.id}"
|
return f"https://{host}/notes/{note.id}"
|
||||||
|
|
||||||
|
|
||||||
def gen_link_button(host: str, user: LiteUser = None, note: Note = None):
|
def gen_link_button(host: str, user: PartialUser = None, note: Note = None):
|
||||||
return [
|
return [
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
text="Link",
|
text="Link",
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from mipac import UserDetailed
|
from mipac import UserDetailedNotMe
|
||||||
from mipac.errors import FailedToResolveRemoteUserError
|
from mipac.errors import FailedToResolveRemoteUserError
|
||||||
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||||
|
|
||||||
|
from defs.misskey import get_user_link
|
||||||
from misskey_init import MisskeyBot
|
from misskey_init import MisskeyBot
|
||||||
|
|
||||||
template = """<b>Misskey User Info</b>
|
template = """<b>Misskey User Info</b>
|
||||||
@ -18,18 +19,18 @@ Updated: <code>%s</code>
|
|||||||
📤 %s 粉丝 %s 关注 %s"""
|
📤 %s 粉丝 %s 关注 %s"""
|
||||||
|
|
||||||
|
|
||||||
def gen_text(user: UserDetailed):
|
def gen_text(host: str, user: UserDetailedNotMe):
|
||||||
def parse_time(time: str) -> str:
|
def parse_time(time: datetime) -> str:
|
||||||
if not time:
|
if not time:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
time = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S.%fZ") + timedelta(hours=8)
|
time = time + timedelta(hours=8)
|
||||||
return time.strftime("%Y-%m-%d %H:%M:%S")
|
return time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
create_at = parse_time(user.created_at)
|
create_at = parse_time(user.created_at)
|
||||||
update_at = parse_time(user.updated_at)
|
update_at = parse_time(user.updated_at)
|
||||||
return template % (
|
return template % (
|
||||||
user.nickname,
|
user.name,
|
||||||
user.api.action.get_profile_link(),
|
get_user_link(host, user),
|
||||||
user.username,
|
user.username,
|
||||||
user.description or "",
|
user.description or "",
|
||||||
create_at,
|
create_at,
|
||||||
@ -40,9 +41,9 @@ def gen_text(user: UserDetailed):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def gen_button(user: UserDetailed):
|
def gen_button(host: str, user: UserDetailedNotMe):
|
||||||
first_line = [
|
first_line = [
|
||||||
InlineKeyboardButton(text="Link", url=user.api.action.get_profile_link()),
|
InlineKeyboardButton(text="Link", url=get_user_link(host, user)),
|
||||||
]
|
]
|
||||||
second_line = [
|
second_line = [
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
@ -55,7 +56,7 @@ def gen_button(user: UserDetailed):
|
|||||||
|
|
||||||
async def search_user(
|
async def search_user(
|
||||||
misskey_bot: MisskeyBot, username: str, host: str = None
|
misskey_bot: MisskeyBot, username: str, host: str = None
|
||||||
) -> Optional[UserDetailed]:
|
) -> Optional[UserDetailedNotMe]:
|
||||||
"""
|
"""
|
||||||
搜索用户
|
搜索用户
|
||||||
"""
|
"""
|
||||||
|
21
glover.py
21
glover.py
@ -1,6 +1,25 @@
|
|||||||
from configparser import RawConfigParser
|
from configparser import RawConfigParser
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from distutils.util import strtobool
|
|
||||||
|
|
||||||
|
def strtobool(val, default=False):
|
||||||
|
"""Convert a string representation of truth to true (1) or false (0).
|
||||||
|
|
||||||
|
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
|
||||||
|
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
|
||||||
|
'val' is anything else.
|
||||||
|
"""
|
||||||
|
if val is None:
|
||||||
|
return default
|
||||||
|
val = val.lower()
|
||||||
|
if val in ("y", "yes", "t", "true", "on", "1"):
|
||||||
|
return 1
|
||||||
|
elif val in ("n", "no", "f", "false", "off", "0"):
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
print("[Degrade] invalid truth value %r" % (val,))
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
# [pyrogram]
|
# [pyrogram]
|
||||||
api_id: int = 0
|
api_id: int = 0
|
||||||
|
@ -50,11 +50,11 @@ class MisskeyBot(commands.Bot):
|
|||||||
|
|
||||||
async def fetch_offline_notes(self):
|
async def fetch_offline_notes(self):
|
||||||
logs.info(f"{self.tg_user.user_id} 开始获取最近十条时间线")
|
logs.info(f"{self.tg_user.user_id} 开始获取最近十条时间线")
|
||||||
data = {"withReplies": False, "limit": 10}
|
data = {"withReplies": False, "limit": 1}
|
||||||
data = await self.core.http.request(
|
data = await self.core.http.request(
|
||||||
Route("POST", "/api/notes/timeline"), auth=True, json=data
|
Route("POST", "/api/notes/timeline"), auth=True, json=data
|
||||||
)
|
)
|
||||||
for note in (Note(note=note, client=self.client) for note in data):
|
for note in (Note(raw_note=note, client=self.client) for note in data):
|
||||||
await self.process_note(note, notice=False)
|
await self.process_note(note, notice=False)
|
||||||
logs.info(f"{self.tg_user.user_id} 处理完成最近十条时间线")
|
logs.info(f"{self.tg_user.user_id} 处理完成最近十条时间线")
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class NoRepeatRenoteAction:
|
|||||||
async def check(uid: int, note: Note):
|
async def check(uid: int, note: Note):
|
||||||
if await NoRepeatRenoteAction.get(uid, note.id):
|
if await NoRepeatRenoteAction.get(uid, note.id):
|
||||||
return False
|
return False
|
||||||
if note.renote and (not note.content):
|
if note.renote and (not note.text):
|
||||||
if await NoRepeatRenoteAction.get(uid, note.renote.id):
|
if await NoRepeatRenoteAction.get(uid, note.renote.id):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@ -26,5 +26,5 @@ class NoRepeatRenoteAction:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
async def set(uid: int, note: Note):
|
async def set(uid: int, note: Note):
|
||||||
await NoRepeatRenoteAction.push(uid, note.id)
|
await NoRepeatRenoteAction.push(uid, note.id)
|
||||||
if note.renote and (not note.content):
|
if note.renote and (not note.text):
|
||||||
await NoRepeatRenoteAction.push(uid, note.renote.id)
|
await NoRepeatRenoteAction.push(uid, note.renote.id)
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
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 misskey_init import get_misskey_bot
|
|
||||||
from models.filters import notice_filter
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
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)
|
|
||||||
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:
|
|
||||||
misskey_bot = get_misskey_bot(message.from_user.id)
|
|
||||||
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$") & notice_filter)
|
|
||||||
async def chat_send_callback(_: Client, callback_query: CallbackQuery):
|
|
||||||
"""
|
|
||||||
发送
|
|
||||||
"""
|
|
||||||
msg = callback_query.message
|
|
||||||
if need_send := ready_send.get((msg.chat.id, msg.id), None):
|
|
||||||
await need_send.send(msg, callback_query.from_user.id)
|
|
||||||
return await callback_query.answer("发送成功")
|
|
||||||
else:
|
|
||||||
return await callback_query.answer("按钮已过期", show_alert=True)
|
|
@ -28,7 +28,8 @@ async def search_user_command(_: Client, message: Message):
|
|||||||
user = await search_user(misskey_bot, username, host)
|
user = await search_user(misskey_bot, username, host)
|
||||||
if not user:
|
if not user:
|
||||||
return await message.reply("没有找到用户", quote=True)
|
return await message.reply("没有找到用户", quote=True)
|
||||||
text, button = gen_text(user), gen_button(user)
|
host = misskey_bot.tg_user.host
|
||||||
|
text, button = gen_text(host, user), gen_button(host, user)
|
||||||
if user.avatar_url:
|
if user.avatar_url:
|
||||||
try:
|
try:
|
||||||
await message.reply_photo(
|
await message.reply_photo(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Pyrogram==2.0.106
|
Pyrogram==2.0.106
|
||||||
tgCrypto==1.2.5
|
PyrotgCrypto==1.2.6
|
||||||
httpx==0.24.1
|
httpx==0.24.1
|
||||||
apscheduler==3.10.1
|
apscheduler==3.10.1
|
||||||
sqlalchemy==1.4.41
|
sqlalchemy==1.4.41
|
||||||
@ -7,7 +7,7 @@ sqlmodel==0.0.8
|
|||||||
aiosqlite==0.19.0
|
aiosqlite==0.19.0
|
||||||
PyYAML==6.0.1
|
PyYAML==6.0.1
|
||||||
aiofiles==23.1.0
|
aiofiles==23.1.0
|
||||||
pillow==10.0.0
|
pillow==10.2.0
|
||||||
cashews[redis]==6.2.0
|
cashews[redis]==6.2.0
|
||||||
alembic==1.11.2
|
alembic==1.11.2
|
||||||
sentry-sdk==1.29.2
|
sentry-sdk==1.29.2
|
||||||
|
Loading…
Reference in New Issue
Block a user