Logo

dev-resources.site

for different kinds of informations.

Calculating your potential reach on Mastodon with Google Cloud Workflows orchestrating the Mastodon APIs

Published at
1/11/2023
Categories
webapis
googlecloud
workflows
mastodon
Author
glaforge
Author
8 person written this
glaforge
open
Calculating your potential reach on Mastodon with Google Cloud Workflows orchestrating the Mastodon APIs

With the turmoil around Twitter, like many, Iā€™ve decided to look into Mastodon. My friend Geert is running his own Mastodon server, and welcomed me on his instance at: uwyn.net/@glaforge.

Image description

With Twitter, you can access your analytics to know how your tweets are doing, how many views youā€™re getting. Working in developer relations, itā€™s always interesting to get some insights into those numbers to figure out if what youā€™re sharing is interesting for your community. But for various (actually good) reasons, Mastodon doesnā€™t offer such detailed analytics. However, I wanted to see what the Mastodon APIs offered.

How to calculate your potential reach

Your ā€œtootsā€ (ie. your posts on Mastodon) can be ā€œboostedā€ (equivalent of a retweet on Twitter). Also, each actor on Mastodon has a certain number of followers. So potentially, one of your toots can reach all your followers, as well as all the followers of the actors who reshare your toot.

So the maximum potential reach of one of your posts would correspond to the following equation:

potential_reach = me.followers_count + āˆ‘ ( boosters[i].followers_count )

Letā€™s play with the Mastodon APIs to compute your reach

Fortunately, the Mastodon APIs allow you to get those numbers, albeit not with a single API call. Letā€™s have a look at the interesting endpoints to get the potential reach of my most recent posts.

First of all, Iā€™ll look up my account on the Mastodon instance that hosts me:

GET https://uwyn.net/api/v1/accounts/lookup?acct=glaforge

I pass my account name as a query parameter to the /accounts/lookup endpoint.

In return, I get a JSON document that contains various details about my account and me (Iā€™ll just show some of the interesting fields, not the whole payload):

{
    id: "109314675907601286",
    username: "glaforge",
    acct: "glaforge",
    display_name: "Guillaume Laforge",
    ...
    note: "...",
    url: "https://uwyn.net/@glaforge",
    ...
    followers_count: 878,
    fields: [...]
}
Enter fullscreen mode Exit fullscreen mode

I get two important pieces of information here: the followers_count gives me, you guessed it, the number of followers my account has, thus the potential number of persons that can see my toots. Also the id of my account, which Iā€™ll need for some further API calls further down.

To get the most recent statuses Iā€™ve posted, Iā€™ll indeed need that account id for crafting the new URL Iā€™ll call:

GET https://uwyn.net/api/v1/accounts/109314675907601286/statuses

This call will return a list of statuses (again, snipped less interesting part of the payload):

[
    ...
    {
        id: "109620174916140649",
        created_at: "2023-01-02T14:52:06.044Z",
        ...
        replies_count: 2,
        reblogs_count: 6,
        favourites_count: 6,
        ...
        edited_at: null,
        content: "...",
        reblog: null,
        ...
    },
    ...
]
Enter fullscreen mode Exit fullscreen mode

In each status object, you can see the number of replies, the number of times the post was reshared or favorited, or whether itā€™s a reshared toot itself. So whatā€™s interesting here is the reblogs_count number.

However, you donā€™t get more details about who reshared your toot. So weā€™ll need some extra calls to figure that out!

So for each of your posts, youā€™ll have to call the following endpoint to know more about those ā€œreblogsā€:

GET https://uwyn.net/api/v1/statuses/109620174916140649/reblogged_by

This time, youā€™ll get a list of all the persons who reshared your post:

[
    {
        id: "123456789",
        username: "...",
        acct: "...",
        display_name: "...",
        ...
        followers_count: 7,
        ...
    },
    ...
]
Enter fullscreen mode Exit fullscreen mode

And as you can see the details of those persons also have the followers_count field, that tells the number of people that follow them.

So now, we have all the numbers we need to calculate the potential reach of our toots: your own number of followers, and the number of followers of all those who reshared! It doesnā€™t mean that your toots will actually be viewed that many times, as one doesnā€™t necessarily read each and every toots on their timelines, but at least, thatā€™s an approximation of the maximum reach you can get.

Automating the potential reach calculation with Web API orchestration

Initially I played with both cURL and a little Apache Groovy script to better understand the Mastodon APIs to figure out how to chain them to get to the expected result. Then I decided to automate that series of Web API calls using an API orchestrator: Google Cloud Workflows.

To recap, we need to:

  • Get the details of your account
  • Get the recent posts for that account
  • Get all the followers count for each person who reshared each post

Letā€™s have a look at this piece by piece:

main:
    params: [input]
    steps:
    - account_server_vars:
        assign:
        - account: ${input.account}
        - server: ${input.server}
        - prefix: ${"https://" + server + "/api/v1"}
        - impact_map: {}
Enter fullscreen mode Exit fullscreen mode

First, the workflow takes an account and server arguments, in my case that is glaforge and uwyn.net. And Iā€™m defining a variable with the base path of the Mastodon API, and a dictionary to hold the data for each toot.

- find_account_id:
    call: http.get
    args:
        url: ${prefix + "/accounts/lookup"}
        query:
            acct: ${account}
    result: account_id_lookup
- account_id_var:
    assign:
    - account_id: ${account_id_lookup.body.id}
    - followers_count: ${account_id_lookup.body.followers_count}
