Skip to content

Commit

Permalink
Rewritten the bluesky and slack plugins and add some fixes.
Browse files Browse the repository at this point in the history
This commit updates the dependencies in the `requirements.txt` file. It also updates the GitHub Actions workflows (`preview.yml` and `publish_content.yml`) to use the latest versions of the `actions/checkout` and `actions/setup-python` actions. The Python version in the workflows is updated to `3.12` (this was necessary for  using `asyncio.Runner()`) . These changes aim to improve the overall functionality and compatibility of the project.
  • Loading branch information
arash77 committed Jun 4, 2024
1 parent 1b86cf2 commit 8cfb87e
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 76 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Get changed files in posts folder
id: get_changed_files
Expand All @@ -30,9 +30,9 @@ jobs:
- name: Set up Python
if: steps.get_changed_files.outputs.any_changed == 'true'
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: '3.12'

- name: Install dependencies
if: steps.get_changed_files.outputs.any_changed == 'true'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish_content.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Get changed files in posts folder
id: get_changed_files
Expand All @@ -31,9 +31,9 @@ jobs:
- name: Set up Python
if: steps.get_changed_files.outputs.any_changed == 'true'
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: '3.12'

- name: Install dependencies
if: steps.get_changed_files.outputs.any_changed == 'true'
Expand Down
16 changes: 8 additions & 8 deletions github_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ def comment(self, comment_text):
url = (
f"https://api.github.com/repos/{self.repo}/issues/{self.pr_number}/comments"
)
data = {"body": str(comment_text)}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 201:
return True
else:
raise Exception(
f"Failed to create github comment!, {response.json().get('message')}"
)
for comment_body in comment_text.split("\n\n---\n"):
data = {"body": str(comment_body)}
response = requests.post(url, headers=headers, json=data)
if response.status_code != 201:
raise Exception(
f"Failed to create github comment!, {response.json().get('message')}"
)
return True

def get_files(self):
url = f"https://api.github.com/repos/{self.repo}/pulls/{self.pr_number}/files"
Expand Down
16 changes: 10 additions & 6 deletions lib/galaxy_social.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ def process_markdown_file(self, file_path, processed_files):
except Exception as e:
raise Exception(f"Failed to format post for {file_path}.\n{e}")
if self.preview:
message = f"File: {file_path}"
message = f'Hi, I\'m your friendly social media assistant. In the following, you will see a preview of this post "{file_path}"'
for media in metadata["media"]:
formatted_content, preview, warning = formatting_results[media]
message += f"\n\nThis is a preview of what will be posted to {media}:\n\n"
message += f"\n\n## {media}\n\n"
message += preview
if warning:
message += f"\nWARNING: {warning}"
return processed_files, message
return processed_files, message.strip()

stats = {}
url = {}
Expand All @@ -143,7 +143,11 @@ def process_markdown_file(self, file_path, processed_files):
formatted_content, file_path=file_path
)
url_text = "\n".join(
[f"- [{media}]({link})" if link else f"- {media}" for media, link in url.items() if stats[media]]
[
f"- [{media}]({link})" if link else f"- {media}"
for media, link in url.items()
if stats[media]
]
)
message = f"Posted to:\n\n{url_text}" if url_text else "No posts created."

Expand All @@ -153,7 +157,7 @@ def process_markdown_file(self, file_path, processed_files):

def process_files(self, files_to_process):
processed_files = {}
messages = "---\n"
messages = ""
processed_files_path = self.json_out
if os.path.exists(processed_files_path):
with open(processed_files_path, "r") as file:
Expand All @@ -162,7 +166,7 @@ def process_files(self, files_to_process):
processed_files, message = self.process_markdown_file(
file_path, processed_files
)
messages += f"{message}\n---\n"
messages += f"{message}\n\n---\n"
if not self.preview:
with open(processed_files_path, "w") as file:
json.dump(processed_files, file)
Expand Down
66 changes: 51 additions & 15 deletions lib/plugins/bluesky.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,52 @@ def handle_url_card(
)
return embed_external

