6.2.2. Demo & Practice: Author Info#
Choose Social Media Platform: Reddit | Discord | Bluesky | No Coding
Though Bluesky might collect the device/program sources of submissions (like we saw from former President Trump), it unfortunately doesn’t let us see them.
Instead we will look at other information about the author of posts on Bluesky that can perhaps tell us something about their authenticity.
Log into Bluesky (atproto)#
These are our normal steps get atproto loaded and logged into Bluesky
helper function for atproto links
NOTE: You don’t need to worry about the details of how this works, it just is here to make the code later easier to use.
import re #load a "regular expression" library for helping to parse text
from atproto import IdResolver # Load the atproto IdResolver library to get offical ATProto user IDs
# function to convert a feed from a weblink url to the special atproto "at" URI
def getATFeedLinkFromURL(url):
# Get the user did and feed id from the weblink url
match = re.search(r'https://bsky.app/profile/([^/]+)/feed/([^/]+)', url)
if not match:
raise ValueError("Invalid Bluesky feed URL format.")
user_handle, feed_id = match.groups()
# Get the official atproto user ID (did) from the handle
resolver = IdResolver()
did = resolver.handle.resolve(user_handle)
if not did:
raise ValueError(f'Could not resolve DID for handle "{user_handle}".')
# Construct the at:// URI
post_uri = f"at://{did}/app.bsky.feed.generator/{feed_id}"
return post_uri
# function to convert a post's special atproto "at" URI to a weblink url
def getWebLinkFromPost(post):
# Get the user id and post id from the weblink url
match = re.search(r'at://([^/]+)/app.bsky.feed.post/([^/]+)', post.uri)
if not match:
raise ValueError("Invalid Bluesky atproto post URL format.")
user_id, post_id = match.groups()
post_uri = f"https://bsky.app/profile/{user_id}/post/{post_id}"
return post_uri
# function to take an author profile and generate a weblink url
def getWebLinkFromProfile(authorInfo):
author_uri = f"https://bsky.app/profile/{authorInfo.did}"
return author_uri
from atproto import Client
(optional) make a fake Bluesky connection with the fake_atproto library For testing purposes, we”ve added this line of code, which loads a fake version of atproto, so it wont actually connect to Bluesky. If you want to try to actually connect to Bluesky, don’t run this line of code.
%run ../../fake_apis/fake_atproto.ipynb
# Login to Bluesky
# TODO: put your account name and password below
client = Client(base_url="https://bsky.social")
client.login("your_account_name.bsky.social", "m#5@_fake_bsky_password_$%Ds")
Load a set of Bluesky posts and look up author information#
The code below searches for recent posts from a Bluesky feed, and then does a loop though all the posts, for each one making another request to Bluesky for the author info, then printing out some of that information, such as:
followers_count (how many accounts this author follows)
follows_count (how many accounts follow this author)
posts_count (how many posts this account has made)
Try searching through other feeds and see what you notice about the authors of posts in different subreddits.
To do this:
put in your Bluesky bot username and passwords
skip the fake_atproto step above
take the first line of the code below and replace the url for the animals feed with a different Bluesky feed
feedUrl = "https://bsky.app/profile/shouldhaveanimal.bsky.social/feed/aaab56iiatpdo"
atFeedLink = getATFeedLinkFromURL(feedUrl)
post_info_list = client.app.bsky.feed.get_feed({'feed': atFeedLink}).feed
# go through each post and look up author information for that post
for post_info in post_info_list:
print("Info for post with url: " + str(getWebLinkFromPost(post_info.post)))
# look up additional information about that author
author_did = post_info.post.author.did
author_info = client.app.bsky.actor.get_profile({'actor': author_did})
# print out various pieces of author info
print(" author handle: " + str(author_info.handle))
print(" author display name: " + str(author_info.display_name))
print(" author creation date: " + str(author_info.created_at))
print(" author did: " + str(author_info.did))
print(" author followers_count: " + str(author_info.followers_count))
print(" author follows_count: " + str(author_info.follows_count))
print(" author posts_count: " + str(author_info.posts_count))
print(" author avatar: " + str(author_info.avatar))
print(" author banner: " + str(author_info.banner))
print(" author description: " + str(author_info.description))
print(" author profile url: " + getWebLinkFromProfile(author_info))
print()
print()
Info for post with url: https://bsky.app/profile/did:plc:fake_user/post/fake_post_id
author handle: fake_user.bsky.social
author display name: Fake User
author creation date: 2024-1-01
author did: 93j45jg9ej5gjt
author followers_count: 75
author follows_count: 345
author posts_count: 13
author avatar: fake_user_profile.jpg
author banner: fake_user_banner.jpg
author description: I am a fake user!
author profile url: https://bsky.app/profile/93j45jg9ej5gjt
Info for post with url: https://bsky.app/profile/did:plc:pretend_user/post/fake_post_id
author handle: pretend_user.bsky.social
author display name: Pretend User
author creation date: 2024-3-02
author did: 75n4tk5gn4oi
author followers_count: 2
author follows_count: 1323
author posts_count: 1
author avatar: pretend_user_profile.jpg
author banner: pretend_user_banner.jpg
author description: I am a pretend user!
author profile url: https://bsky.app/profile/75n4tk5gn4oi
Info for post with url: https://bsky.app/profile/did:plc:imaginary_user/post/fake_post_id
author handle: imaginary_user.bsky.social
author display name: Imaginary User
author creation date: 2022-1-01
author did: 5kj45nkj4n6kj45n
author followers_count: 50
author follows_count: 60
author posts_count: 355
author avatar: imaginary_user_profile.jpg
author banner: imaginary_user_banner.jpg
author description: I am an imaginary user!
author profile url: https://bsky.app/profile/5kj45nkj4n6kj45n