diff --git a/base-config.yaml b/base-config.yaml index f0da8c9..1fb1bb2 100644 --- a/base-config.yaml +++ b/base-config.yaml @@ -12,4 +12,7 @@ instagram: youtube: enabled: True info: True - thumbnail: True \ No newline at end of file + thumbnail: True +tiktok: + enabled: True + video: True \ No newline at end of file diff --git a/socialmediadownload.py b/socialmediadownload.py index fd5445f..8ad3ce4 100644 --- a/socialmediadownload.py +++ b/socialmediadownload.py @@ -4,6 +4,10 @@ import instaloader import urllib import yarl +import requests +import asyncio +import concurrent.futures + from typing import Type from urllib.parse import quote @@ -13,16 +17,17 @@ from maubot import Plugin, MessageEvent from maubot.handlers import event - class Config(BaseProxyConfig): def do_update(self, helper: ConfigUpdateHelper) -> None: - for prefix in ["reddit", "instagram", "youtube"]: + for prefix in ["reddit", "instagram", "youtube", "tiktok"]: for suffix in ["enabled", "info", "image", "video", "thumbnail"]: helper.copy(f"{prefix}.{suffix}") reddit_pattern = re.compile(r"((?:https?:)?\/\/)?((?:www|m|old|nm)\.)?((?:reddit\.com|redd\.it))(\/r\/[^/]+\/(?:comments|s)\/[a-zA-Z0-9_\-]+)") instagram_pattern = re.compile(r"(?:https?:\/\/)?(?:www\.)?instagram\.com\/?([a-zA-Z0-9\.\_\-]+)?\/([p]+)?([reel]+)?([tv]+)?([stories]+)?\/([a-zA-Z0-9\-\_\.]+)\/?([0-9]+)?") youtube_pattern = re.compile(r"((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu\.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?") +tiktok_pattern = re.compile(r"((?:https?:)?\/\/)?((?:www|m|vm)\.)?((?:tiktok\.com))(\/[@a-zA-Z0-9\-\_\.]+)?(\/video\/)?([a-zA-Z0-9\-\_]+)?") + class SocialMediaDownloadPlugin(Plugin): async def start(self) -> None: @@ -52,6 +57,85 @@ async def on_message(self, evt: MessageEvent) -> None: if self.config["reddit.enabled"]: await self.handle_reddit(evt, url_tup) + for url_tup in tiktok_pattern.findall(evt.content.body): + await evt.mark_read() + if self.config["tiktok.enabled"]: + await self.handle_tiktok(evt, url_tup) + + async def get_ttdownloader_params(self, tokensDict, url) -> list: + cookies = { + 'PHPSESSID': tokensDict['PHPSESSID'] + } + headers = { + 'authority': 'ttdownloader.com', + 'accept': '*/*', + 'accept-language': 'en-US,en;q=0.9', + 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'origin': 'https://ttdownloader.com', + 'referer': 'https://ttdownloader.com/', + 'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'same-origin', + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36', + 'x-requested-with': 'XMLHttpRequest', + } + data = { + 'url': url, + 'format': '', + 'token': tokensDict['token'], + } + return cookies, headers, data + + def get_ttdownloader_tokens(self) -> dict: + tokens = {} + response = requests.get('https://ttdownloader.com/') + if response.status_code != 200: + self.log.warning(f"Unexpected status fetching tokens for ttdownloader.com: {response.status_code}") + return + + token_match = re.search(r'