def create_post(
self, content, mentions, hashtags, images, **kwargs
) -> Tuple[bool, Optional[str]]:
def wrap_text_with_index(self, content):
if len(content) <= self.max_content_length:
return [content]
urls = re.findall(r"https?://\S+", content)
placeholder_content = re.sub(
r"https?://\S+", lambda m: "~" * len(m.group()), content
)
wrapped_lines = textwrap.wrap(
placeholder_content, self.max_content_length - 8, replace_whitespace=False
)
final_lines = []
url_index = 0
for i, line in enumerate(wrapped_lines, 1):
while "~~~~~~~~~~" in line and url_index < len(urls):
placeholder = "~" * len(urls[url_index])
line = line.replace(placeholder, urls[url_index], 1)
url_index += 1
final_lines.append(f"{line} ({i}/{len(wrapped_lines)})")
return final_lines

def format_content(self, content, mentions, hashtags, images, **kwargs):
mentions = " ".join([f"@{v}" for v in mentions])
hashtags = " ".join([f"#{v}" for v in hashtags])
if len(images) > 4:
warnings = f"A maximum of four images, not {len(images)}, can be included in a single bluesky post."
images = images[:4]
else:
warnings = ""

chunks = self.wrap_text_with_index(f"{content}\n\n{mentions}\n{hashtags}")

formatted_content = {
"body": "\n\n".join(chunks),
"images": images,
"chunks": chunks,
}
preview = formatted_content["body"]
images_preview = "\n".join(
[f'![{image.get("alt_text", "")}]({image["url"]})' for image in images]
)
preview += "\n\n" + images_preview
return formatted_content, preview, warnings

