Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Smerity/f896e0a9d27c725b2bc03cd85e105b31 to your computer and use it in GitHub Desktop.
Save Smerity/f896e0a9d27c725b2bc03cd85e105b31 to your computer and use it in GitHub Desktop.
All the examples from the Bluesky `atproto` Python API as a single text file with delineation
=== Start of delete_post.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
# same with the like_post.py example we need to keep a reference to the post
post_ref = client.send_post('Test send-delete from Python SDK')
print('Post reference:', post_ref)
# this method returns True/False depends on the response
print('Deleted successfully:', client.delete_post(post_ref.uri))
if __name__ == '__main__':
main()
=== End of delete_post.py ===
=== Start of home_timeline.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
print('Home (Following):\n')
# Get "Home" page. Use pagination (cursor + limit) to fetch all posts
timeline = client.get_timeline(algorithm='reverse-chronological')
for feed_view in timeline.feed:
action = 'New Post'
if feed_view.reason:
action_by = feed_view.reason.by.handle
action = f'Reposted by @{action_by}'
post = feed_view.post.record
author = feed_view.post.author
print(f'[{action}] {author.display_name}: {post.text}')
if __name__ == '__main__':
main()
=== End of home_timeline.py ===
=== Start of like_post.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
post = client.send_post(text='Hello World from Python!')
print('Post reference:', post)
print('Like reference:', client.like(uri=post.uri, cid=post.cid))
if __name__ == '__main__':
main()
=== End of like_post.py ===
=== Start of process_notifications.py ===
from time import sleep
from atproto import Client
# how often we should check for new notifications
FETCH_NOTIFICATIONS_DELAY_SEC = 3
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
# fetch new notifications
while True:
# save the time in UTC when we fetch notifications
last_seen_at = client.get_current_time_iso()
response = client.app.bsky.notification.list_notifications()
for notification in response.notifications:
if not notification.is_read:
print(f'Got new notification! Type: {notification.reason}; from: {notification.author.did}')
# example: "Got new notification! Type: like; from: did:plc:hlorqa2iqfooopmyzvb4byaz"
# mark notifications as processed (isRead=True)
client.app.bsky.notification.update_seen({'seen_at': last_seen_at})
print('Successfully process notification. Last seen at:', last_seen_at)
sleep(FETCH_NOTIFICATIONS_DELAY_SEC)
if __name__ == '__main__':
main()
=== End of process_notifications.py ===
=== Start of profile_posts.py ===
from atproto import Client
def main(client: Client, handle: str) -> None:
print(f'\nProfile Posts of {handle}:\n\n')
# Get profile's posts. Use pagination (cursor + limit) to fetch all
profile_feed = client.get_author_feed(actor=handle)
for feed_view in profile_feed.feed:
print('-', feed_view.post.record.text)
if __name__ == '__main__':
at_client = Client()
at_client.login('my-handle', 'my-password')
while True:
input_handle = input('\nPlease, enter the handle of the user: ')
main(at_client, input_handle)
=== End of profile_posts.py ===
=== Start of repost_post.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
post_ref = client.send_post(text='Hello World from Python!')
print('Post reference:', post_ref)
print('Reposted post reference:', client.repost(uri=post_ref.uri, cid=post_ref.cid))
if __name__ == '__main__':
main()
=== End of repost_post.py ===
=== Start of send_image.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
# replace the path to your image file
with open('cat.jpg', 'rb') as f:
img_data = f.read()
client.send_image(text='Post with image from Python', image=img_data, image_alt='Text version of the image (ALT)')
if __name__ == '__main__':
main()
=== End of send_image.py ===
=== Start of send_images.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
# replace the path to your image file
paths = ['cat.jpg', 'dog.jpg', 'bird.jpg']
image_alts = ['Text version', 'of the image (ALT)', 'This parameter is optional']
images = []
for path in paths:
with open(path, 'rb') as f:
images.append(f.read())
client.send_images(text='Post with image from Python', images=images, image_alts=image_alts)
if __name__ == '__main__':
main()
=== End of send_images.py ===
=== Start of send_post.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
client.send_post(text='Hello World from Python!')
if __name__ == '__main__':
main()
=== End of send_post.py ===
=== Start of send_reply.py ===
from atproto import Client, models
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
root_post_ref = models.create_strong_ref(client.send_post('Post from Python SDK'))
# Reply to the root post. We need to pass ReplyRef with root and parent
reply_to_root = models.create_strong_ref(
client.send_post(
text='Reply to the root post',
reply_to=models.AppBskyFeedPost.ReplyRef(parent=root_post_ref, root=root_post_ref),
)
)
# To reply on reply, we need to change the "parent" field. Let's reply to our previous reply
client.send_post(
text='Reply to the parent reply',
reply_to=models.AppBskyFeedPost.ReplyRef(parent=reply_to_root, root=root_post_ref),
)
if __name__ == '__main__':
main()
=== End of send_reply.py ===
=== Start of send_rich_text.py ===
from atproto import Client, client_utils
# To send links as "link card" or "quote post" look at the advanced_usage/send_embed.py example.
# There is a more advanced way to send rich text without helper class in the advanced_usage/send_rich_text.py example.
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
text_builder = client_utils.TextBuilder()
text_builder.tag('This is a rich message. ', 'atproto')
text_builder.text('I can mention ')
text_builder.mention('account', 'did:plc:kvwvcn5iqfooopmyzvb4qzba')
text_builder.text(' and add clickable ')
text_builder.link('link', 'https://atproto.blue/')
# You can pass instance of TextBuilder instead of str to the "text" argument.
client.send_post(text_builder) # same with send_image method
# Same with chaining:
client.send_post(client_utils.TextBuilder().text('Test msg using ').link('Python SDK', 'https://atproto.blue/'))
if __name__ == '__main__':
main()
=== End of send_rich_text.py ===
=== Start of send_video.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
# replace the path to your video file
with open('video.mp4', 'rb') as f:
vid_data = f.read()
client.send_video(text='Post with video from Python', video=vid_data, video_alt='Text version of the video (ALT)')
if __name__ == '__main__':
main()
=== End of send_video.py ===
=== Start of unlike_post.py ===
from atproto import Client
def main() -> None:
client = Client()
client.login('my-handle', 'my-password')
post = client.send_post('Test like-unlike from Python SDK')
print('Post reference:', post)
like = client.like(uri=post.uri, cid=post.cid)
print('Like reference:', like)
# this method return True/False depends on the response. could throw exceptions too
print(client.unlike(like.uri))
if __name__ == '__main__':
main()
=== End of unlike_post.py ===
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment