Compare commits

...
8 Commits
Author SHA1 Message Date
YoursFunny 985fe3fbfe update api format and logger 2024-03-22 22:45:52 +08:00
YoursFunny 19fb5b9822 fix logger 2024-03-22 22:34:59 +08:00
YoursFunny 1185d4bc5f fix logger 2024-03-22 22:26:31 +08:00
YoursFunny c3faecf640 add logger 2024-03-22 22:18:43 +08:00
YoursFunny 76e0ffe58c fix image suffix 2024-03-22 21:32:32 +08:00
YoursFunny a38c1b05b4 fix twitter id 2024-03-22 21:11:19 +08:00
YoursFunny b3c9b1ace7 fix api request 2024-03-22 21:03:25 +08:00
YoursFunny 6a7ab11148 fix query id duplicate 2024-03-22 20:13:46 +08:00
3 changed files with 28 additions and 17 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ if WEBHOOK:
WEBHOOK_CERT = os.getenv("WEBHOOK_CERT", "cert/cert.pem") WEBHOOK_CERT = os.getenv("WEBHOOK_CERT", "cert/cert.pem")
WEBHOOK_SECRET_TOKEN = os.getenv("WEBHOOK_SECRET_TOKEN") WEBHOOK_SECRET_TOKEN = os.getenv("WEBHOOK_SECRET_TOKEN")
x_url_regex = re.compile(r"^(?:https?://)(?:www\.|mobile\.|)(?:x|twitter)\.com/.+/status/(\d+)") 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_media_regex = re.compile(r"^(?:https?://)(pbs|video)\.twimg\.com/(.*)")
x_tco_regex = re.compile(r"(?:https?://)t\.co/.+$", re.M) x_tco_regex = re.compile(r"(?:https?://)t\.co/.+$", re.M)
+6 -2
View File
@@ -9,7 +9,8 @@ from telegram.ext import (
filters, filters,
InlineQueryHandler, InlineQueryHandler,
PicklePersistence, PicklePersistence,
MessageHandler, CommandHandler MessageHandler,
CommandHandler
) )
import common import common
@@ -20,6 +21,7 @@ async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
query = update.inline_query.query query = update.inline_query.query
if query == "": if query == "":
return return
common.logger.info(f"Query: {query}")
async with TGTweet(context.bot_data['client'], query) as tweet: async with TGTweet(context.bot_data['client'], query) as tweet:
result = list(tweet.inline_query_generator) result = list(tweet.inline_query_generator)
await update.inline_query.answer(result) await update.inline_query.answer(result)
@@ -29,10 +31,12 @@ async def reply_media(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
await update.effective_chat.send_action(ChatAction.UPLOAD_PHOTO) await update.effective_chat.send_action(ChatAction.UPLOAD_PHOTO)
# url = update.message.text.split(" ")[0] # url = update.message.text.split(" ")[0]
url = update.message.text url = update.message.text
common.logger.info(f"Receiving url: {url}")
async with TGTweet(context.bot_data['client'], url) as tweet: async with TGTweet(context.bot_data['client'], url) as tweet:
media = list(tweet.pm_media_generator) media = list(tweet.pm_media_generator)
message_sent = await update.effective_message.reply_media_group( message_sent = await update.effective_message.reply_media_group(
media, caption=tweet.message_text, media,
caption=tweet.message_text,
reply_to_message_id=update.message.message_id reply_to_message_id=update.message.message_id
) )
if 'forward_channel_id' in context.user_data: if 'forward_channel_id' in context.user_data:
+21 -14
View File
@@ -8,10 +8,10 @@ from telegram import (
InputMediaVideo InputMediaVideo
) )
from common import x_url_regex, x_media_regex, x_tco_regex from common import x_url_regex, x_media_regex, x_tco_regex, logger
twimg_url = 'https://pbs.twimg.com/' twimg_url = 'https://pbs.twimg.com/'
vx_api_url = 'https://api.vxtwitter.com/status/' vx_api_url = 'https://api.vxtwitter.com/{0}/status/{1}'
message_raw_text = """{url} message_raw_text = """{url}
<a href="{author_url}">{author}</a>: {text} <a href="{author_url}">{author}</a>: {text}
@@ -19,6 +19,7 @@ message_raw_text = """{url}
async def fetch_json(session: ClientSession, url: str) -> dict: async def fetch_json(session: ClientSession, url: str) -> dict:
logger.info(f"Fetching {url}")
async with session.get(url) as response: async with session.get(url) as response:
assert response.status == 200, f"Failed to fetch {url}, status code {response.status}" assert response.status == 200, f"Failed to fetch {url}, status code {response.status}"
return await response.json() return await response.json()
@@ -30,18 +31,21 @@ class TweetMedia:
self._thumb: str = thumb self._thumb: str = thumb
self._type: str = media_type self._type: str = media_type
def __str__(self):
return f"Media[url: {self.url} thumb: {self.thumb} type: {self.type}]"
@property @property
def _uri(self) -> str | None: def _uri(self) -> str | None:
match = x_media_regex.match(self._url) match = x_media_regex.match(self._url)
if match: if match:
return match.group(2).removesuffix('.jpg') return match.group(2).removesuffix('.jpg').removesuffix('.png')
return None return None
@property @property
def url(self) -> str: def url(self) -> str:
match self._type: match self._type:
case "image": case "image":
return f"{twimg_url}{self._uri}?format=jpg&name=orig" return f"{twimg_url}{self._uri}?format=jpg&name=4096x4096"
case "video": case "video":
return self._url return self._url
@@ -108,25 +112,25 @@ class TGTweet(Tweet):
def __init__(self, session: ClientSession, url: str): def __init__(self, session: ClientSession, url: str):
self._session: ClientSession = session self._session: ClientSession = session
self._url: str = url self._url: str = url
self._id: str = self._tweet_id self._api_param: tuple[str] = self._tweet_id
assert self._id assert self._api_param
async def __aenter__(self): async def __aenter__(self):
self._tweet: dict = await self._fetch_tweet(self._id) self._tweet: dict = await self._fetch_tweet(self._api_param)
super().__init__(*self._init_properties) super().__init__(*self._init_properties)
return self return self
async def __aexit__(self, exc_type, exc_val, exc_tb): async def __aexit__(self, exc_type, exc_val, exc_tb):
pass pass
async def _fetch_tweet(self, tweet_id: str) -> dict: async def _fetch_tweet(self, api_param: tuple[str]) -> dict:
return await fetch_json(self._session, vx_api_url + tweet_id) return await fetch_json(self._session, vx_api_url.format(*api_param))
@property @property
def _tweet_id(self) -> str | None: def _tweet_id(self) -> tuple[str] | None:
match = x_url_regex.match(self._url) match = x_url_regex.match(self._url)
if match: if match:
return match.group(1).strip('/') return match.groups()
return None return None
@property @property
@@ -147,12 +151,13 @@ class TGTweet(Tweet):
@property @property
def _init_properties(self) -> tuple: def _init_properties(self) -> tuple:
id = self._tweet['tweetID']
author = self._tweet['user_name'] author = self._tweet['user_name']
author_id = self._tweet['user_screen_name'] author_id = self._tweet['user_screen_name']
text = self._tweet_text text = self._tweet_text
media = self._tweet_media media = self._tweet_media
sensitive = self._tweet['possibly_sensitive'] sensitive = self._tweet['possibly_sensitive']
return self._id, author, author_id, text, media, sensitive return id, author, author_id, text, media, sensitive
@property @property
def message_text(self) -> str: def message_text(self) -> str:
@@ -166,9 +171,10 @@ class TGTweet(Tweet):
@property @property
def inline_query_generator(self) -> Generator[InlineQueryResultPhoto | InlineQueryResultVideo, None, None]: def inline_query_generator(self) -> Generator[InlineQueryResultPhoto | InlineQueryResultVideo, None, None]:
for i, tweet_media in enumerate(self.media): for i, tweet_media in enumerate(self.media):
logger.info(str(tweet_media))
if tweet_media.type == "image": if tweet_media.type == "image":
yield InlineQueryResultPhoto( yield InlineQueryResultPhoto(
id=self.id, id=str(i),
photo_url=tweet_media.url, photo_url=tweet_media.url,
thumbnail_url=tweet_media.thumb, thumbnail_url=tweet_media.thumb,
title=self.url, title=self.url,
@@ -177,7 +183,7 @@ class TGTweet(Tweet):
) )
elif tweet_media.type == "video": elif tweet_media.type == "video":
yield InlineQueryResultVideo( yield InlineQueryResultVideo(
id=self.id, id=str(i),
video_url=tweet_media.url, video_url=tweet_media.url,
mime_type="video/mp4", mime_type="video/mp4",
thumbnail_url=tweet_media.thumb, thumbnail_url=tweet_media.thumb,
@@ -189,6 +195,7 @@ class TGTweet(Tweet):
@property @property
def pm_media_generator(self) -> Generator[InputMediaPhoto | InputMediaVideo, None, None]: def pm_media_generator(self) -> Generator[InputMediaPhoto | InputMediaVideo, None, None]:
for tweet_media in self.media: for tweet_media in self.media:
logger.info(str(tweet_media))
if tweet_media.type == "image": if tweet_media.type == "image":
yield InputMediaPhoto( yield InputMediaPhoto(
media=tweet_media.url, media=tweet_media.url,