From fea2efefc8031521be692c5a92f530a6919323b2 Mon Sep 17 00:00:00 2001 From: Jadowyne Ulve Date: Sun, 8 Jun 2025 10:44:58 -0500 Subject: [PATCH] Created and coded bridges between misskey, mattermost, and discord --- __pycache__/NarratorAi.cpython-312.pyc | Bin 2920 -> 2914 bytes __pycache__/NarratorAi.cpython-313.pyc | Bin 2890 -> 2885 bytes __pycache__/bridges.cpython-312.pyc | Bin 0 -> 6676 bytes __pycache__/discord.cpython-312.pyc | Bin 0 -> 8592 bytes __pycache__/mattermost_bridge.cpython-312.pyc | Bin 0 -> 4547 bytes __pycache__/mattermost_bridge.cpython-313.pyc | Bin 0 -> 2267 bytes __pycache__/misskey.cpython-312.pyc | Bin 0 -> 3127 bytes bridges.py | 189 ++++++++++++++++++ bot.py => discordapp.py | 77 ++++++- mattermost.app.py | 64 ++++++ misskey.app.py | 59 ++++++ test.json | 117 +++++++++++ test.py | 25 +++ test.txt | 1 + 14 files changed, 526 insertions(+), 6 deletions(-) create mode 100644 __pycache__/bridges.cpython-312.pyc create mode 100644 __pycache__/discord.cpython-312.pyc create mode 100644 __pycache__/mattermost_bridge.cpython-312.pyc create mode 100644 __pycache__/mattermost_bridge.cpython-313.pyc create mode 100644 __pycache__/misskey.cpython-312.pyc create mode 100644 bridges.py rename bot.py => discordapp.py (52%) create mode 100644 mattermost.app.py create mode 100644 misskey.app.py create mode 100644 test.json create mode 100644 test.py create mode 100644 test.txt diff --git a/__pycache__/NarratorAi.cpython-312.pyc b/__pycache__/NarratorAi.cpython-312.pyc index 053886a2e0474b50973e286adc705eb6cd2ec86f..561bde8c44ce2407e49d595b65e54e22ba575d8b 100644 GIT binary patch delta 54 zcmaDM_DGE9G%qg~0}%Z6ch1lc2tb}GcPX}0}x!fX1I}CpG8{B)hZ@AKP5FLFR`d7u_V7pHzl(;Ilm}HH)(Se H%Lg_9z!DMD delta 58 zcmX>qc1n!sc+=gXHn1(wTj6~Ovx{=%u9`N&QD2AN-Rz-j`2$@DoQNL MFLK%(%JP8?0Qv_L82|tP diff --git a/__pycache__/bridges.cpython-312.pyc b/__pycache__/bridges.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78ff3b822949da547bfb091551ef1185e2622aea GIT binary patch literal 6676 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 B4f6m1 literal 0 HcmV?d00001 diff --git a/__pycache__/discord.cpython-312.pyc b/__pycache__/discord.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe8b7ef237775c29a27b28ba6ccbe92010964b42 GIT binary patch literal 8592 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 literal 0 HcmV?d00001 diff --git a/__pycache__/mattermost_bridge.cpython-313.pyc b/__pycache__/mattermost_bridge.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66f17156b314404a56ab1b91cd88e5bc8b327be3 GIT binary patch literal 2267 zcmds3O-~y~7@pnr+KWE`^I^LNf}w<91a?q?K$JFzGz|q3ByW6ZL9y1}!8q8v%j}wB zD?;4jNR=X@R`gOe$MoOW3aVGrR%%r)y_wP<(3!={(u%gnN*&oV&%E=_`|*tD9iIgP zUO?LCYxlOkaRcxRo!E_UgR{p3dp2#{ty**A*v4Lwj?8AAPBeAvJN-P#iF{Y8xqnJ zIkkkN`9-9at2u33%U5JstxEFz(>bMFSVVCab7fS-yrFJGCC56Bfrns@e9!KXo+QF3 ztjH>y$SJP%3$@hc9c^jKrr<&g0MV6Z=GwXVWYog z@d{nXCSmc4^)`$CwEzFh;-yoJ+8jD#YRJJhO7n!RD}E7ax9Cf7qJNQzfjo!@9w8Um zQk~f{4DEI@`H#0XDQSh|?rc(1bwjUyM7QYwx@SvOxAo-C(>;B5etvI8L-X%dZp~!% zY8B4S@6G0L-{UKa17-^{<~IvPs8PA9S@}weoNq~w1i!c`oRLv-;iXQL6-6hE|AS#hm&MOrb+NO0pl7~jdc9gAT z6sZI=k|JjeD3z=kcEeH@$~xvXR8R~=?*60`pdkZ31W|B?0OhNgv`4ixgQhB{DxJM^Bk~lNYD!M@o)AP~4CXdSjFnf~+tETt; zgL`Jrrw1!1!I5TgvJsqY23H%w)%wF+9jb4GT79S72<{#%|I`&cSTa4G&-b72{~!cv z`IpKIPwKH-_0U3#2jRsQ;KH3PH|QET^>E=qf`+b9G)z!z zjH2tc2Q2{v`d_ZSSo`Y1cmA={eh?aKMS#%N^hC+Wimur?(&!vH7DmnJNHaQp9G$K$ zo8gh8{loqLB*KBj?-9WFH(k+&E8298H(cXpC}#FXkM17cHTwohW;d_ZUE{w2jvqcF zrv&0|L|=%@w?($zbwraVi(?lvKG~gdd*MO6yX6H;un9s95IP2tGuI7f*s}Tu>FM{_ literal 0 HcmV?d00001 diff --git a/__pycache__/misskey.cpython-312.pyc b/__pycache__/misskey.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8a36eb23412c8a601bc8502e27d65edb63ba16a GIT binary patch literal 3127 zcmcH*TW}NC^OJ&$|Ny?^p}st`P(U-V7<*@@5>^v8bKGV!Dc#7!h48K+RRgmDyG|Bk4` z!c3I0FdJn7J5pSlkMg+0D?|mEi8^IA>T)3BNc!ysDwsHl>n?Z4Q5uO>lj`J-%B)S@ zDHAeJC!-!&AkKG@?0lbzZW%|i>o+*+m8;%BQJ-85u!hvi?#aCfY1?64lx(&2R4|O! z*jn%4(l|!bcp3*iU((;X>fCH9aJ$ zX;T~=xqL2@>mnoF$4*>2crrdNpN{mVyS~#qekzs9N~eMjQ;5s5Ms(f83Dc2~b9`3U z!=0VEs!kpB#?uL9Jjj@ylq$tjXA)_WN+`tKIi6BSEB_PIqgq1Vm}S%Pgd&ygx4fXa zy9VEr9DpH&A%Dike6k#8i?a-7knR60nt@Ey2+Ix&GFA-h4bJ9I@-|h$Aj8`Eg9yU= zA(O>HZrEf;Re9QEjp-?3vWjXDGcYzOU5f9&lsvqDJhOjvEHNo%dV2J+Y&IKYO*W~k zipizaxU8E3^>du)WYXd``#YBJ~*FQ zb~nuRuL<&F8NgF|l6Do^1AvW<_}dZ(&^4&XAA;07%uVJe9EWB% zYj)UtpqbiXJ$>l4d4y)M%*H>7waF=Ew`|Nv+%)RHBb_&G~^7`*o0z6SknbDV+ai$mzfAK^>FcLcr$_&hDB3t7C7 zzjrK;4b?nqGWXw&u}gf zQ5A(q26Rc$P{mit=!hy!5+f7}cE^)$dxJZh{&nwu=pkIvbn8C6%jfTtfWd( zM$?EK7K1e=H>D*M!>r1ZQQh)d*XV{Z`Bz6`XJ7fg=`0(io7~Csv4K9*b8=v0WT^jq z?98d5erUzCiE2J7!pWKRly0&bkuF=E&#WR>Bx1R$o7*a8Ml37)sWEVL>C=joP)$xx z5i(`E`fZUQXSz15(&({a`Zq@}R*s(Ov}0ppqElZ*`e?Me&DwIFV$hIdsf2D2MGL_M zRi~@aEUc!yR<)(*XmGU@+%@^y(2BdWP~Ws#A6%*r-fdm3@A?Y)Jl#bK7S0!Z+wygx z6<_Dy8`~ZuPfhpyiFGl!-WDn}w-wrZ9|>$z;1MUZ*X8|ti$3(+?q7v|8M^ELec*#Y z{=iGi!GYz#;HrNx?;kAqcjR}5?;W}q%ty|yoclrk?1g;bwH5!xwLPKVUi|gN1dxXxk8ey589Hblum!ibTJ>lh$BJg$4A~nt7-U9TZ7e_jr zi$0#xb=APX*n}gU>|!%Z=~fI17uztUgP8JwEWi#6c3R_Id>S5Zd-1S9=_3O0 zf66x;uVX%KY3=tj_g%Q(&EK!$DDCAy=Y78$X77uw$7`4eJU;H?9|#KLF+XAJHS2_+T_`n5K2Qls6{6v}slQiZ@ywF+K`TbioT16iZzoawV`YG8Qe%+cXU zzt&_4pDbMtO(v~RYV?HGL<(s4)fy?F_X}%3)8&1L$u`~s{w&Hb0^*$x;nJvYhL#4{+!(dw;MK~^@2730m0: + text += new_contents + + text = parse_links_from_discord(text) + + response = mattermostDriver.posts.create_post(options={ + 'channel_id': channel_id, + 'props':{ + 'from_webhook': 'true', + 'override_username': message.author.nick, + 'override_icon_url': message.author.display_avatar.url + }, + 'message': text, + 'file_ids': file_ids}) + +def send_misskey_to_mattermost(event, channel_id): + if event['body']['body']['renoteId']: + files = event['body']['body']['renote'].get('files', None) + else: + files = event['body']['body'].get('files', None) + + file_ids=[] + if files != []: + for i, file in enumerate(files): + response = requests.get(file['url']) + file_data = BytesIO(response.content) + filename = file['name'] + file_id = mattermostDriver.files.upload_file( + channel_id=channel_id, + files={'files': (filename, file_data)} + )['file_infos'][0]['id'] + file_ids.append(file_id) + + if event['body']['body']['renoteId']: + renote_user = event['body']['body']['renote']['user'].get('name', 'unknown') + renote_username = event['body']['body']['renote']['user'].get('username', 'unknown') + renote_user_host = event['body']['body']['renote']['user'].get('hose', 'unknown') + note_content = f"*Renoted {renote_user} (@{renote_username}@{renote_user_host})*\n{event['body']['body']['renote']['text']}" + else: + note_content = event['body']['body'].get('text', 'No text in note') + + username = event['body']['body']['user'].get('name', 'Misskey Bot') + avatar_url = event['body']['body']['user'].get('avatarUrl', '') + + response = mattermostDriver.posts.create_post(options={ + 'channel_id': channel_id, + 'props':{ + 'from_webhook': 'true', + 'override_username':username, + 'override_icon_url': avatar_url + }, + 'message': note_content, + 'file_ids': file_ids}) \ No newline at end of file diff --git a/bot.py b/discordapp.py similarity index 52% rename from bot.py rename to discordapp.py index 9164140..1389df0 100644 --- a/bot.py +++ b/discordapp.py @@ -1,8 +1,11 @@ import discord -from discord import app_commands +#from discord import app_commands from NarratorAi import setScene, setItem, setRollDice import random - +import flask +import bridges +from threading import Thread +import requests guild_id = 954201387770736751 @@ -10,7 +13,9 @@ intents = discord.Intents.default() intents.message_content = True client = discord.Client(intents=intents) -tree = app_commands.CommandTree(client) +tree = discord.app_commands.CommandTree(client) + + @tree.command(name="roll_die", description="Ask NARC to roll dice for you with flair.", @@ -63,13 +68,73 @@ async def on_ready(): await tree.sync(guild=discord.Object(id=guild_id)) print(f'We have logged in as {client.user}') + +channels = { + 1125968295967850559: "our-comforter", #comforter + 954201387770736754: "lounge", #lounge + 1119502004721557554: "town-square", # kweh + 1367978276185964584: "misskey", #misskey + 1167176429797113926: "photos-from-another-star", #photos-from-another-star + 1119508652844404816: "bulletin-board", #bulletin-board + 955394194766192690: "photos-of-the-gang" #photos-of-the-gang +} + @client.event async def on_message(message): if message.author == client.user: return - if message.content.startswith('$hello'): - await message.channel.send('Hello!') + if not message.webhook_id and message.channel.id in channels.keys(): + bridges.send_discord_to_mattermost(message, channel_to=channels[message.channel.id]) + + +async def send_custom_message(channel: discord.TextChannel, message, username, user_id, avatar_url=None): + if user_id: + print(user_id) + member = await channel.guild.fetch_member(user_id) + avatar_url = member.display_avatar.url + username = member.nick + elif avatar_url: + avatar_url = avatar_url + else: + avatar_url = "" + + print(avatar_url) + webhook = await channel.create_webhook(name=username) + await webhook.send(message, username=username, avatar_url=avatar_url) + await webhook.delete() + +# flask +app = flask.Flask(__name__) + +@app.route('/post_message', methods=['POST']) +async def post_message(): + data:dict = flask.request.json + message = data.get('message') + username = data.get('username', 'Unknown') + avatar_url = data.get('avatar_url', None) + user_id = data.get('discord_id', None) + print(data) + if message == "": + return flask.jsonify({'error': 'Message cannot be blank.'}), 400 + + channel = client.get_channel(data['channel_to']) + if channel: + client.loop.create_task(send_custom_message(channel, message, username, user_id, avatar_url)) + #client.loop.create_task(channel.send(message)) + return flask.jsonify({'status': 'Message sent successfully.'}), 200 + else: + return flask.jsonify({'error': 'Channel not found.'}), 404 + +def run_flask_app(): + app.run(port=5001) + +# Run the Flask app in a separate thread +thread = Thread(target=run_flask_app) +thread.start() + token = "MTMyNzcxNDM3MTEyMzgxMDMwNA.GwLjEd.quGP0FA5gHRe1xLyuYq-ANuJ5cRuRQ6dhJiojI" -client.run(token) \ No newline at end of file +client.run(token) + + diff --git a/mattermost.app.py b/mattermost.app.py new file mode 100644 index 0000000..d2c2825 --- /dev/null +++ b/mattermost.app.py @@ -0,0 +1,64 @@ +import requests, json +from mattermostdriver import Driver +import bridges + +channels = { + "ibfp3fskai8adgmynbfispz3se": 1125968295967850559, #comforter + "rb43iupdy7rjbjwhg9w9c1mzjy": 954201387770736754, # lounge + "s6muherhotfoircc1yzmwr5wty": 1119502004721557554, # kweh + "fkcqa3qj83gu3bfikcu55sfwww": 1367978276185964584, #misskey + "na4doo5f83ykbc45m9a5dn513a": 1167176429797113926, #photos-from-another-star + "9ydcz9orepbtmedncb7idh43hr": 1119508652844404816, #bulletin-board + "81qmzfzeeif7mmfhpy7hkxnjuc": 955394194766192690 #photos-of-the-gang +} + +users = { + "f3nja8t9fpy73cxeh5ykzrozaw": 407247496008433675, + "3byr3scix3f78xs5bpmgqzc6pc": 189202462442389514 +} + +async def event_handler(event): + event = json.loads(event) + if 'event' in event.keys() and event['event'] == "posted": + print("event:", event) + event_data = event['data'] + post = event_data['post'] + + post = json.loads(post) + if post['channel_id'] in channels.keys(): + print(f"watched channel {post['channel_id']}") + if 'from_webhook' in post['props'].keys(): + is_webhook = post['props']['from_webhook'] + else: + is_webhook = "false" + print(is_webhook) + if is_webhook != "true": + # add file syncing means you need to get the "file_ids" key from the post and then download them into blobs and pass those along + # to the request as files, on the discord side those files would then get attached to the webhook. + + user = mattermostDriver.users.get_user(user_id=post['user_id']) + #print(user) + post['user'] = user + discord_id = None + print("user:", user) + if user['id'] in users.keys(): + discord_id = users[post['user']['id']] + post['discord_id'] = discord_id + bridges.send_mattermost_to_discord(post, channel_to=channels[post['channel_id']]) + elif post['channel_id'] == "fkcqa3qj83gu3bfikcu55sfwww" and is_webhook == "true": + username = post['props']['override_username'] + avatar_url = post['props']['override_icon_url'] + user = {"nickname": username} + post['user'] = user + post['discord_id'] = None + bridges.send_mattermost_to_discord(post, channel_to=channels[post['channel_id']], avatar_url=avatar_url) + +mattermostDriver = Driver({ + "url": "192.168.1.67", + "port": 8065, + "scheme": "http", + "token": "dmefeb8t7pditf3ot9377hrxch" +}) + +mattermostDriver.login() +mattermostDriver.init_websocket(event_handler) diff --git a/misskey.app.py b/misskey.app.py new file mode 100644 index 0000000..a7398ca --- /dev/null +++ b/misskey.app.py @@ -0,0 +1,59 @@ +import asyncio +import websockets +import misskey +import json +import requests +from io import BytesIO +import bridges + +MISSKEY_INSTANCE = "misskey.treehousefullofstars.com" +MISSKEY_TOKEN = "JSvVuz1eS2BGq6MagdQC9m109gOllwcO" + +msk = misskey.Misskey(address=MISSKEY_INSTANCE, i=MISSKEY_TOKEN) +MY_ID = msk.i()['id'] +WS_URL=f"wss://{MISSKEY_INSTANCE}/streaming" + +channels = ['localTimeline', 'globalTimeline' 'hybridTimeline', 'main'] + + +async def event_handler(event): + event = json.loads(event) + if event['body']['type'] == "note": + bridges.send_misskey_to_mattermost(event, "fkcqa3qj83gu3bfikcu55sfwww") + + +async def connect_and_listen(): + while True: + try: + print("Connecting to WebSocket...") + async with websockets.connect(WS_URL) as websocket: + print("Connected to WebSocket") + # Subscribe to the channels + for channel in channels: + subscription_request = { + "type": "connect", + "body": { + "channel": channel, + "id": MY_ID, + "access_token": MISSKEY_TOKEN + } + } + await websocket.send(json.dumps(subscription_request)) + print(f"Sent subscription request for {channel} channel with ID: {MY_ID}") + response = await websocket.recv() + print(f"Received response for {channel} channel: {response}") + await event_handler(response) + # Listen for messages + #while True: + # async for message in websocket: + # await handle_message(websocket, message) + + except websockets.exceptions.ConnectionClosedError as e: + print(f"Connection closed unexpectedly: {e}") + await asyncio.sleep(5) # Wait for 5 seconds before retrying + except Exception as e: + print(f"An error occurred: {e}") + await asyncio.sleep(5) # Wait for 5 seconds before retrying + +if __name__ == "__main__": + asyncio.run(connect_and_listen()) \ No newline at end of file diff --git a/test.json b/test.json new file mode 100644 index 0000000..fe93c47 --- /dev/null +++ b/test.json @@ -0,0 +1,117 @@ +{ + "type": "channel", + "body": { + "id": "a79jhleyz47f00j9", + "type": "note", + "body": { + "id": "a8qi6tndcsjw00uj", + "createdAt": "2025-06-08T00:42:51.673Z", + "userId": "a78vufh1z47f000t", + "user": { + "id": "a78vufh1z47f000t", + "name": "Gabriella Versi", + "username": "gabriella", + "host": null, + "avatarUrl": "https://misskey.treehousefullofstars.com/proxy/avatar.webp?url=https%3A%2F%2Fmisskey.treehousefullofstars.com%2Ffiles%2F64e5e5cf-5d64-40f1-91ab-f7858f4b0e18&avatar=1", + "avatarBlurhash": "eOPZ7PRjpd%Mx]_Nxt?bs:xZ%gWCROWCM|%gWBRjofWXSPf5xtt7V@", + "avatarDecorations": [], + "isBot": false, + "isCat": false, + "emojis": {}, + "onlineStatus": "online", + "badgeRoles": [ + { + "name": "Roots", + "iconUrl": null, + "displayOrder": 0 + } + ] + }, + "text": null, + "cw": null, + "visibility": "public", + "localOnly": false, + "reactionAcceptance": null, + "renoteCount": 0, + "repliesCount": 0, + "reactionCount": 0, + "reactions": {}, + "reactionEmojis": {}, + "reactionAndUserPairCache": [], + "fileIds": [], + "files": [], + "replyId": null, + "renoteId": "a8ohrbj431al069k", + "clippedCount": 0, + "renote": { + "id": "a8ohrbj431al069k", + "createdAt": "2025-06-06T14:55:16.000Z", + "userId": "a7xcts4vcsjw00at", + "user": { + "id": "a7xcts4vcsjw00at", + "name": "Information Is Beautiful", + "username": "infobeautiful", + "host": "vis.social", + "avatarUrl": "https://misskey.treehousefullofstars.com/proxy/avatar.webp?url=https%3A%2F%2Fcdn.masto.host%2Fvissocial%2Faccounts%2Favatars%2F111%2F030%2F299%2F829%2F248%2F466%2Foriginal%2F0d4bfae30dce0763.png&avatar=1", + "avatarBlurhash": "e2CY]zxI9xx@=y$%juXSa{aeD,ou~UV|bayCj@ena#t7yCRowIxo01", + "avatarDecorations": [], + "isBot": false, + "isCat": false, + "instance": { + "name": "vis.social", + "softwareName": "mastodon", + "softwareVersion": "4.3.8", + "iconUrl": "https://vis.social/packs/media/icons/android-chrome-36x36-4c61fdb42936428af85afdbf8c6a45a8.png", + "faviconUrl": "https://vis.social/packs/media/icons/favicon-48x48-c1197e9664ee6476d2715a1c4293bf61.png", + "themeColor": "#181820" + }, + "emojis": {}, + "onlineStatus": "unknown" + }, + "text": "Some interesting variations here...\n(by reddit user theworldmaps)", + "cw": null, + "visibility": "public", + "localOnly": false, + "reactionAcceptance": null, + "renoteCount": 1, + "repliesCount": 1, + "reactionCount": 0, + "reactions": {}, + "reactionEmojis": {}, + "reactionAndUserPairCache": [], + "emojis": {}, + "fileIds": [ + "a8ohrh7e31al069j" + ], + "files": [ + { + "id": "a8ohrh7e31al069j", + "createdAt": "2025-06-06T14:55:23.354Z", + "name": "b1743c8a716cf03a.png", + "type": "image/png", + "md5": "8fa3149c3db0e0d11e7b0b0007cabeeb", + "size": 0, + "isSensitive": false, + "blurhash": "eHQuZ@WdUE+^XoghOkXlw1oxLzNrmSr{t1vgQ;ogXOWZu2r;bwpaaM", + "properties": { + "width": 853, + "height": 1024 + }, + "url": "https://misskey.treehousefullofstars.com/files/webpublic-1225bfbb-9837-44b0-b0ac-1ed14fa1df92", + "thumbnailUrl": "https://misskey.treehousefullofstars.com/proxy/static.webp?url=https%3A%2F%2Fcdn.masto.host%2Fvissocial%2Fmedia_attachments%2Ffiles%2F114%2F636%2F994%2F245%2F080%2F080%2Foriginal%2Fb1743c8a716cf03a.png&static=1", + "comment": "A map of Europe showing the mean age of women at the birth of their first child, categorized by color from yellow (age 25) to purple (age 33). Examples include: Moldova with the youngest average age at 25.1, and Monaco with the highest at 32.5. Other notable countries: Spain at 31.6, Italy at 31.7, Germany at 29.9, and Finland at 29.9. The map includes small flags and labeled figures for precision. Data for the UK is from 2018, and other countries are from 2021 or 2022.", + "folderId": null, + "folder": null, + "userId": "a7xcts4vcsjw00at", + "user": null + } + ], + "replyId": null, + "renoteId": null, + "uri": "https://vis.social/users/infobeautiful/statuses/114636994393755424", + "url": "https://vis.social/@infobeautiful/114636994393755424", + "clippedCount": 0 + } + } + } +} \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..4377ed9 --- /dev/null +++ b/test.py @@ -0,0 +1,25 @@ +import re +import requests +from bs4 import BeautifulSoup + +# pattern = re.compile(r'!\[.*?\]\(.*?\)') +#pattern = re.compile(r'!\[.*?\]\(.*?\)') +linkmatches = re.compile(r'\b(?:https?://|www\.)\S+\b') + +test_string = "https://tenor.com/view/i-love-you-iloveyou-i-love-it-love-you-love-u-gif-1804813945664624577" + + +links = linkmatches.findall(test_string) + + +for match in links: + + response = requests.get(match) + soup = BeautifulSoup(response.text, 'html.parser') + gif_title = soup.find('meta', property='og:title')['content'] + gif_url = soup.find('meta', property='og:image')['content'] + + test_string = test_string.replace(match, "") + test_string += f"![{gif_title}]({gif_url})" + +print(test_string) \ No newline at end of file diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..a8a9406 --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +this is a test \ No newline at end of file