using System.Collections.Generic; using Newtonsoft.Json; using System.Net.Http.Json; // https://tt-rss.org/wiki/ApiReference namespace ttrss_co_client.ttrss { public class ApiClient { public Uri BaseURI { get; private set; } private HttpClient httpClient { get; set; } private string SessionId { get; set; } = null; private int api_level{get;set;} public ApiClient(Uri baseUri) { BaseURI = baseUri; httpClient = new HttpClient() { BaseAddress = baseUri }; } public async Task Login(string username, string password) { var json = new { op = "login", user = username, password = password }; var content = JsonContent.Create(json); var response = await (await httpClient.PostAsync(BaseURI, content)).Content.ReadAsStringAsync(); var loginResult = JsonConvert.DeserializeObject(response); if (loginResult.status == 0) { SessionId = loginResult.content.session_id; api_level = loginResult.content.api_level ?? 1; Console.WriteLine(SessionId); } else { throw new NotImplementedException(); } } public async Task GetApiLevel() { assertInitialized(); throw new NotImplementedException(); } public async Task GetVersion() { assertInitialized(); throw new NotImplementedException(); } public async Task Logout() { assertInitialized(); throw new NotImplementedException(); } public async Task IsLoggedIn() { assertInitialized(); throw new NotImplementedException(); } public async Task GetUnread() { assertInitialized(); throw new NotImplementedException(); } public async Task GetFeeds(int cat_id, bool unread_only, int limit, int offset, bool include_nested) { assertInitialized(); throw new NotImplementedException(); } public async Task GetCategories(bool unread_only, bool enable_nested, bool include_empty) { assertInitialized(); throw new NotImplementedException(); } public enum VIEWMODE { All, Unread, Adaptive, Marked, Updated } public enum SORTORDER { Default, OldestFirst, NewestFirst } public async Task GetHeadlines(int feed_id, int limit, int skip, /*string filter, */ bool is_cat, bool show_excerpt, bool show_content, VIEWMODE view_mode, bool include_attachments, int since_id, bool include_nested, SORTORDER order_by, bool sanitize, bool force_update = false, bool has_sandbox = false, bool include_header) { await getHeadlines(feed_id, null, limit, skip, /*filter, */ is_cat, show_excerpt, show_content, view_mode, include_attachments, since_id, include_nested, order_by, sanitize, force_update, has_sandbox, include_header); } public async Task GetHeadlines(string feed_id, int limit, int skip, /*string filter, */ bool is_cat, bool show_excerpt, bool show_content, VIEWMODE view_mode, bool include_attachments, int since_id, bool include_nested, SORTORDER order_by, bool sanitize, bool force_update = false, bool has_sandbox = false, bool include_header) { await getHeadlines(null, feed_id, limit, skip, /*filter, */ is_cat, show_excerpt, show_content, view_mode, include_attachments, since_id, include_nested, order_by, sanitize, force_update, has_sandbox, include_header); } private async Task getHeadlines(int? int_feed_id, string string_feed_id, int limit, int skip, /*string filter, */ bool is_cat, bool show_excerpt, bool show_content, VIEWMODE view_mode, bool include_attachments, int since_id, bool include_nested, SORTORDER order_by, bool sanitize, bool force_update, bool has_sandbox, bool include_header) { assertInitialized(); throw new NotImplementedException(); } public enum UPDATEMODE { SetFalse, SetTrue, Toggle } public enum UPDATEFIELD { starred, published, unread } public async Task UpdateArticleField(UPDATEMODE mode, UPDATEFIELD field, params int[] ids) { //documentation: UpdateArticle - for note, we have a separate method UpdateArticleNote assertInitialized(); throw new NotImplementedException(); } public async Task UpdateArticleNote(string data, params int[] ids) { //documentation: UpdateArticle - for fields other than note, we have a separate method UpdateArticleField assertInitialized(); throw new NotImplementedException(); } public async Task> GetArticle(params int[] article_id) { if (!article_id.Any()) { throw new ArgumentException("need at least one article_id"); } assertInitialized(); throw new NotImplementedException(); } public async Task GetConfig() { assertInitialized(); throw new NotImplementedException(); } /// ///tell the feed to update. As opposed to updating our configuration of the feed. /// public async Task UpdateFeed(int feed_id) { assertInitialized(); throw new NotImplementedException(); } public async Task GetPref(string key) { assertInitialized(); throw new NotImplementedException(); } public enum CATCHUPMODE { All, OneDay, OneWeek, TwoWeeks } public async Task CatchupFeed(int feed_id, bool is_cat, CATCHUPMODE mode = CATCHUPMODE.All) { assertInitialized(); throw new NotImplementedException(); } public async Task GetCounters(bool actual_feeds = true, bool labels = true, bool categories = true, bool tags = false) { assertInitialized(); throw new NotImplementedException(); } public async Task GetLabels(int? article_id) { assertInitialized(); if(article_id != null) { assertApiLevel(5); } throw new NotImplementedException(); } public async Task SetArticleLabel(int label_id, bool assign, params int[] article_ids) { //there's a label "cache", i guess? assertInitialized(); throw new NotImplementedException(); } public async Task ShareToPublished(string title, Uri url, string content, bool sanitize = true) { assertInitialized(); assertApiLevel(4); if(!sanitize) assertApiLevel(20); throw new NotImplementedException(); } /// ///if the feed requires basic HTTP auth; the login. (decidedly not self-explanatory, gdi) ///if the feed requires basic HTTP auth; the password. (decidedly not self-explanatory, gdi) /// public async Task SubscribeToFeed(Uri feed_url, int category_id, string login, string password) { assertInitialized(); assertApiLevel(5); throw new NotImplementedException(); } public async Task UnsubscribeFeed() { assertInitialized(); assertApiLevel(5); throw new NotImplementedException(); } public async Task GetFeedTree() { assertInitialized(); assertApiLevel(5); throw new NotImplementedException(); } private void assertInitialized() { if (SessionId == null) { throw new InvalidOperationException("no session ID - call Login first!"); } } private void assertApiLevel(int ApiLevel) { if(ApiLevel > this.api_level) { throw new NotSupportedException($"method requires api level {ApiLevel}, have {this.api_level}"); } } } }