Client API methods for Lichess account and social actions. It makes HTTP requests via helper methods to get account email, profile, preferences, kid mode status, follow/unfollow/block/unblock users, set kid mode, and fetch timeline parsing JSON into domain types.
#nullable enable annotations
using LichessNET.Entities;
using LichessNET.Entities.Account;
using LichessNET.Entities.Social;
using LichessNET.Entities.Social.Timeline;
namespace LichessNET.API;
public partial class LichessApiClient
{
/// <summary>
/// Retrieves the email address of the authenticated user.
/// </summary>
/// <returns>
/// A string representing the email address of the authenticated user.
/// </returns>
public async Task<string> GetAccountEmail()
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold("api/account/email");
var response = await SendRequest(request);
var content = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
return content["email"];
}
/// <summary>
/// Retrieves the profile information of the authenticated user from the Lichess platform.
/// </summary>
/// <returns>
/// An instance of <see cref="LichessUser"/> representing the profile details of the user.
/// </returns>
public async Task<LichessUser> GetOwnProfile()
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold("api/account");
var response = await SendRequest(request);
return await response.Content.ReadFromJsonAsync<LichessUser>();
}
/// <summary>
/// Retrieves the account preferences of the authenticated user.
/// </summary>
/// <returns>
/// An instance of <see cref="AccountPreferences"/> representing the user's account preferences.
/// </returns>
public async Task<AccountPreferences> GetAccountPreferences()
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold("api/account/preferences");
var response = await SendRequest(request);
var preferences = await response.Content.ReadFromJsonAsync<AccountPreferences>();
return preferences;
}
/// <summary>
/// Determines whether the authenticated user's account is in kid mode.
/// </summary>
/// <returns>
/// A boolean value indicating if the user's account is set to kid mode.
/// </returns>
public async Task<bool> GetKidModeStatus()
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold("api/account/kid");
var response = await SendRequest(request);
var content = await response.Content.ReadFromJsonAsync<Dictionary<string, bool>>();
return content["kid"];
}
/// <summary>
/// Sets the kid mode status for the authenticated account.
/// </summary>
/// <param name="enable">
/// A boolean value indicating whether to enable or disable kid mode.
/// </param>
/// <returns>
/// A boolean indicating whether the operation was successful.
/// </returns>
public async Task<bool> SetKidModeStatus(bool enable)
{
var request = GetRequestScaffold("api/account/kid", Tuple.Create("v", enable.ToString()));
var response = await SendRequest(request, "POST");
var result = LichessJson.Deserialize<Dictionary<string, bool>>(await response.Content.ReadAsStringAsync());
return result != null && result.TryGetValue("ok", out var ok) && ok;
}
/// <summary>
/// Follows a player with the specified username on Lichess.
/// </summary>
/// <param name="username">
/// The username of the player to follow.
/// </param>
/// <returns>
/// A boolean value indicating whether the operation was successful.
/// </returns>
public async Task<bool> FollowPlayerAsync(string username)
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold($"api/rel/follow/{username}");
var response = await SendRequest(request, "POST");
var content = await response.Content.ReadFromJsonAsync<Dictionary<string, bool>>();
return content["ok"];
}
/// <summary>
/// Unfollows a specified player using their username.
/// </summary>
/// <param name="username">
/// The username of the player to unfollow.
/// </param>
/// <returns>
/// A boolean value indicating whether the operation was successful.
/// </returns>
public async Task<bool> UnfollowPlayerAsync(string username)
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold($"api/rel/unfollow/{username}");
var response = await SendRequest(request, "POST");
var content = await response.Content.ReadFromJsonAsync<Dictionary<string, bool>>();
return content["ok"];
}
/// <summary>
/// Blocks a player on Lichess based on their username.
/// </summary>
/// <param name="username">
/// The username of the player to be blocked.
/// </param>
/// <returns>
/// A boolean indicating whether the player was successfully blocked.
/// </returns>
public async Task<bool> BlockPlayerAsync(string username)
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold($"api/rel/block/{username}");
var response = await SendRequest(request, "POST");
var content = await response.Content.ReadFromJsonAsync<Dictionary<string, bool>>();
return content["ok"];
}
/// <summary>
/// Unblocks a player specified by username.
/// </summary>
/// <param name="username">
/// The username of the player to unblock.
/// </param>
/// <returns>
/// A boolean value indicating whether the player was successfully unblocked.
/// </returns>
public async Task<bool> UnblockPlayerAsync(string username)
{
await _ratelimitController.Consume("api/account", false);
var request = GetRequestScaffold($"api/rel/unblock/{username}");
var response = await SendRequest(request, "POST");
var content = await response.Content.ReadFromJsonAsync<Dictionary<string, bool>>();
return content["ok"];
}
/// <summary>
/// Gets the timeline of the authenticated user.
/// </summary>
/// <param name="since">When the timeline should start</param>
/// <param name="nb">The number of timeline events that should be loaded. Defaults to 15, the maximum is 50.</param>
/// <returns>A Timeline object</returns>
public async Task<Timeline?> GetTimelineAsync(DateTime since, int nb = 15)
{
await _ratelimitController.Consume("api/timeline", false);
var unixTimestamp = new DateTimeOffset(since).ToUnixTimeMilliseconds();
var request = GetRequestScaffold($"api/timeline",
new Tuple<string, string>("since", unixTimestamp.ToString()),
new Tuple<string, string>("nb", nb.ToString()));
var response = await SendRequest(request);
var content = await response.Content.ReadAsStringAsync();
var root = LichessJson.Parse(content);
var timeline = new Timeline
{
Entries = new List<TimelineEntry>(),
Users = root.TryGetProperty("users", out var users)
? users.Deserialize<Dictionary<string, TimelineUser>>(LichessJson.Options) ?? new Dictionary<string, TimelineUser>()
: new Dictionary<string, TimelineUser>()
};
if (root.TryGetProperty("entries", out var entries))
{
foreach (var entryElement in entries.EnumerateArray())
{
var type = entryElement.TryGetProperty("type", out var typeElement) ? typeElement.GetString() : null;
var date = entryElement.TryGetProperty("date", out var dateElement) ? dateElement.GetInt64() : 0;
var data = entryElement.TryGetProperty("data", out var dataElement)
? TimelineEventDataConverter.DeserializeData(type, dataElement, LichessJson.Options)
: new UnknownEventData();
timeline.Entries.Add(new TimelineEntry
{
Type = type,
Date = date,
Data = data
});
}
}
return timeline;
}
}