generated from freelawproject/new-project-template
-
-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(channels): Add support for Threads #618
Merged
Merged
Changes from 8 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
03e2db8
feat(channels): Add script to retrieve credentials for new Threads ch…
elisa-a-v 6c38736
feat(channels): Add new service option in Channel model to support Th…
elisa-a-v 2506d91
feat(channels): Add Threads connector with custom API
elisa-a-v 8d7b5e0
fix(settings): Fix default value for DOCTOR_HOST env variable
elisa-a-v 9fe1b73
feat(channels): Integrate ThreadsConnector with channels module
elisa-a-v 54c65c6
fix(threads_api): Fix rounding issue when cropping image to meet Thre…
elisa-a-v 503474a
docs(threads_api): Add docstrings to ThreadsAPI and ThreadsConnector
elisa-a-v 4b9e577
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] c5089f4
fix(channels): Use account instead of account_id for Threads self_url
elisa-a-v 535cc70
feat(ThreadsAPI): add attempt_post method with timeout and error hand…
elisa-a-v f171af4
refactor(threads): Rename variables from 'zone' to 'region' for AWS r…
elisa-a-v d7af8b8
fix(threads): fix return types
elisa-a-v b4d2bf1
feat(threads): Add Threads logo to little bots follow button
elisa-a-v 74f9933
fix(aws_credentials): Add session token env variable to support tempo…
elisa-a-v File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Generated by Django 5.1.1 on 2024-10-28 17:23 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
dependencies = [ | ||
("channel", "0008_alter_channel_service_alter_post_object_id"), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name="channel", | ||
name="service", | ||
field=models.PositiveSmallIntegerField( | ||
choices=[ | ||
(1, "Twitter"), | ||
(2, "Mastodon"), | ||
(3, "Bluesky"), | ||
(4, "Threads"), | ||
], | ||
help_text="Type of the service", | ||
), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{% extends "post.html" %} | ||
{% block title %}Threads Authorization Code{% endblock %} | ||
|
||
{% block post_title %}Threads Onboarding{% endblock %} | ||
|
||
{% block post_content %} | ||
<p class="lead">You're almost done! Use the code below in your CLI to complete the setup for this Threads account.</p> | ||
|
||
<h3>Authorization Code:</h3> | ||
<div class="flex bg-gray-200 rounded-lg p-5"> | ||
<p class="w-full break-all">{{code}}</p> | ||
</div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,17 @@ | ||
from django.urls import path | ||
|
||
from .api_views import receive_mastodon_push | ||
from .views import threads_callback | ||
|
||
urlpatterns = [ | ||
path( | ||
"webhooks/mastodon/", | ||
receive_mastodon_push, | ||
name="mastodon_push_handler", | ||
), | ||
path( | ||
"threads_callback/", | ||
threads_callback, | ||
name="threads_code_display", | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import logging | ||
|
||
from bc.core.utils.images import TextImage | ||
|
||
from .alt_text_utils import text_image_alt_text, thumb_num_alt_text | ||
from .threads_api.client import ThreadsAPI | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ThreadsConnector: | ||
""" | ||
A connector for interfacing with the Threads API, which complies with | ||
the BaseAPIConnector protocol. | ||
""" | ||
|
||
def __init__( | ||
self, account: str, account_id: str, access_token: str | ||
) -> None: | ||
self.account = account | ||
self.account_id = account_id | ||
self.access_token = access_token | ||
self.api = self.get_api_object() | ||
|
||
def get_api_object(self, _version=None) -> ThreadsAPI: | ||
""" | ||
Returns an instance of the ThreadsAPI class. | ||
""" | ||
api = ThreadsAPI( | ||
self.account_id, | ||
self.access_token, | ||
) | ||
return api | ||
|
||
def upload_media(self, media: bytes, _alt_text=None) -> str: | ||
""" | ||
Uploads media to public storage for Threads API compatibility. | ||
|
||
Since Threads API requires media to be accessible via public URL, | ||
this method resizes the image as needed, uploads it to S3, and | ||
returns the public URL. | ||
|
||
Args: | ||
media (bytes): The image bytes to be uploaded. | ||
_alt_text (str, optional): Alternative text for accessibility | ||
(not currently used, required by protocol). | ||
|
||
Returns: | ||
str: Public URL of the uploaded image. | ||
""" | ||
return self.api.resize_and_upload_to_public_storage(media) | ||
|
||
def add_status( | ||
self, | ||
message: str, | ||
text_image: TextImage | None = None, | ||
thumbnails: list[bytes] | None = None, | ||
) -> str: | ||
""" | ||
Creates and publishes a new status update on Threads. | ||
|
||
This method determines the type of post (text-only, single image, | ||
or carousel) based on the provided media. If multiple images are | ||
provided, a carousel post is created. Otherwise, it creates a | ||
single image or text-only post. | ||
|
||
Args: | ||
message (str): The text content of the status. | ||
text_image (TextImage | None): An optional main image with text. | ||
thumbnails (list[bytes] | None): Optional list of thumbnails for | ||
a carousel post. | ||
|
||
Returns: | ||
str: The ID of the published status. | ||
""" | ||
media: list[str] = [] | ||
|
||
# Count media elements to determine type of post: | ||
multiple_thumbnails = thumbnails is not None and len(thumbnails) > 1 | ||
text_image_and_thumbnail = ( | ||
thumbnails is not None | ||
and len(thumbnails) > 0 | ||
and text_image is not None | ||
) | ||
is_carousel_item = multiple_thumbnails or text_image_and_thumbnail | ||
|
||
if text_image: | ||
image_url = self.upload_media(text_image.to_bytes()) | ||
item_container_id = self.api.create_image_container( | ||
image_url, | ||
message, | ||
text_image_alt_text(text_image.description), | ||
is_carousel_item, | ||
) | ||
if item_container_id: | ||
media.append(item_container_id) | ||
|
||
if thumbnails: | ||
for idx, thumbnail in enumerate(thumbnails): | ||
thumbnail_url = self.upload_media(thumbnail) | ||
item_container_id = self.api.create_image_container( | ||
thumbnail_url, | ||
message, | ||
thumb_num_alt_text(idx), | ||
is_carousel_item, | ||
) | ||
if not item_container_id: | ||
continue | ||
media.append(item_container_id) | ||
|
||
# Determine container id to be published based on media count: | ||
if len(media) > 1: | ||
# Carousel post (multiple images) | ||
container_id = self.api.create_carousel_container(media, message) | ||
elif len(media) == 1: | ||
# Single image post | ||
container_id = media[0] | ||
else: | ||
# Text-only post | ||
container_id = self.api.create_text_only_container(message) | ||
|
||
return self.api.publish_container(container_id) | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"<{self.__class__.__module__}.{self.__class__.__name__}: " | ||
f"account:'{self.account}'>" | ||
) |
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were removed because they weren't used anymore, as discussed with @ERosendo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. We should definitely clean up the settings module as well.