Compare commits

..
19 Commits
Author SHA1 Message Date
YoursFunny 85d0257c51 feat: change forward confirm reply markup 2024-04-28 01:08:22 +08:00
YoursFunny 7f90670f1c fix edit message html escape 2024-04-28 01:01:59 +08:00
YoursFunny 755c405196 update ptb version 2024-04-26 15:49:52 +08:00
YoursFunny 0ffa9903c4 add hint 2024-04-26 15:19:04 +08:00
YoursFunny 248e7d48e0 fix caption of multiple inline query results 2024-04-26 15:15:13 +08:00
YoursFunny e915cd13de fix html escape 2024-04-26 15:13:38 +08:00
YoursFunny a7d144f2ee fix multiple media forward 2024-03-25 16:54:08 +08:00
YoursFunny 081ee595b1 remove edit reply 2024-03-24 22:54:23 +08:00
YoursFunny 4272454f9a fix url match 2024-03-24 22:33:36 +08:00
YoursFunny 7d289c9db7 fix multiple line substitution 2024-03-24 22:32:22 +08:00
YoursFunny 500ba14565 fix caption text substitute 2024-03-24 22:15:06 +08:00
YoursFunny 1cb64b64e2 fix edit enable 2024-03-24 21:59:55 +08:00
YoursFunny 8ad9078c5e fix edit enable 2024-03-24 21:54:50 +08:00
YoursFunny ebfaaad75a fix message handler filter 2024-03-24 21:46:32 +08:00
YoursFunny fdd21e22ed add command handler 2024-03-24 21:20:34 +08:00
YoursFunny ee92b8d8aa add edit before forward 2024-03-24 21:17:05 +08:00
YoursFunny 50161243ea simplify send action 2024-03-24 16:45:42 +08:00
YoursFunny 7846873b9c fix video title 2024-03-24 01:03:39 +08:00
YoursFunny 6d06e28598 fix gif media 2024-03-23 15:01:17 +08:00
4 changed files with 122 additions and 26 deletions
+1
View File
@@ -17,6 +17,7 @@ if WEBHOOK:
x_url_regex = re.compile(r"^(?:https?://)(?:www\.|mobile\.|)(?:x|twitter)\.com/(.+)/status/(\d+)")
x_media_regex = re.compile(r"^(?:https?://)(pbs|video)\.twimg\.com/(.*)")
x_tco_regex = re.compile(r"(?:https?://)t\.co/.+$", re.M)
message_url_regex = re.compile(r"\{.+\}", re.S)
logging.basicConfig(
level=os.getenv("LOG_LEVEL", "WARNING"),
+98 -17
View File
@@ -1,5 +1,8 @@
import html
from functools import wraps
from aiohttp import ClientSession
from telegram import Update, Chat
from telegram import Update, Chat, InlineKeyboardMarkup, InlineKeyboardButton, ForceReply, Message
from telegram.constants import ParseMode, ChatAction, ChatType
from telegram.ext import (
Application,
@@ -10,13 +13,25 @@ from telegram.ext import (
InlineQueryHandler,
PicklePersistence,
MessageHandler,
CommandHandler
CommandHandler, CallbackQueryHandler
)
import common
from tweet import TGTweet
def send_action(action):
def decorator(func):
@wraps(func)
async def command_func(update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
await update.effective_chat.send_action(action)
return await func(update, context, *args, **kwargs)
return command_func
return decorator
async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.inline_query.query
if query == "":
@@ -27,30 +42,79 @@ async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
await update.inline_query.answer(result)
async def reply_media(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_chat.send_action(ChatAction.UPLOAD_PHOTO)
# url = update.message.text.split(" ")[0]
@send_action(ChatAction.UPLOAD_PHOTO)
async def url_media(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
url = update.message.text
common.logger.info(f"Receiving url: {url}")
async with TGTweet(url) as tweet:
media = list(tweet.pm_media_generator)
message_sent = await update.effective_message.reply_media_group(
message_to_send = await update.effective_message.reply_media_group(
media,
caption=tweet.message_text,
reply_to_message_id=update.message.message_id
reply_to_message_id=update.message.message_id,
)
url = tweet.url
if context.user_data.get('edit_before_forward', False):
message_reply = await update.effective_message.reply_text(
"Reply to edit message.",
reply_markup=ForceReply(selective=True, input_field_placeholder="{URL}"),
reply_to_message_id=update.message.message_id,
)
context.user_data['message_reply'] = message_reply
context.user_data['message_to_send'] = message_to_send
context.user_data['message_url'] = url
return
if 'forward_channel_id' in context.user_data:
try:
await update.effective_chat.copy_messages(
chat_id=context.user_data['forward_channel_id'],
message_ids=[m.id for m in message_sent],
)
except Exception as e:
await update.effective_message.reply_text(str(e))
await forward_message(update, context, message_to_send)
async def forward_message(
update: Update,
context: ContextTypes.DEFAULT_TYPE,
message_to_send: tuple[Message, ...],
) -> None:
try:
await update.effective_chat.copy_messages(
context.user_data['forward_channel_id'],
[m.id for m in message_to_send]
)
except Exception as e:
await update.effective_message.reply_text(str(e))
async def edit_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if 'message_reply' not in context.user_data:
return
if update.message.reply_to_message != context.user_data['message_reply']:
return
update_text = update.message.text
match = common.message_url_regex.search(update_text)
if match:
match = match.span()
update_text = update_text[:match[0]] + '<a href="{0}">{1}</a>'.format(
context.user_data['message_url'], update_text[match[0] + 1:match[1] - 1]
) + update_text[match[1]:]
message_to_send = context.user_data['message_to_send']
await message_to_send[0].edit_caption(html.escape(update_text))
await context.user_data['message_reply'].edit_message_reply_markup(
InlineKeyboardMarkup.from_button(
InlineKeyboardButton("↩️ Confirm", callback_data="forward")
)
)
async def query_forward_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
message_to_send = context.user_data['message_to_send']
await forward_message(update, context, message_to_send)
await update.callback_query.answer('✅ Forwarded')
await update.callback_query.delete_message()
del context.user_data['message_reply']
del context.user_data['message_to_send']
del context.user_data['message_url']
@send_action(ChatAction.TYPING)
async def cmd_set_forward_channel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_chat.send_action(ChatAction.TYPING)
if not context.args:
await update.effective_message.reply_text("Please provide a channel username or id.")
return
@@ -75,8 +139,8 @@ async def cmd_set_forward_channel(update: Update, context: ContextTypes.DEFAULT_
await update.effective_message.reply_text("Add successfully.")
@send_action(ChatAction.TYPING)
async def cmd_remove_forward_channel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_chat.send_action(ChatAction.TYPING)
if 'forward_channel_id' in context.user_data:
del context.user_data['forward_channel_id']
await update.effective_message.reply_text("Remove successfully.")
@@ -84,6 +148,20 @@ async def cmd_remove_forward_channel(update: Update, context: ContextTypes.DEFAU
await update.effective_message.reply_text("No channel to remove.")
@send_action(ChatAction.TYPING)
async def cmd_edit_before_forward(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if context.user_data.get('forward_channel_id', None) is None:
await update.effective_message.reply_text("Please enable forward channel first.")
return
ebf_status = context.user_data.get('edit_before_forward', False)
if ebf_status:
context.user_data['edit_before_forward'] = False
await update.effective_message.reply_text("Disable edit before forward.")
return
context.user_data['edit_before_forward'] = True
await update.effective_message.reply_text("Enable edit before forward.")
async def post_init(application: Application) -> None:
# commands = [
# BotCommand('start', CMD_START),
@@ -120,10 +198,13 @@ def main():
# user_filter.add_user_ids(common.admin)
handlers = [
MessageHandler(filters.Regex(common.x_url_regex) & filters.ChatType.PRIVATE, reply_media),
MessageHandler(filters.Regex(common.x_url_regex) & filters.ChatType.PRIVATE, url_media),
InlineQueryHandler(inline_query, common.x_url_regex),
CommandHandler("set_forward_channel", cmd_set_forward_channel),
CommandHandler("remove_forward_channel", cmd_remove_forward_channel),
CommandHandler("edit_before_forward", cmd_edit_before_forward),
MessageHandler(~filters.COMMAND & filters.ChatType.PRIVATE, edit_message),
CallbackQueryHandler(query_forward_message, pattern="forward"),
]
application.add_handlers(handlers)
+1 -1
View File
@@ -1,2 +1,2 @@
python-telegram-bot[webhooks]~=21.0.1
python-telegram-bot[webhooks]~=21.1.1
aiohttp[speedups]~=3.9.3
+22 -8
View File
@@ -1,11 +1,14 @@
import html
from typing import Generator
from aiohttp import ClientSession
from telegram import (
InlineQueryResultPhoto,
InlineQueryResultVideo,
InlineQueryResultMpeg4Gif,
InputMediaPhoto,
InputMediaVideo, InputMediaAnimation, InlineQueryResultMpeg4Gif
InputMediaVideo,
InputMediaAnimation
)
from common import x_url_regex, x_media_regex, x_tco_regex, logger
@@ -48,6 +51,10 @@ class TweetMedia:
return f"{twimg_url}{self._uri}?format=jpg&name=4096x4096"
case "video":
return self._url
case "gif":
return self._url
case _:
return self._url
@property
def thumb(self) -> str:
@@ -56,6 +63,10 @@ class TweetMedia:
return f"{twimg_url}{self._uri}?format=jpg&name=thumb"
case "video":
return self._thumb
case "gif":
return self._thumb
case _:
return self._thumb
@property
def type(self) -> str:
@@ -173,12 +184,14 @@ class TGTweet(Tweet):
return message_raw_text.format(
url=self.url,
author_url=self.author_url,
author=self.author,
text=self.text
author=html.escape(self.author),
text=html.escape(self.text)
)
@property
def inline_query_generator(self) -> Generator[InlineQueryResultPhoto | InlineQueryResultVideo, None, None]:
def inline_query_generator(self) -> Generator[
InlineQueryResultPhoto | InlineQueryResultVideo | InlineQueryResultMpeg4Gif, None, None
]:
for i, tweet_media in enumerate(self.media):
logger.info(str(tweet_media))
if tweet_media.type == "image":
@@ -186,7 +199,7 @@ class TGTweet(Tweet):
id=str(i),
photo_url=tweet_media.url,
thumbnail_url=tweet_media.thumb,
caption=self.message_text if not i else None
caption=self.message_text
)
elif tweet_media.type == "video":
yield InlineQueryResultVideo(
@@ -194,18 +207,19 @@ class TGTweet(Tweet):
video_url=tweet_media.url,
mime_type="video/mp4",
thumbnail_url=tweet_media.thumb,
caption=self.message_text if not i else None
title=self.text,
caption=self.message_text
)
elif tweet_media.type == "gif":
yield InlineQueryResultMpeg4Gif(
id=str(i),
mpeg4_url=tweet_media.url,
thumbnail_url=tweet_media.thumb,
caption=self.message_text if not i else None
caption=self.message_text
)
@property
def pm_media_generator(self) -> Generator[InputMediaPhoto | InputMediaVideo, None, None]:
def pm_media_generator(self) -> Generator[InputMediaPhoto | InputMediaVideo | InputMediaAnimation, None, None]:
for tweet_media in self.media:
logger.info(str(tweet_media))
if tweet_media.type == "image":