=== 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 ===

