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âon nâa pas utilisĂ© le
BskyAuthUser. On aurait pu, mais le clientATPle 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 :
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 :
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
GetAccountsBlockedpeut ĂȘtre longue si la personne a une longue liste de blocages.
Vous voyez en effet que cette fonction a lâargumentcursorĂ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.



Top comments (0)