Compare commits

...
15 Commits
Author SHA1 Message Date
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
YoursFunny 18f1f00259 fix docker compose file 2024-03-22 19:46:30 +08:00
YoursFunny 04da6eb3d9 fix reply message 2024-03-22 19:45:26 +08:00
YoursFunny 7a35b06d4e fix channel check 2024-03-22 19:04:30 +08:00
YoursFunny a5ae2321c5 fix regex pattern 2024-03-22 19:02:38 +08:00
YoursFunny d263071946 add assert message 2024-03-22 18:57:59 +08:00
YoursFunny 0491d8c3fc fix pers_data 2024-03-22 18:55:48 +08:00
YoursFunny 3afea136a4 update docker.yml 2024-03-22 18:41:09 +08:00
YoursFunny 87108b2ac8 fix await 2024-03-22 18:41:07 +08:00
YoursFunny 4613e4c825 remove version in compose 2024-03-22 17:56:59 +08:00
YoursFunny eb1016f137 fix typo 2024-03-22 17:49:38 +08:00
YoursFunny 5059a4d04a update docker.yml 2024-03-22 17:43:00 +08:00
YoursFunny c85c6191ad update docker.yml 2024-03-22 17:34:11 +08:00
5 changed files with 47 additions and 39 deletions
+15 -8
View File
@@ -4,6 +4,8 @@ on:
push:
tags:
- v*
branches:
- master
env:
APP_NAME: telegram-twitter-media-bot
@@ -13,6 +15,17 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKERHUB_REPO }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}.{{patch}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -25,18 +38,12 @@ jobs:
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Generate APP Version
run: echo APP_VERSION=`git describe --tags --always` >> $GITHUB_ENV
-
name: Build and push
uses: docker/build-push-action@v5
with:
push: true
platforms: |
linux/amd64
build-args: |
APP_NAME=${{ env.APP_NAME }}
APP_VERSION=${{ env.APP_VERSION }}
tags: |
${{ env.DOCKERHUB_REPO }}:latest
${{ env.DOCKERHUB_REPO }}:${{ env.APP_VERSION }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+3 -3
View File
@@ -1,9 +1,9 @@
import logging
import re
import os
import re
BOT_TOKEN = os.getenv("BOT_TOKEN")
ADMIN = os.getenv("ADMIN").split(",")
ADMIN = os.getenv("BOT_ADMIN").split(",")
WEBHOOK = os.getenv("WEBHOOK", False)
if WEBHOOK:
@@ -14,7 +14,7 @@ if WEBHOOK:
WEBHOOK_CERT = os.getenv("WEBHOOK_CERT", "cert/cert.pem")
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_tco_regex = re.compile(r"(?:https?://)t\.co/.+$", re.M)
+2 -2
View File
@@ -1,4 +1,3 @@
version: '3.7'
services:
tgxmb: image: yoursfunny/telegram-twitter-media-bot: latest
restart: always
@@ -16,6 +15,7 @@ services:
WEBHOOK_CERT: './cert/cert.pem'
WEBHOOK_SECRET_TOKEN: 'secret-token'
# LOG_LEVEL: 'WARNING'
# volumes:
volumes:
- ./pers_data: /app/pers_data
# - ./cert:/app/cert
container_name: tgxmb
+12 -13
View File
@@ -1,6 +1,6 @@
from aiohttp import ClientSession
from telegram import Update, Chat
from telegram.constants import ParseMode, ChatAction
from telegram.constants import ParseMode, ChatAction, ChatType
from telegram.ext import (
Application,
ApplicationBuilder,
@@ -9,7 +9,8 @@ from telegram.ext import (
filters,
InlineQueryHandler,
PicklePersistence,
MessageHandler, CommandHandler
MessageHandler,
CommandHandler
)
import common
@@ -32,8 +33,9 @@ async def reply_media(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
async with TGTweet(context.bot_data['client'], url) as tweet:
media = list(tweet.pm_media_generator)
message_sent = await update.effective_message.reply_media_group(
media, caption=tweet.message_text,
# reply_to_message_id=update.message.message_id
media,
caption=tweet.message_text,
reply_to_message_id=update.message.message_id
)
if 'forward_channel_id' in context.user_data:
try:
@@ -52,19 +54,20 @@ async def cmd_set_forward_channel(update: Update, context: ContextTypes.DEFAULT_
return
channel = context.args[0]
try:
channel: Chat = context.bot.get_chat(channel)
channel: Chat = await context.bot.get_chat(channel)
except Exception as e:
await update.effective_message.reply_text(str(e))
return
if channel.type != "CHANNEL":
if channel.type != ChatType.CHANNEL:
await update.effective_message.reply_text("That is not a channel.")
return
try:
channel_admin = await channel.get_administrators()
except Exception as e:
await update.effective_message.reply_text(str(e) + "\nPlease add the bot to the channel and set as admin")
return
user_bot = filter(lambda x: x.user.id == context.bot.id, channel_admin)
user_bot = next(user_bot, None)
if not user_bot:
await update.effective_message.reply_text("I am not an admin in that channel.")
return
if user_bot.can_post_messages:
context.user_data['forward_channel_id'] = channel.id
await update.effective_message.reply_text("Add successfully.")
@@ -101,7 +104,6 @@ async def post_shutdown(application: Application) -> None:
def main():
defaults = Defaults(parse_mode=ParseMode.HTML, allow_sending_without_reply=True)
persistence = PicklePersistence(filepath='pers_data')
# proxy_url = 'http://127.0.0.1:10809'
application = (ApplicationBuilder()
.token(common.BOT_TOKEN)
.defaults(defaults)
@@ -109,8 +111,6 @@ def main():
.post_init(post_init)
.post_stop(post_stop)
.post_shutdown(post_shutdown)
# .proxy(proxy_url)
# .get_updates_proxy(proxy_url)
.build()
)
@@ -119,7 +119,6 @@ def main():
handlers = [
MessageHandler(filters.Regex(common.x_url_regex) & filters.ChatType.PRIVATE, reply_media),
# MessageHandler(None, reply_media),
InlineQueryHandler(inline_query, common.x_url_regex),
CommandHandler("set_forward_channel", cmd_set_forward_channel),
CommandHandler("remove_forward_channel", cmd_remove_forward_channel),
+14 -12
View File
@@ -7,10 +7,11 @@ from telegram import (
InputMediaPhoto,
InputMediaVideo
)
from common import x_url_regex, x_media_regex, x_tco_regex
twimg_url = 'https://pbs.twimg.com/'
vx_api_url = 'https://api.vxtwitter.com/status/'
vx_api_url = 'https://api.vxtwitter.com/status/{0}/status/{1}'
message_raw_text = """{url}
<a href="{author_url}">{author}</a>: {text}
@@ -19,7 +20,7 @@ message_raw_text = """{url}
async def fetch_json(session: ClientSession, url: str) -> dict:
async with session.get(url) as response:
assert response.status == 200
assert response.status == 200, f"Failed to fetch {url}, status code {response.status}"
return await response.json()
@@ -107,25 +108,25 @@ class TGTweet(Tweet):
def __init__(self, session: ClientSession, url: str):
self._session: ClientSession = session
self._url: str = url
self._id: str = self._tweet_id
assert self._id
self._api_param: tuple[str] = self._tweet_id
assert self._api_param
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)
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
pass
async def _fetch_tweet(self, tweet_id: str) -> dict:
return await fetch_json(self._session, vx_api_url + tweet_id)
async def _fetch_tweet(self, api_param: tuple[str]) -> dict:
return await fetch_json(self._session, vx_api_url.format(*api_param))
@property
def _tweet_id(self) -> str | None:
def _tweet_id(self) -> tuple[str] | None:
match = x_url_regex.match(self._url)
if match:
return match.group(1).strip('/')
return match.groups()
return None
@property
@@ -146,12 +147,13 @@ class TGTweet(Tweet):
@property
def _init_properties(self) -> tuple:
id = self._tweet['tweetID']
author = self._tweet['user_name']
author_id = self._tweet['user_screen_name']
text = self._tweet_text
media = self._tweet_media
sensitive = self._tweet['possibly_sensitive']
return self._id, author, author_id, text, media, sensitive
return id, author, author_id, text, media, sensitive
@property
def message_text(self) -> str:
@@ -167,7 +169,7 @@ class TGTweet(Tweet):
for i, tweet_media in enumerate(self.media):
if tweet_media.type == "image":
yield InlineQueryResultPhoto(
id=self.id,
id=str(i),
photo_url=tweet_media.url,
thumbnail_url=tweet_media.thumb,
title=self.url,
@@ -176,7 +178,7 @@ class TGTweet(Tweet):
)
elif tweet_media.type == "video":
yield InlineQueryResultVideo(
id=self.id,
id=str(i),
video_url=tweet_media.url,
mime_type="video/mp4",
thumbnail_url=tweet_media.thumb,