Enter fullscreen mode Exit fullscreen mode

Above, Iā€™m doing an account lookup, to get the id of the account, but also the followers count.

- get_statuses:
    call: http.get
    args:
        url: ${prefix + "/accounts/" + account_id + "/statuses"}
        query:
            limit: 100
            exclude_reblogs: true
    result: statuses
Enter fullscreen mode Exit fullscreen mode

We get the list of most recent toots.

Now things get more interesting, as we need to iterate over all the statuses. Weā€™ll do so in parallel, to save some time:

- iterate_statuses:
    parallel:
        shared: [impact_map]
        for:
            value: status
            in: ${statuses.body}
Enter fullscreen mode Exit fullscreen mode

To parallelize the per-status calls, we just need to state itā€™s parallel, and that the variable weā€™ll keep our data in is a shared variable that needs to be accessed in parallel. Next, we define the steps for each parallel iteration:

steps:
- counter_var:
    assign:
    - impact: ${followers_count}
- fetch_reblogs:
    call: http.get
    args:
        url: ${prefix + "/statuses/" + status.id + "/reblogged_by"}
    result: reblogs
Enter fullscreen mode Exit fullscreen mode

Above, we get the list of people who reshared our post. And for each of these accounts, weā€™re incrementing our impact counter with the number of their followers. Itā€™s another loop, but that doesnā€™t need to be done in parallel, as weā€™re not calling any API:

- iterate_reblogs:
    for:
        value: reblog
        in: ${reblogs.body}
        steps:
        - increment_reblog:
            assign: 
            - impact: ${impact + reblog.followers_count}
- update_impact_map:
    assign:
    - impact_map[status.url]: ${impact}
Enter fullscreen mode Exit fullscreen mode

And we finish the workflow by returning the data:

- returnOutput:
        return:
            id: ${account_id}
            account: ${account}
            server: ${server}
            followers: ${followers_count}
            impact: ${impact_map}
Enter fullscreen mode Exit fullscreen mode

This will return an output similar to this:

{
  "account": "glaforge",
  "followers": 878,
  "id": "109314675907601286",
  "impact": {
    "https://uwyn.net/@glaforge/109422399389341013": 945,
    "https://uwyn.net/@glaforge/109462120695384207": 1523,
    "https://uwyn.net/@glaforge/109494881278500194": 121385,
    "https://uwyn.net/@glaforge/109495686235916646": 878,
    "https://uwyn.net/@glaforge/109516968335141401": 1002,
    "https://uwyn.net/@glaforge/109523829424569844": 878,
    "https://uwyn.net/@glaforge/109528949144442301": 896,
    "https://uwyn.net/@glaforge/109620174916140649": 1662,
    "https://uwyn.net/@glaforge/109621803885287542": 1523,
    ...
  },
  "server": "uwyn.net"
}
Enter fullscreen mode Exit fullscreen mode

With this little workflow, I can check how my toots are doing on this new social media! As next steps, you might want to check out how to get started with API orchestration with Google Cloud Workflows, in the cloud console, or from the command-line. And to go further, potentially, it might be interesting to schedule a workflow execution with Cloud Scheduler. We could also imagine storing those stats in a database (perhaps BigQuery for some analytics, or simply Firestore or CloudSQL), to see how your impact evolves over time.

workflows Article's
30 articles in total
Favicon
Security Teams : Automate Cybersecurity Workflows
Favicon
GitHub Action security hardening with OpenID (OIDC) Connect - "Password-Less"
Favicon
Optimizing Test Coverage for Oracle OTM Workflows
Favicon
Continuous Integration
Favicon
DBOS-Cloud Simple and Robust Workflow Orchestration
Favicon
DBOS-Cloud: Minimal Effort Change Data Capture (CDC) Tool
Favicon
DBOS-Cloud: Fast and Free Automatic Data Aggregator
Favicon
DBOS-Cloud: Fast and Free Automatic Supabase Table Copier
Favicon
Part 1 - LittleHorse Advanced Concept Series: Conditionals
Favicon
Free & Paid Notion templates, covers, tools and more!
Favicon
Announcing WDL 1.1.1
Favicon
Visualize and Inspect Workflows Executions
Favicon
Simplifying Workflow Management with the XWorkflows Library
Favicon
How to use GitHub Workflows to Streamline Your Software Development Process
Favicon
Building Autonomous Business Processes using AI Agent Workflows
Favicon
šŸ“¦ Stay Organized and Efficient with Auto-Label-Pulls Github Action
Favicon
Temporal for VS Code
Favicon
Using the Temporal CLI
Favicon
Getting Started With Apache Airflow
Favicon
Getting Started with n8n: Integrating Typeform and Slack for Dynamic Messaging
Favicon
Calculating your potential reach on Mastodon with Google Cloud Workflows orchestrating the Mastodon APIs
Favicon
Simple Github Workflow for Lint - Prettier & Jest (yarn)
Favicon
How to view fields in an unauthorized connector's action cards
Favicon
All Okta Workflows Community-Created Flows
Favicon
Okta Workflows Connector Builder
Favicon
Manage Short Term Users with Okta Workflows
Favicon
GraphQL queries with Okta Workflows
Favicon
Event Hook Filtering and Okta Workflows
Favicon
Pagination with Okta Workflows
Favicon
A Flow to Audit Inactive Google Workspace Users in Okta

Featured ones: