SDK BlueSky : Utiliser C# pour comprendre les blocages entre utilisateurs

La plus part des services, réseaux sociaux compris, on des API disponibles pour permettre à des programmes tiers ou des utilisateurs avertis d’effectuer des actions, normalement manuelles et fastidieuses, grâce à du code. Imaginons, que je bloque des gens sur BlueSky, et j’aimerais savoir si un autre compte a bloqué les mêmes comptes que moi. Je dois : Prendre ma liste de personnes bloquées Prendre la liste des personnes bloquées par l’autre compte Et pour chaque nom vérifier s’il est présent dans les deux listes. C’est pas impossible à faire, sur BlueSky en tous cas car tout est public. Mais c’est extrêmement chiant. Autre exemple. Imaginez que je veuille bloquer toutes les personnes qui ont liké un post (Parce que par exemple c’est un post qui vante les mérites de Kubernetes et que je n'aime pas Kubernetes) Je dois pour ça : Prendre le post Voir la liste des personnes qui ont liké le post Bloquer une à une les personnes Hey, on va pas se mentir, c’est chiant comme la pluie à faire ! Surtout que tous les services ne se valent pas en termes d’API. Pricing excessif à la Twitter (Oui je dis toujours Twitter, tu vas faire quoi Elon ?), extrêmement restrictif à la LinkedIn ou juste parfois non documenté à la Yammer, on pourrait faire un article entier dédié aux différents designs des API. Il existe quand même des bons élèves, à propos des APIs, on peut parler de BlueSky. Bon élève principalement car leur application web est basée sur leur propre API. Ce qui aide pas mal à avoir une API propre. Mais aussi propre soit l’API BlueSky, ça reste une API, une API REST. Donc un protocole Web. C’est très bien les API REST, ça peut être utilisé par n’importe quel langage (Bash y arrive c’est pour vous dire !) Sauf qu'entre les appels asynchrones à gérer et les codes de réponses HTTP qui sont plus longs qu’une liste de courses de fin d’année, ça peut être… embêtant à gérer… proprement. Pour masquer l’utilisation des API il est donc possible d’utiliser des SDK. Les SDK sont des bibliothèques pour votre langage qui facilitent l’utilisation d’un service. Pour BlueSky vous avez par exemple des SDK TypeScript ou Python (Alors autant je vois l’utilité d’un SDK Python, autant TypeScript, c’est déjà des gens chelous qui font du web, je pense qu’ils ont l’habitude de faire des appels sur des API REST) Si par contre vous codez avec autre chose comme du Java ou du C#, vous n’aurez pas le choix que de gérer vos appels REST vous-même. Heureusement, mes sharpistes, pour vous pas de galère, on va voir ici comment résoudre nos problèmes en C# ! Hello World Première chose : il nous faut donc un SDK ! Ça tombe bien, sur Nuggets on peut trouver un SDK nommé ATbluePandaSDK, ce SDK permet d’interagir simplement avec BlueSky en C#. Pour l’installer, rien de plus simple : allez dans votre gestionnaire de packages Nugget ou exécutez la commande : dotnet add package ATbluePandaSDK --version 0.1.2 Avant de faire notre use cases super complexe, on va tester quelque chose de simple et basique : un petit Hello World. On ouvre notre projet ConsoleApp1 car on n’est pas là pour donner des noms à nos projets, on n’a pas le temps. Commençons avec ce code assez simple : using ATPandaSDK; using ATPandaSDK.Models.Auth; Console.WriteLine("Hello, World!"); ATPClient client = new ATPClient(); AuthRequest authRequest = new AuthRequest("handle.bsky.social", "password"); BskyAuthUser authUser = client.Authenticate(authRequest); client.CreatePost("Hello world from ATbluePandaSDK version 0.1.2"); Si vous exécutez ce code, vous devriez avoir juste une sortie console disant "Hello world". Mais là où vous devriez regarder, c’est maintenant sur votre compte BlueSky : vous devriez voir quelque chose comme ceci : Le code est court, mais on va quand même l’expliquer : On commence par créer un objet client de type ATPClient. Ce client, c’est vraiment la classe la plus importante du SDK : tout ce que vous voulez faire sur BlueSky est fait grâce à ce client. Mais pour faire des trucs, on doit commencer par se connecter. Pour cela, on va créer un objet AuthRequest qui reçoit en paramètre votre handle et votre mot de passe. "Mais pour faire des trucs, on doit commencer par se connecter" En fait c'est faux, tous les endpoints ne demandent pas une authentification, mais le post en l’occurrence — et d’autres que l’on va utiliser — le nécessitent. Puis on s’authentifie via la méthode Authenticate du client ATP qui prend en paramètre notre AuthRequest précédemment créé, et qui va nous renvoyer un objet BskyAuthUser. Cet objet, c’est vous, votre identité. Il contient vos informations principales comme votre DID, votre handle, mais aussi — et surtout — votre token, qui va permettre d’utiliser d’autres endpoints de l’API BlueSky sans redonner votre mot de passe. Ne le donnez à personne ! Finalement, on crée notre post via la fonction CreatePost, qui prend en paramètre le texte que l’on souhaite poster. Notez qu

May 7, 2025 - 09:25
 0
SDK BlueSky : Utiliser C# pour comprendre les blocages entre utilisateurs

La plus part des services, réseaux sociaux compris, on des API disponibles pour permettre à des programmes tiers ou des utilisateurs avertis d’effectuer des actions, normalement manuelles et fastidieuses, grâce à du code.

Imaginons, que je bloque des gens sur BlueSky, et j’aimerais savoir si un autre compte a bloqué les mêmes comptes que moi. Je dois :

  • Prendre ma liste de personnes bloquées
  • Prendre la liste des personnes bloquées par l’autre compte
  • Et pour chaque nom vérifier s’il est présent dans les deux listes.

C’est pas impossible à faire, sur BlueSky en tous cas car tout est public. Mais c’est extrêmement chiant.

Autre exemple. Imaginez que je veuille bloquer toutes les personnes qui ont liké un post (Parce que par exemple c’est un post qui vante les mérites de Kubernetes et que je n'aime pas Kubernetes)

Je dois pour ça :

  • Prendre le post
  • Voir la liste des personnes qui ont liké le post
  • Bloquer une à une les personnes

Hey, on va pas se mentir, c’est chiant comme la pluie à faire !

Surtout que tous les services ne se valent pas en termes d’API. Pricing excessif à la Twitter (Oui je dis toujours Twitter, tu vas faire quoi Elon ?), extrêmement restrictif à la LinkedIn ou juste parfois non documenté à la Yammer, on pourrait faire un article entier dédié aux différents designs des API.

Il existe quand même des bons élèves, à propos des APIs, on peut parler de BlueSky. Bon élève principalement car leur application web est basée sur leur propre API. Ce qui aide pas mal à avoir une API propre.

Mais aussi propre soit l’API BlueSky, ça reste une API, une API REST. Donc un protocole Web. C’est très bien les API REST, ça peut être utilisé par n’importe quel langage (Bash y arrive c’est pour vous dire !)

Sauf qu'entre les appels asynchrones à gérer et les codes de réponses HTTP qui sont plus longs qu’une liste de courses de fin d’année, ça peut être… embêtant à gérer… proprement.

Pour masquer l’utilisation des API il est donc possible d’utiliser des SDK. Les SDK sont des bibliothèques pour votre langage qui facilitent l’utilisation d’un service.

Pour BlueSky vous avez par exemple des SDK TypeScript ou Python (Alors autant je vois l’utilité d’un SDK Python, autant TypeScript, c’est déjà des gens chelous qui font du web, je pense qu’ils ont l’habitude de faire des appels sur des API REST)

Si par contre vous codez avec autre chose comme du Java ou du C#, vous n’aurez pas le choix que de gérer vos appels REST vous-même.

Heureusement, mes sharpistes, pour vous pas de galère, on va voir ici comment résoudre nos problèmes en C# !

Hello World

Première chose : il nous faut donc un SDK !
Ça tombe bien, sur Nuggets on peut trouver un SDK nommé ATbluePandaSDK, ce SDK permet d’interagir simplement avec BlueSky en C#.

Pour l’installer, rien de plus simple : allez dans votre gestionnaire de packages Nugget ou exécutez la commande :

dotnet add package ATbluePandaSDK --version 0.1.2

Avant de faire notre use cases super complexe, on va tester quelque chose de simple et basique : un petit Hello World.

On ouvre notre projet ConsoleApp1 car on n’est pas là pour donner des noms à nos projets, on n’a pas le temps.

Commençons avec ce code assez simple :

using ATPandaSDK;
using ATPandaSDK.Models.Auth;

Console.WriteLine("Hello, World!");

ATPClient client = new ATPClient();
AuthRequest authRequest = new AuthRequest("handle.bsky.social", "password");
BskyAuthUser authUser = client.Authenticate(authRequest);

client.CreatePost("Hello world from ATbluePandaSDK version 0.1.2");

Si vous exécutez ce code, vous devriez avoir juste une sortie console disant "Hello world".
Mais là où vous devriez regarder, c’est maintenant sur votre compte BlueSky : vous devriez voir quelque chose comme ceci :

BlueSky Post saying hello world

Le code est court, mais on va quand même l’expliquer :

On commence par créer un objet client de type ATPClient. Ce client, c’est vraiment la classe la plus importante du SDK : tout ce que vous voulez faire sur BlueSky est fait grâce à ce client.

Mais pour faire des trucs, on doit commencer par se connecter. Pour cela, on va créer un objet AuthRequest qui reçoit en paramètre votre handle et votre mot de passe.

"Mais pour faire des trucs, on doit commencer par se connecter" En fait c'est faux, tous les endpoints ne demandent pas une authentification, mais le post en l’occurrence — et d’autres que l’on va utiliser — le nécessitent.

Puis on s’authentifie via la méthode Authenticate du client ATP qui prend en paramètre notre AuthRequest précédemment créé, et qui va nous renvoyer un objet BskyAuthUser.
Cet objet, c’est vous, votre identité. Il contient vos informations principales comme votre DID, votre handle, mais aussi — et surtout — votre token, qui va permettre d’utiliser d’autres endpoints de l’API BlueSky sans redonner votre mot de passe.

Ne le donnez à personne !

Finalement, on crée notre post via la fonction CreatePost, qui prend en paramètre le texte que l’on souhaite poster.

Notez qu’on n’a pas utilisé le BskyAuthUser. On aurait pu, mais le client ATP le garde en mémoire, et vous pouvez donc l’omettre pour vos prochaines actions.

Bravo ! Vous avez fait votre Hello World avec le SDK C# de BlueSky.
Ému ? Attendez, c’est pas fini !

Un vrai use case

Ok, vous avez pu tester les premières fonctionnalités du SDK pour vous assurer que tout marche correctement. Sauf que poster sur BlueSky via votre IDE, c’est très cool, mais c’est, je pense, moins user friendly que via l’application web. Alors allons ensemble un peu plus loin avec notre tout premier exemple : connaître les comptes bloqués par moi-même et un autre utilisateur.

À quoi cela peut bien servir ? Je ne sais pas, peut-être un futur Tinder qui vous proposera des matchs via une compatibilité basée sur votre pourcentage en commun de gens bloqués !

Commençons par récupérer notre propre liste des gens qu’on a bloqués et afficher leur nom :

using ATbluePandaSDK.Models.Account;
using ATPandaSDK;
using ATPandaSDK.Models.Auth;

ATPClient client = new ATPClient();
AuthRequest authRequest = new AuthRequest("handle.bsky.social", "password");
BskyAuthUser authUser = client.Authenticate(authRequest);
List<Block> listOfUsersBlocked = client.GetBlocks();
foreach (Block b in listOfUsersBlocked)
{
    Console.WriteLine(b.displayName);
}

Ce code donnera pour moi cette sortie :

Pleople I blocked on bsky

Pour vous bien sûr, il s’agira de vos propres gens bloqués, mais n’ayez pas honte de partager votre liste, de toute façon c’est public !

Notez que ce sont les gens que vous avez bloqués personnellement, les gens bloqués via des listes de modération ne sont pas affichés ici !

Reprenons ensemble le code à partir de la connexion !

Avec notre client, nous appelons la fonction GetBlocks qui retourne une liste de personnes bloquées (Pas de chance pour eux !) — cette fonction s’exécute pour l’utilisateur connecté, donc nous-même, et uniquement nous-même !

On parcourt cette liste, et dans les différents attributs de notre objet Block, nous avons par exemple le displayName (on a d’autres infos, mais pas utiles pour le moment).

Est-ce que Block est un User ?
Oui, il existe un objet User qui a beaucoup plus d’informations, mais Block a la majorité des informations d’un utilisateur, vous pouvez donc passer facilement d’un objet Block à un objet User si vous le souhaitez !

Prochaine étape : obtenir la liste des personnes bloquées par quelqu’un d’autre !

Pour ça, on va devoir utiliser deux autres fonctions du client :

using ATbluePandaSDK.Models.Account;
using ATPandaSDK;
using ATPandaSDK.Models.Auth;

ATPClient client = new ATPClient();
AuthRequest authRequest = new AuthRequest("handle.bsky.social", "password");
BskyAuthUser authUser = client.Authenticate(authRequest);

List<Block> listOfUsersBlocked = client.GetBlocks();

User actor = client.GetUserProfil("otherhandle.bsky.social");
List<Records> otherListOfUsersBlocked = client.GetAccountsBlocked(actor, cursor: true);

Il va nous falloir cette fois un acteur (qui est un objet User).
On peut l’obtenir de plein de manières. Ici, on a utilisé la fonction GetUserProfil qui permet d’obtenir toutes les informations d’un utilisateur. Vous pouvez passer en paramètre de cette fonction un DID ou un handle.

On a donc maintenant deux listes : une de Block (les utilisateurs que l’on a bloqués), et une de Record (qui est un terme un peu valise chez BlueSky — mais dans notre cas, ce sont aussi des gens bloqués !).

On ne rentrera pas dans le détail ici de ce qu’est un Record, ce blog post est déjà beaucoup trop long !

Nous avons donc deux listes, que nous pouvons maintenant croiser facilement car nous sommes en C# et pas en Bash !

using ATbluePandaSDK.Models;
using ATbluePandaSDK.Models.Account;
using ATPandaSDK;
using ATPandaSDK.Models.Auth;

ATPClient client = new ATPClient();
AuthRequest authRequest = new AuthRequest("handle.bsky.social", "password");
BskyAuthUser authUser = client.Authenticate(authRequest);

List<Block> listOfUsersBlocked = client.GetBlocks();

User actor = client.GetUserProfil("otherhandle.bsky.social");
List<Records> otherListOfUsersBlocked = client.GetAccountsBlocked(actor, cursor: true);

foreach (Block b in listOfUsersBlocked)
{
    foreach (Records r in otherListOfUsersBlocked)
    {
        if (b.did.Equals(r.Value.Subject))
        {
            try
            {
                User userBlocked = client.GetUserProfil(b.did);
                Console.WriteLine(userBlocked.DisplayName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

Voici ma sortie :

List of people blocked by myself AND another user

On voit que la liste est plus courte qu’avant (c’est normal, c’est une sorte de inner join que nous avons fait !). Encore une fois, la sortie sera pour vous sans doute différente.

Attention, l’instruction GetAccountsBlocked peut être longue si la personne a une longue liste de blocages.
Vous voyez en effet que cette fonction a l’argument cursor à true — cela veut dire qu’on doit faire plusieurs requêtes pour gérer la pagination, et cela peut prendre du temps selon le nombre de pages.

Conclusion

Vous avez aimé ce blog post ? N’hésitez pas à le faire savoir en likant mon post hello world. Maintenant que vous avez un SDK, rien de plus simple :

using ATPandaSDK;
using ATPandaSDK.Models.Auth;
using ATPandaSDK.Models.Feed;

ATPClient client = new ATPClient();
AuthRequest authRequest = new AuthRequest("handle.bsky.social", "password");
BskyAuthUser authUser = client.Authenticate(authRequest);
BskyTimeline timeline = client.GetAuthorTimeline();
BskyThread helloWorld = client.GetPostThread("at://did:plc:6rujkdwb4mzzplqzccqmui2h/app.bsky.feed.post/3lojdtvoqb52g");
client.LikePost(helloWorld.thread.post);

Et si vous souhaitez aller plus loin, il y a plein d'autres fonctions déjà disponibles dans le SDK :

Le like/unlike, mais aussi le follow/unfollow, block/unblock, mute/unmute et l’accès à toutes vos timelines.