def create_post(self, content, **kwargs) -> Tuple[bool, Optional[str]]:
embed_images = []
for image in images[:4]:
for image in content["images"][:4]:
response = requests.get(image["url"])
if response.status_code == 200 and response.headers.get(
"Content-Type", ""
Expand All @@ -172,17 +213,11 @@ def create_post(
else None
)

status = []
reply_to = None
mentions = " ".join([f"@{v}" for v in mentions])
hashtags = " ".join([f"#{v}" for v in hashtags])
for text in textwrap.wrap(
content + "\n" + mentions + "\n" + hashtags,
self.max_content_length,
replace_whitespace=False,
):

for text in content["chunks"]:
facets, last_url = self.parse_facets(text)
if not images or reply_to:
if not content["images"] or reply_to:
embed = self.handle_url_card(cast(str, last_url))

post = self.blueskysocial.send_post(
Expand All @@ -192,13 +227,14 @@ def create_post(
for _ in range(5):
data = self.blueskysocial.get_posts([post.uri]).posts
if data:
status.append(data[0].record.text == text)
break
else:
return False, None

if reply_to is None:
link = f"https://bsky.app/profile/{self.blueskysocial.me.handle}/post/{post.uri.split('/')[-1]}"
root = atproto.models.create_strong_ref(post)
parent = atproto.models.create_strong_ref(post)
reply_to = atproto.models.AppBskyFeedPost.ReplyRef(parent=parent, root=root)

return all(status), link
return True, link
14 changes: 4 additions & 10 deletions lib/plugins/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ def __init__(self, **kwargs):

def format_content(self, content, mentions, hashtags, images, **kwargs):
_images = "\n".join(
[
f'![{image.get("alt_text", "")}]({image["url"]})'
for image in images
]
[f'![{image.get("alt_text", "")}]({image["url"]})' for image in images]
)
mentions = " ".join([f"@{v}" for v in mentions])
hashtags = " ".join([f"#{v}" for v in hashtags])
Expand All @@ -29,13 +26,10 @@ def create_post(self, formatted_content, **kwargs):
if self.save_path:
os.makedirs(self.save_path, exist_ok=True)
prefix = kwargs.get("file_path", "").replace(".md", "")
file_name = (
f"{self.save_path}/{prefix.replace('/', '-')}_{time.strftime('%Y%m%d-%H%M%S')}.md"
)
file_name = f"{self.save_path}/{prefix.replace('/', '-')}_{time.strftime('%Y%m%d-%H%M%S')}.md"
with open(file_name, "w") as f:
f.write(formatted_content)
return True, None
except Exception as e:
print(e)
return False, None

print(e)
return False, None
40 changes: 28 additions & 12 deletions lib/plugins/mastodon.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
import tempfile
import textwrap

import requests
from bs4 import BeautifulSoup
from mastodon import Mastodon


Expand All @@ -14,6 +14,26 @@ def __init__(self, **kwargs):
)
self.max_content_length = kwargs.get("max_content_length", 500)

def wrap_text_with_index(self, content):
if len(content) <= self.max_content_length:
return [content]
urls = re.findall(r"https?://\S+", content)
placeholder_content = re.sub(
r"https?://\S+", lambda m: "~" * len(m.group()), content
)
wrapped_lines = textwrap.wrap(
placeholder_content, self.max_content_length - 8, replace_whitespace=False
)
final_lines = []
url_index = 0
for i, line in enumerate(wrapped_lines, 1):
while "~~~~~~~~~~" in line and url_index < len(urls):
placeholder = "~" * len(urls[url_index])
line = line.replace(placeholder, urls[url_index], 1)
url_index += 1
final_lines.append(f"{line} ({i}/{len(wrapped_lines)})")
return final_lines

def format_content(self, content, mentions, hashtags, images, **kwargs):
mentions = " ".join([f"@{v}" for v in mentions])
hashtags = " ".join([f"#{v}" for v in hashtags])
Expand All @@ -22,16 +42,17 @@ def format_content(self, content, mentions, hashtags, images, **kwargs):
images = images[:4]
else:
warnings = ""

chunks = self.wrap_text_with_index(f"{content}\n\n{mentions}\n{hashtags}")

formatted_content = {
"body": f"{content}\n\n{mentions}\n{hashtags}",
"body": "\n\n".join(chunks),
"images": images,
"chunks": chunks,
}
preview = formatted_content["body"]
images_preview = "\n".join(
[
f'![{image.get("alt_text", "")}]({image["url"]})'
for image in images
]
[f'![{image.get("alt_text", "")}]({image["url"]})' for image in images]
)
preview += "\n\n" + images_preview
return formatted_content, preview, warnings
Expand All @@ -53,12 +74,7 @@ def create_post(self, content, **kwargs):
media_ids.append(media_uploaded["id"])

toot_id = link = None
status = []
for text in textwrap.wrap(
content["body"],
self.max_content_length,
replace_whitespace=False,
):
for text in content["chunks"]:
toot = self.mastodon_handle.status_post(
status=text,
in_reply_to_id=toot_id,
Expand Down
22 changes: 16 additions & 6 deletions lib/plugins/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,28 @@ async def async_format_content(self, content, mentions, hashtags, images, **kwar
# try to get the display name of the mentioned matrix user
response = await self.client.get_displayname(f"@{mention}")
mention_name = getattr(response, "displayname", mention)
mention_links.append(f"[{mention_name}](https://matrix.to/#/@{mention})")
mention_links.append(
f"[{mention_name}](https://matrix.to/#/@{mention})"
)
message_content["m.mentions"]["user_ids"].append(f"@{mention}")
mentions_string = " ".join(mention_links)
content = f"{mentions_string}: {content}"
if hashtags:
content += "\n\n" + " ".join([f"\\#{h}" for h in hashtags])
formatted_body = markdown(content)
body = BeautifulSoup(formatted_body, features="html.parser").get_text("\n", strip=True)
body = BeautifulSoup(formatted_body, features="html.parser").get_text(
"\n", strip=True
)
message_content["body"] = body
message_content["formatted_body"] = formatted_body
formatted_content.append(message_content)
warnings = ""
return formatted_content, preview + "\n" + message_content["formatted_body"], warnings
await self.client.close()
return (
formatted_content,
preview + "\n" + message_content["formatted_body"],
warnings,
)

async def async_create_post(self, content):
for msg in content:
Expand Down Expand Up @@ -113,9 +122,10 @@ async def async_create_post(self, content):
return True, event_link

def format_content(self, *args, **kwargs):
return self.runner.run(self.async_format_content(*args, **kwargs))
result = self.runner.run(self.async_format_content(*args, **kwargs))
return result

def create_post(self, content, **kwargs):
# hashtags and alt_texts are not used in this function
return self.runner.run(self.async_create_post(content))

result = self.runner.run(self.async_create_post(content))
return result
Loading

0 comments on commit 8cfb87e

Please sign in to comment.