DEV Community

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
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)