mirror of
https://github.com/TeamPGM/PagerMaid_Plugins_Pyro.git
synced 2024-11-22 09:41:54 +00:00
This commit is contained in:
parent
f9e5e6afb5
commit
95293aea7e
213
shift/main.py
213
shift/main.py
@ -1,22 +1,32 @@
|
|||||||
""" PagerMaid module for channel help. """
|
""" PagerMaid module for channel help. """
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import datetime
|
||||||
from asyncio import sleep
|
from asyncio import sleep
|
||||||
from random import uniform
|
from random import uniform
|
||||||
from typing import Any, List, Union, Set
|
from typing import Any, List, Literal, Optional
|
||||||
|
|
||||||
from pyrogram.enums.chat_type import ChatType
|
import pytz
|
||||||
from pyrogram.errors.exceptions.flood_420 import FloodWait
|
from pyrogram.enums import ChatType
|
||||||
|
from pyrogram.errors import FloodWait
|
||||||
from pyrogram.types import Chat
|
from pyrogram.types import Chat
|
||||||
|
|
||||||
from pagermaid import log, logs
|
from pagermaid import log, Config
|
||||||
from pagermaid.enums import Client, Message
|
from pagermaid.enums import Client, Message
|
||||||
|
from pagermaid.enums.command import CommandHandler
|
||||||
from pagermaid.listener import listener
|
from pagermaid.listener import listener
|
||||||
from pagermaid.single_utils import sqlite
|
from pagermaid.services import bot, scheduler, sqlite, logs
|
||||||
from pagermaid.utils import lang
|
from pagermaid.utils import lang
|
||||||
|
|
||||||
WHITELIST = [-1001441461877]
|
WHITELIST = [-1001441461877]
|
||||||
|
AVAILABLE_OPTIONS_TYPE = Literal["silent", "text", "all", "photo", "document", "video"]
|
||||||
AVAILABLE_OPTIONS = {"silent", "text", "all", "photo", "document", "video"}
|
AVAILABLE_OPTIONS = {"silent", "text", "all", "photo", "document", "video"}
|
||||||
|
HELP_TEXT = """set [from channel] [to channel] (silent) 自动转发频道新消息(可以使用频道用户名或者 id)
|
||||||
|
del [from channel] 删除转发
|
||||||
|
backup [from channel] [to channel] (silent) 备份频道(可以使用频道用户名或者 id)
|
||||||
|
list 顯示目前轉發的頻道
|
||||||
|
选项说明:
|
||||||
|
silent: 禁用通知, text: 文字, all: 全部訊息都傳, photo: 圖片, document: 檔案, video: 影片"""
|
||||||
|
|
||||||
|
|
||||||
def try_cast_or_fallback(val: Any, t: type) -> Any:
|
def try_cast_or_fallback(val: Any, t: type) -> Any:
|
||||||
@ -28,7 +38,14 @@ def try_cast_or_fallback(val: Any, t: type) -> Any:
|
|||||||
|
|
||||||
def check_chat_available(chat: Chat):
|
def check_chat_available(chat: Chat):
|
||||||
assert (
|
assert (
|
||||||
chat.type in [ChatType.CHANNEL, ChatType.GROUP, ChatType.SUPERGROUP, ChatType.BOT, ChatType.PRIVATE]
|
chat.type
|
||||||
|
in [
|
||||||
|
ChatType.CHANNEL,
|
||||||
|
ChatType.GROUP,
|
||||||
|
ChatType.SUPERGROUP,
|
||||||
|
ChatType.BOT,
|
||||||
|
ChatType.PRIVATE,
|
||||||
|
]
|
||||||
and not chat.has_protected_content
|
and not chat.has_protected_content
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,18 +53,17 @@ def check_chat_available(chat: Chat):
|
|||||||
@listener(
|
@listener(
|
||||||
command="shift",
|
command="shift",
|
||||||
description="开启转发频道新消息功能",
|
description="开启转发频道新消息功能",
|
||||||
parameters="set [from channel] [to channel] (silent) 自动转发频道新消息(可以使用频道用户名或者 id)\n"
|
parameters=HELP_TEXT,
|
||||||
"del [from channel] 删除转发\n"
|
|
||||||
"backup [from channel] [to channel] (silent) 备份频道(可以使用频道用户名或者 id)\n"
|
|
||||||
"list 顯示目前轉發的頻道\n\n"
|
|
||||||
"选项说明:\n"
|
|
||||||
"silent: 禁用通知, text: 文字, all: 全部訊息都傳, photo: 圖片, document: 檔案, video: 影片",
|
|
||||||
)
|
)
|
||||||
async def shift_set(client: Client, message: Message):
|
async def shift_func(message: Message):
|
||||||
if not message.parameter:
|
await message.edit(HELP_TEXT)
|
||||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
|
||||||
return
|
|
||||||
if message.parameter[0] == "set":
|
shift_func: "CommandHandler"
|
||||||
|
|
||||||
|
|
||||||
|
@shift_func.sub_command(command="set")
|
||||||
|
async def shift_func_set(client: Client, message: Message):
|
||||||
if len(message.parameter) < 3:
|
if len(message.parameter) < 3:
|
||||||
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||||
options = set(message.parameter[3:] if len(message.parameter) > 3 else ())
|
options = set(message.parameter[3:] if len(message.parameter) > 3 else ())
|
||||||
@ -55,9 +71,7 @@ async def shift_set(client: Client, message: Message):
|
|||||||
return await message.edit("出错了呜呜呜 ~ 无法识别的选项。")
|
return await message.edit("出错了呜呜呜 ~ 无法识别的选项。")
|
||||||
# 检查来源频道
|
# 检查来源频道
|
||||||
try:
|
try:
|
||||||
source = await client.get_chat(
|
source = await client.get_chat(try_cast_or_fallback(message.parameter[1], int))
|
||||||
try_cast_or_fallback(message.parameter[1], int)
|
|
||||||
)
|
|
||||||
assert isinstance(source, Chat)
|
assert isinstance(source, Chat)
|
||||||
check_chat_available(source)
|
check_chat_available(source)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -66,9 +80,7 @@ async def shift_set(client: Client, message: Message):
|
|||||||
return await message.edit("出错了呜呜呜 ~ 此对话位于白名单中。")
|
return await message.edit("出错了呜呜呜 ~ 此对话位于白名单中。")
|
||||||
# 检查目标频道
|
# 检查目标频道
|
||||||
try:
|
try:
|
||||||
target = await client.get_chat(
|
target = await client.get_chat(try_cast_or_fallback(message.parameter[2], int))
|
||||||
try_cast_or_fallback(message.parameter[2], int)
|
|
||||||
)
|
|
||||||
assert isinstance(target, Chat)
|
assert isinstance(target, Chat)
|
||||||
except Exception:
|
except Exception:
|
||||||
return await message.edit("出错了呜呜呜 ~ 无法识别的目标对话。")
|
return await message.edit("出错了呜呜呜 ~ 无法识别的目标对话。")
|
||||||
@ -81,26 +93,30 @@ async def shift_set(client: Client, message: Message):
|
|||||||
)
|
)
|
||||||
await message.edit(f"已成功配置将对话 {source.id} 的新消息转发到 {target.id} 。")
|
await message.edit(f"已成功配置将对话 {source.id} 的新消息转发到 {target.id} 。")
|
||||||
await log(f"已成功配置将对话 {source.id} 的新消息转发到 {target.id} 。")
|
await log(f"已成功配置将对话 {source.id} 的新消息转发到 {target.id} 。")
|
||||||
elif message.parameter[0] == "del":
|
|
||||||
|
|
||||||
|
@shift_func.sub_command(command="del")
|
||||||
|
async def shift_func_del(message: Message):
|
||||||
if len(message.parameter) != 2:
|
if len(message.parameter) != 2:
|
||||||
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||||
# 检查来源频道
|
# 检查来源频道
|
||||||
try:
|
try:
|
||||||
source = await client.get_chat(
|
source = try_cast_or_fallback(message.parameter[1], int)
|
||||||
try_cast_or_fallback(message.parameter[1], int)
|
assert isinstance(source, int)
|
||||||
)
|
|
||||||
assert isinstance(source, Chat)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return await message.edit("出错了呜呜呜 ~ 无法识别的来源对话。")
|
return await message.edit("出错了呜呜呜 ~ 无法识别的来源对话。")
|
||||||
try:
|
try:
|
||||||
del sqlite[f"shift.{source.id}"]
|
del sqlite[f"shift.{source}"]
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
del sqlite[f"shift.{source.id}.options"]
|
del sqlite[f"shift.{source}.options"]
|
||||||
except Exception:
|
except Exception:
|
||||||
return await message.edit("emm...当前对话不存在于自动转发列表中。")
|
return await message.edit("emm...当前对话不存在于自动转发列表中。")
|
||||||
await message.edit(f"已成功关闭对话 {str(source.id)} 的自动转发功能。")
|
await message.edit(f"已成功关闭对话 {str(source)} 的自动转发功能。")
|
||||||
await log(f"已成功关闭对话 {str(source.id)} 的自动转发功能。")
|
await log(f"已成功关闭对话 {str(source)} 的自动转发功能。")
|
||||||
elif message.parameter[0] == "backup":
|
|
||||||
|
|
||||||
|
@shift_func.sub_command(command="backup")
|
||||||
|
async def shift_func_backup(client: Client, message: Message):
|
||||||
if len(message.parameter) < 3:
|
if len(message.parameter) < 3:
|
||||||
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
return await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
||||||
options = set(message.parameter[3:] if len(message.parameter) > 3 else ())
|
options = set(message.parameter[3:] if len(message.parameter) > 3 else ())
|
||||||
@ -108,9 +124,7 @@ async def shift_set(client: Client, message: Message):
|
|||||||
return await message.edit("出错了呜呜呜 ~ 无法识别的选项。")
|
return await message.edit("出错了呜呜呜 ~ 无法识别的选项。")
|
||||||
# 检查来源频道
|
# 检查来源频道
|
||||||
try:
|
try:
|
||||||
source = await client.get_chat(
|
source = await client.get_chat(try_cast_or_fallback(message.parameter[1], int))
|
||||||
try_cast_or_fallback(message.parameter[1], int)
|
|
||||||
)
|
|
||||||
assert isinstance(source, Chat)
|
assert isinstance(source, Chat)
|
||||||
check_chat_available(source)
|
check_chat_available(source)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -119,9 +133,7 @@ async def shift_set(client: Client, message: Message):
|
|||||||
return await message.edit("出错了呜呜呜 ~ 此对话位于白名单中。")
|
return await message.edit("出错了呜呜呜 ~ 此对话位于白名单中。")
|
||||||
# 检查目标频道
|
# 检查目标频道
|
||||||
try:
|
try:
|
||||||
target = await client.get_chat(
|
target = await client.get_chat(try_cast_or_fallback(message.parameter[2], int))
|
||||||
try_cast_or_fallback(message.parameter[2], int)
|
|
||||||
)
|
|
||||||
assert isinstance(target, Chat)
|
assert isinstance(target, Chat)
|
||||||
except Exception:
|
except Exception:
|
||||||
return await message.edit("出错了呜呜呜 ~ 无法识别的目标对话。")
|
return await message.edit("出错了呜呜呜 ~ 无法识别的目标对话。")
|
||||||
@ -139,12 +151,15 @@ async def shift_set(client: Client, message: Message):
|
|||||||
message,
|
message,
|
||||||
msg,
|
msg,
|
||||||
target.id,
|
target.id,
|
||||||
options,
|
list(options),
|
||||||
disable_notification="silent" in options,
|
disable_notification="silent" in options,
|
||||||
)
|
)
|
||||||
await message.edit(f"备份频道 {source.id} 到 {target.id} 已完成。")
|
await message.edit(f"备份频道 {source.id} 到 {target.id} 已完成。")
|
||||||
# 列出要轉存的頻道
|
|
||||||
elif message.parameter[0] == "list":
|
|
||||||
|
# 列出要轉存的頻道
|
||||||
|
@shift_func.sub_command(command="list")
|
||||||
|
async def shift_func_list(message: Message):
|
||||||
from_ids = list(
|
from_ids = list(
|
||||||
filter(
|
filter(
|
||||||
lambda x: (x.startswith("shift.") and (not x.endswith("options"))),
|
lambda x: (x.startswith("shift.") and (not x.endswith("options"))),
|
||||||
@ -161,9 +176,6 @@ async def shift_set(client: Client, message: Message):
|
|||||||
format_channel_id(to_id),
|
format_channel_id(to_id),
|
||||||
)
|
)
|
||||||
await message.edit(output)
|
await message.edit(output)
|
||||||
else:
|
|
||||||
await message.edit(f"{lang('error_prefix')}{lang('arg_error')}")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def format_channel_id(channel_id: str):
|
def format_channel_id(channel_id: str):
|
||||||
@ -174,62 +186,123 @@ def format_channel_id(channel_id: str):
|
|||||||
@listener(is_plugin=True, incoming=True, ignore_edited=True)
|
@listener(is_plugin=True, incoming=True, ignore_edited=True)
|
||||||
async def shift_channel_message(message: Message):
|
async def shift_channel_message(message: Message):
|
||||||
"""Event handler to auto forward channel messages."""
|
"""Event handler to auto forward channel messages."""
|
||||||
d = dict(sqlite)
|
|
||||||
source = message.chat.id
|
source = message.chat.id
|
||||||
|
target = sqlite.get(f"shift.{source}")
|
||||||
# 找訊息類型video、document...
|
|
||||||
media_type = message.media.value if message.media else "text"
|
|
||||||
target = d.get(f"shift.{source}")
|
|
||||||
if not target:
|
if not target:
|
||||||
return
|
return
|
||||||
if message.chat.has_protected_content:
|
if message.chat.has_protected_content:
|
||||||
del sqlite[f"shift.{source}"]
|
del sqlite[f"shift.{source}"]
|
||||||
return
|
return
|
||||||
options = d.get(f"shift.{source}.options") or []
|
options = sqlite.get(f"shift.{source}.options") or []
|
||||||
|
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
if (not options) or "all" in options:
|
if message.media_group_id:
|
||||||
await message.forward(
|
add_or_replace_forward_group_media(
|
||||||
target,
|
target,
|
||||||
|
source,
|
||||||
|
message.id,
|
||||||
|
message.media_group_id,
|
||||||
|
options,
|
||||||
disable_notification="silent" in options,
|
disable_notification="silent" in options,
|
||||||
)
|
)
|
||||||
elif media_type in options:
|
return
|
||||||
await message.forward(
|
await loosely_forward(
|
||||||
|
None,
|
||||||
|
message,
|
||||||
target,
|
target,
|
||||||
|
options,
|
||||||
disable_notification="silent" in options,
|
disable_notification="silent" in options,
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
logs.debug("skip message type: %s", media_type)
|
|
||||||
|
|
||||||
|
|
||||||
async def loosely_forward(
|
async def loosely_forward(
|
||||||
notifier: Message,
|
notifier: Optional[Message],
|
||||||
message: Message,
|
message: Message,
|
||||||
chat_id: int,
|
chat_id: int,
|
||||||
options: Union[List[str], Set[str]],
|
options: List[AVAILABLE_OPTIONS_TYPE],
|
||||||
disable_notification: bool = False,
|
disable_notification: bool = False,
|
||||||
):
|
):
|
||||||
# 找訊息類型video、document...
|
# 找訊息類型video、document...
|
||||||
media_type = message.media.value if message.media else "text"
|
media_type = message.media.value if message.media else "text"
|
||||||
try:
|
|
||||||
if (not options) or "all" in options:
|
if (not options) or "all" in options:
|
||||||
await message.forward(
|
await forward_messages(
|
||||||
chat_id,
|
chat_id, message.chat.id, [message.id], disable_notification, notifier
|
||||||
disable_notification=disable_notification,
|
|
||||||
)
|
)
|
||||||
elif media_type in options:
|
elif media_type in options:
|
||||||
await message.forward(
|
await forward_messages(
|
||||||
chat_id,
|
chat_id, message.chat.id, [message.id], disable_notification, notifier
|
||||||
disable_notification=disable_notification,
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logs.debug("skip message type: %s", media_type)
|
logs.debug("skip message type: %s", media_type)
|
||||||
# await message.forward(chat_id, disable_notification=disable_notification)
|
|
||||||
|
|
||||||
|
async def forward_messages(
|
||||||
|
cid: int,
|
||||||
|
from_id: int,
|
||||||
|
message_ids: List[int],
|
||||||
|
disable_notification: bool,
|
||||||
|
notifier: Optional["Message"],
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
await bot.forward_messages(
|
||||||
|
cid, from_id, message_ids, disable_notification=disable_notification
|
||||||
|
)
|
||||||
except FloodWait as ex:
|
except FloodWait as ex:
|
||||||
min: int = ex.value # type: ignore
|
min_time: int = ex.value # type: ignore
|
||||||
delay = min + uniform(0.5, 1.0)
|
delay = min_time + uniform(0.5, 1.0)
|
||||||
|
if notifier:
|
||||||
await notifier.edit(f"触发 Flood ,暂停 {delay} 秒。")
|
await notifier.edit(f"触发 Flood ,暂停 {delay} 秒。")
|
||||||
await sleep(delay)
|
await sleep(delay)
|
||||||
await loosely_forward(notifier, message, chat_id, options, disable_notification)
|
await forward_messages(
|
||||||
|
cid, from_id, message_ids, disable_notification, notifier
|
||||||
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # drop other errors
|
pass # drop other errors
|
||||||
|
|
||||||
|
|
||||||
|
async def forward_group_media(
|
||||||
|
cid: int,
|
||||||
|
from_id: int,
|
||||||
|
group_id: int,
|
||||||
|
options: List[AVAILABLE_OPTIONS_TYPE],
|
||||||
|
disable_notification: bool,
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
msgs = await bot.get_media_group(from_id, group_id)
|
||||||
|
except Exception:
|
||||||
|
logs.debug("get_media_group failed for %d %d", from_id, group_id)
|
||||||
|
return
|
||||||
|
real_msgs = []
|
||||||
|
for message in msgs:
|
||||||
|
media_type = message.media.value if message.media else "text"
|
||||||
|
if (not options) or "all" in options:
|
||||||
|
real_msgs.append(message)
|
||||||
|
elif media_type in options:
|
||||||
|
real_msgs.append(message)
|
||||||
|
else:
|
||||||
|
logs.debug("skip message type: %s", media_type)
|
||||||
|
if not real_msgs:
|
||||||
|
return
|
||||||
|
real_msgs_ids = [msg.id for msg in real_msgs]
|
||||||
|
await forward_messages(cid, from_id, real_msgs_ids, disable_notification, None)
|
||||||
|
|
||||||
|
|
||||||
|
def add_or_replace_forward_group_media(
|
||||||
|
cid: int,
|
||||||
|
from_id: int,
|
||||||
|
message_id: int,
|
||||||
|
group_id: int,
|
||||||
|
options: List[AVAILABLE_OPTIONS_TYPE],
|
||||||
|
disable_notification: bool,
|
||||||
|
):
|
||||||
|
key = f"shift.forward_group_media.{group_id}"
|
||||||
|
scheduler.add_job(
|
||||||
|
forward_group_media,
|
||||||
|
trigger="date",
|
||||||
|
args=(cid, from_id, message_id, options, disable_notification),
|
||||||
|
id=key,
|
||||||
|
name=key,
|
||||||
|
replace_existing=True,
|
||||||
|
run_date=datetime.datetime.now(pytz.timezone(Config.TIME_ZONE))
|
||||||
|
+ datetime.timedelta(seconds=4),
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user