Last active
December 6, 2024 06:11
-
-
Save zzstoatzz/7a145b728455f8d8a3fecb9bad55a71b to your computer and use it in GitHub Desktop.
its like quite bespoke spelling, but ive been digging in this SDK for a while :)
This file contains hidden or 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
import httpx | |
from atproto import Client, models | |
from pydantic_settings import BaseSettings, SettingsConfigDict | |
class Settings(BaseSettings): | |
"""set the following in your .env file | |
BSKY_USERNAME=your_username | |
BSKY_PASSWORD=your_password | |
""" | |
model_config = SettingsConfigDict(env_file='.env') | |
bsky_username: str | |
bsky_password: str | |
settings = Settings() # type: ignore[call-arg] | |
DEFAULT_IMAGE_URL = 'https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:xbtmt2zjwlrfegqvch7fboei/bafkreiae4rcokecag5qlpvg6l3otzulqn3hllnazmz2ezyqfl6xzpy5noe@jpeg' | |
def main( | |
user_to_quote: str, | |
post_to_quote: str, | |
message: str = 'Check this out!', | |
image_url: str = DEFAULT_IMAGE_URL, | |
image_path: str | None = None, | |
image_alt: str = '', | |
image_aspect_ratio: tuple[int, int] = (1, 1), # width, height | |
) -> None: | |
"""Post an image while quoting another post.""" | |
if bool(image_url) == bool(image_path): | |
raise ValueError('Exactly one of image_url or image_path must be provided') | |
client = Client() | |
client.login(settings.bsky_username, settings.bsky_password) | |
if image_path: | |
with open(image_path, 'rb') as f: | |
img_data = f.read() | |
else: | |
assert image_url is not None, 'image_url must be provided' # noqa: S101 | |
img_data = httpx.get(image_url).content | |
if len(img_data) > 1_000_000: | |
raise ValueError(f'Image must be under 1MB. Got {len(img_data) / 1_000_000:.1f}MB') | |
uploaded_blob = client.upload_blob(img_data).blob | |
handle_response = client.resolve_handle(user_to_quote) | |
quote_post_uri = f'at://{handle_response.did}/app.bsky.feed.post/{post_to_quote}' | |
quoted_post = client.get_post(post_rkey=post_to_quote, profile_identify=handle_response.did) | |
assert quoted_post.cid is not None, 'Quoted post CID is required' # noqa: S101 | |
client.send_post( | |
text=message, | |
embed=models.AppBskyEmbedRecordWithMedia.Main( | |
record=models.AppBskyEmbedRecord.Main( | |
record=models.ComAtprotoRepoStrongRef.Main( | |
uri=quote_post_uri, | |
cid=quoted_post.cid, | |
) | |
), | |
media=models.AppBskyEmbedImages.Main( | |
images=[ | |
models.AppBskyEmbedImages.Image( | |
image=uploaded_blob, | |
alt=image_alt, | |
aspect_ratio=models.AppBskyEmbedDefs.AspectRatio( | |
width=image_aspect_ratio[0], height=image_aspect_ratio[1] | |
), | |
) | |
] | |
), | |
), | |
) | |
if __name__ == '__main__': | |
# Example usage | |
main( | |
user_to_quote='alternatebuild.dev', | |
post_to_quote='3lbydu5wsdk2h', | |
message='I scorn you! (from the atproto python client)', | |
image_alt='cat with a condescending glare', | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment