diff --git a/ttrss/ApiClient.cs b/ttrss/ApiClient.cs index ddb9ef1..7a94621 100644 --- a/ttrss/ApiClient.cs +++ b/ttrss/ApiClient.cs @@ -5,6 +5,7 @@ using System.Net.Http.Json; using ttrss_co_client.ttrss.datastructures; // https://tt-rss.org/wiki/ApiReference +//TODO: a lot of these are a given at API level 1, so double check all necessary API levels namespace ttrss_co_client.ttrss { @@ -35,7 +36,15 @@ namespace ttrss_co_client.ttrss if (loginResult.status == 0) { SessionId = loginResult.content.session_id; - api_level = loginResult.content.api_level ?? 1; + if(loginResult.content.api_level == null) + { + throw new NotImplementedException($"api doesn't report an api level - unsupported. api level 1 is version 1.5.8, so {BaseURI} might be extremely old. (or maybe this library is extremely old and ttrss changed again?)"); + } + else + { + api_level = loginResult.content.api_level.Value; + } + Console.WriteLine(SessionId); } else @@ -46,6 +55,16 @@ namespace ttrss_co_client.ttrss public async Task GetApiLevel() { + //1.5.8 = api level 1, any lower than that, unsupported. + //???? = 2 + //???? = 3 + //1.6.0 = 4 + //1.7.6 = 5 + //1.8 = ???? + //???? = 6 + //???? = 7 + //???? = 8 + //1.14 = 9 assertInitialized(); return await oneValueGet("getApiLevel", "level"); } @@ -71,7 +90,6 @@ namespace ttrss_co_client.ttrss public async Task> GetCounters(bool feeds = true, bool labels = true, bool categories = true, bool tags = false) { assertInitialized(); - assertApiLevel(4); var output_mode = ""; if (feeds) output_mode += "f"; @@ -140,19 +158,271 @@ namespace ttrss_co_client.ttrss } 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 = false) + public async Task> GetHeadlines( + int feed_id, + bool is_cat, + int limit=60, + int skip=0, + /*string filter,*/ + bool show_excerpt = false, + bool show_content=false, + VIEWMODE view_mode = VIEWMODE.All, + bool include_attachments = false, + int? since_id = null, + bool include_nested = false, + SORTORDER order_by = SORTORDER.Default, + bool sanitize = true, + bool force_update = false, + bool has_sandbox = false) { - 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); + if(limit>60) + { + assertApiLevel(6); + } + if(limit > 200) + { + throw new ArgumentOutOfRangeException("limit", limit, "capped at 200"); + } + + if(include_nested) + { + assertApiLevel(4); + } + + string sortOrderString = ""; + if (order_by != SORTORDER.Default) + { + assertApiLevel(5); + switch (order_by) + { + case SORTORDER.OldestFirst: + sortOrderString = "date_reverse"; + break; + case SORTORDER.NewestFirst: + sortOrderString = "feed_dates"; + break; + } + } + + if(sanitize == false) + { + //TODO: it's version 1.8.0, but no idea what version that is. I can narrow it down to 6, 7, or 8. + assertApiLevel(6); + } + if(force_update) + { + assertApiLevel(9); + } + + var json = JsonContent.Create(new + { + op = "getHeadlines", + sid = this.SessionId, + feed_id = feed_id, + is_cat = is_cat, + limit = limit, + skip = skip, + show_excerpt = show_excerpt, + show_content = show_content, + view_mode = view_mode.ToString("D"), + include_attachments = include_attachments, + since_id = since_id, + include_nested = include_nested, + order_by = sortOrderString, + sanitize = sanitize, + force_update = force_update, + has_sandbox = has_sandbox + }); + return await getHeadlines(json); } - 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 = false) + public async Task> GetHeadlinesTag( + string tag, + int limit=200, + int skip=0, + /*string filter,*/ + bool show_excerpt = false, + bool show_content=false, + VIEWMODE view_mode = VIEWMODE.All, + bool include_attachments = false, + int? since_id = null, + bool include_nested = false, + SORTORDER order_by = SORTORDER.Default, + bool sanitize = true, + bool force_update = false, + bool has_sandbox = false + /*bool include_header = false*/) { - 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); + assertApiLevel(18); + + if(limit > 200) + { + throw new ArgumentOutOfRangeException("limit", limit, "capped at 200"); + } + + string sortOrderString; + switch(order_by) + { + case SORTORDER.OldestFirst: + sortOrderString = "date_reverse"; + break; + case SORTORDER.NewestFirst: + sortOrderString = "feed_dates"; + break; + default: + sortOrderString = ""; + break; + } + + var json = JsonContent.Create(new + { + op = "getHeadlines", + sid = this.SessionId, + feed_id = tag, + limit = limit, + skip = skip, + show_excerpt = show_excerpt, + show_content = show_content, + view_mode = view_mode.ToString("D"), + include_attachments = include_attachments, + since_id = since_id, + include_nested = include_nested, + order_by = sortOrderString, + sanitize = sanitize, + force_update = force_update, + has_sandbox = has_sandbox + }); + return await getHeadlines(json); } - 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) + private async Task> getHeadlines(JsonContent parameters) { - assertInitialized(); - throw new NotImplementedException(); + var response = await (await httpClient.PostAsync(BaseURI, parameters)).Content.ReadAsStringAsync(); + var apiResult = JsonConvert.DeserializeObject(response); + return apiResult.content; } + // public async Task GetHeadlinesAndHeader( + // int feed_id, + // bool is_cat, + // int limit=60, + // int skip=0, + // /*string filter,*/ + // bool show_excerpt = false, + // bool show_content=false, + // VIEWMODE view_mode = VIEWMODE.All, + // bool include_attachments = false, + // int? since_id = null, + // bool include_nested = false, + // SORTORDER order_by = SORTORDER.Default, + // bool sanitize = true, + // bool force_update = false, + // bool has_sandbox = false) + // { + // assertApiLevel(12); + // if(limit > 200) + // { + // throw new ArgumentOutOfRangeException("limit", limit, "capped at 200"); + // } + + // string sortOrderString = ""; + // if (order_by != SORTORDER.Default) + // { + // switch (order_by) + // { + // case SORTORDER.OldestFirst: + // sortOrderString = "date_reverse"; + // break; + // case SORTORDER.NewestFirst: + // sortOrderString = "feed_dates"; + // break; + // } + // } + + // var json = JsonContent.Create(new + // { + // op = "getHeadlines", + // sid = this.SessionId, + // feed_id = feed_id, + // is_cat = is_cat, + // limit = limit, + // skip = skip, + // show_excerpt = show_excerpt, + // show_content = show_content, + // view_mode = view_mode.ToString("D"), + // include_attachments = include_attachments, + // since_id = since_id, + // include_nested = include_nested, + // order_by = sortOrderString, + // sanitize = sanitize, + // force_update = force_update, + // has_sandbox = has_sandbox, + // include_header = true + // }); + // return await getHeadlinesAndHeader(json); + // } + // public async Task GetHeadlinesTagAndHeader( + // string tag, + // int limit=200, + // int skip=0, + // /*string filter,*/ + // bool show_excerpt = false, + // bool show_content=false, + // VIEWMODE view_mode = VIEWMODE.All, + // bool include_attachments = false, + // int? since_id = null, + // bool include_nested = false, + // SORTORDER order_by = SORTORDER.Default, + // bool sanitize = true, + // bool force_update = false, + // bool has_sandbox = false + // /*bool include_header = false*/) + // { + // assertApiLevel(18); + + // if(limit > 200) + // { + // throw new ArgumentOutOfRangeException("limit", limit, "capped at 200"); + // } + + // string sortOrderString; + // switch(order_by) + // { + // case SORTORDER.OldestFirst: + // sortOrderString = "date_reverse"; + // break; + // case SORTORDER.NewestFirst: + // sortOrderString = "feed_dates"; + // break; + // default: + // sortOrderString = ""; + // break; + // } + + // var json = JsonContent.Create(new + // { + // op = "getHeadlines", + // sid = this.SessionId, + // feed_id = tag, + // limit = limit, + // skip = skip, + // show_excerpt = show_excerpt, + // show_content = show_content, + // view_mode = view_mode.ToString("D"), + // include_attachments = include_attachments, + // since_id = since_id, + // include_nested = include_nested, + // order_by = sortOrderString, + // sanitize = sanitize, + // force_update = force_update, + // has_sandbox = has_sandbox, + // include_header = true + // }); + // return await getHeadlinesAndHeader(json); + // } + // private async Task getHeadlinesAndHeader(JsonContent parameters) + // { + // var response = await (await httpClient.PostAsync(BaseURI, parameters)).Content.ReadAsStringAsync(); + // var apiResult = JsonConvert.DeserializeObject(response); + // return apiResult; + // } public enum UPDATEMODE { SetFalse, SetTrue, Toggle } public enum UPDATEFIELD { starred, published, unread } public async Task UpdateArticleField(UPDATEMODE mode, UPDATEFIELD field, params int[] ids) diff --git a/ttrss/datastructures/Headline.cs b/ttrss/datastructures/Headline.cs new file mode 100644 index 0000000..2102829 --- /dev/null +++ b/ttrss/datastructures/Headline.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace ttrss_co_client.ttrss.datastructures +{ + public class Headline + { + public int id { get; set; } + public Guid guid { get; set; } + public bool unread { get; set; } + public bool marked { get; set; } + public bool published { get; set; } + public int updated { get; set; } + public bool is_updated { get; set; } + public string title { get; set; } + public Uri link { get; set; } + public int feed_id { get; set; } + public IEnumerable tags { get; set; } + public string content { get; set; } + ///See + public IEnumerable> labels { get; set; } + public string feed_title { get; set; } + public int comments_count { get; set; } + public Uri comments_link { get; set; } + public bool always_display_attachments { get; set; } + public string author { get; set; } + public double score { get; set; } + public string note { get; set; } + public string lang { get; set; } + public Uri flavor_image { get; set; } + public string flavor_stream { get; set; } + } +} \ No newline at end of file diff --git a/ttrss/datastructures/Label.cs b/ttrss/datastructures/Label.cs new file mode 100644 index 0000000..b56c98a --- /dev/null +++ b/ttrss/datastructures/Label.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace ttrss_co_client.ttrss.datastructures +{ + public class Label + { + public Label(string[] fromServer) + { + int.TryParse(fromServer[0], out id); + Title = fromServer[1]; + unknown = fromServer[2]; + Color = System.Drawing.ColorTranslator.FromHtml(fromServer[3]); + } + public int id; + public string Title { get; set; } + public string unknown { get; set; } + public System.Drawing.Color Color {get; set;} + } +} \ No newline at end of file diff --git a/ttrss/messages/HeadlinesHeaderResponse.cs b/ttrss/messages/HeadlinesHeaderResponse.cs new file mode 100644 index 0000000..1895544 --- /dev/null +++ b/ttrss/messages/HeadlinesHeaderResponse.cs @@ -0,0 +1,9 @@ +using ttrss_co_client.ttrss.datastructures; + +namespace ttrss_co_client.ttrss.messages +{ + public class HeadlinesHeaderResponse : ApiResponse + { + public IEnumerable content { get; set; } + } +} \ No newline at end of file diff --git a/ttrss/messages/HeadlinesResponse.cs b/ttrss/messages/HeadlinesResponse.cs new file mode 100644 index 0000000..86c626a --- /dev/null +++ b/ttrss/messages/HeadlinesResponse.cs @@ -0,0 +1,9 @@ +using ttrss_co_client.ttrss.datastructures; + +namespace ttrss_co_client.ttrss.messages +{ + public class HeadlinesResponse : ApiResponse + { + public IEnumerable content { get; set; } + } +} \ No newline at end of file