Compare commits

...

2 Commits

Author SHA1 Message Date
1480efdd82 several more methods 2023-04-03 00:36:53 -04:00
290092df5a runs. generic API response. getApiLevel works. 2023-04-03 00:10:07 -04:00
7 changed files with 142 additions and 21 deletions

26
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net7.0/ttrss-co-client.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

42
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/ttrss-co-client.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/ttrss-co-client.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/ttrss-co-client.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View File

@ -9,7 +9,21 @@ namespace ttrss_co_client
var conf = Configure(); var conf = Configure();
var ttrssClient = new ttrss.ApiClient(conf.BaseURI); var ttrssClient = new ttrss.ApiClient(conf.BaseURI);
await ttrssClient.Login(conf.Username, conf.Password); await ttrssClient.Login(conf.Username, conf.Password);
Console.WriteLine("Hello, World!");
var loggedin = await ttrssClient.IsLoggedIn();
Console.WriteLine($"logged in: {loggedin}");
var apiLevel = await ttrssClient.GetApiLevel();
Console.WriteLine($"api level: {apiLevel}");
var unread = await ttrssClient.GetUnread();
Console.WriteLine($"{unread} unread article{(unread == 1 ? "" : "s")}");
var loggedout = await ttrssClient.Logout();
Console.WriteLine($"logged out: {loggedout}");
loggedin = await ttrssClient.IsLoggedIn();
Console.WriteLine($"logged in: {loggedin}");
} }
static Configuration Configure(string configurationPath = "appsettings.json") static Configuration Configure(string configurationPath = "appsettings.json")
{ {

View File

@ -1,2 +1,5 @@
# ttrss-co-pilot # ttrss-co-pilot
wait i wanted to call it ttrss-co-client, dammit
but that name isn't good anyway

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Net.Http.Json; using System.Net.Http.Json;
@ -11,7 +12,7 @@ namespace ttrss_co_client.ttrss
public Uri BaseURI { get; private set; } public Uri BaseURI { get; private set; }
private HttpClient httpClient { get; set; } private HttpClient httpClient { get; set; }
private string SessionId { get; set; } = null; private string SessionId { get; set; } = null;
private int api_level{get;set;} private int api_level { get; set; }
public ApiClient(Uri baseUri) public ApiClient(Uri baseUri)
{ {
@ -45,30 +46,26 @@ namespace ttrss_co_client.ttrss
public async Task<int> GetApiLevel() public async Task<int> GetApiLevel()
{ {
assertInitialized(); assertInitialized();
throw new NotImplementedException(); return await oneValueGet<int>("getApiLevel", "level");
}
public async Task<string> GetVersion()
{
assertInitialized();
throw new NotImplementedException();
} }
public async Task<bool> Logout() public async Task<bool> Logout()
{ {
assertInitialized(); assertInitialized();
throw new NotImplementedException();
return (await oneValueGet<string>("logout", "status"))?.ToLower() == "ok";
} }
public async Task<bool> IsLoggedIn() public async Task<bool> IsLoggedIn()
{ {
assertInitialized(); //assertInitialized();
throw new NotImplementedException(); return (await oneValueGet<bool>("isLoggedIn", "status"));
} }
public async Task<int> GetUnread() public async Task<int> GetUnread()
{ {
assertInitialized(); assertInitialized();
throw new NotImplementedException(); return await oneValueGet<int>("getUnread", "unread");
} }
public async Task GetFeeds(int cat_id, bool unread_only, int limit, int offset, bool include_nested) public async Task GetFeeds(int cat_id, bool unread_only, int limit, int offset, bool include_nested)
{ {
assertInitialized(); assertInitialized();
@ -81,11 +78,11 @@ namespace ttrss_co_client.ttrss
} }
public enum VIEWMODE { All, Unread, Adaptive, Marked, Updated } public enum VIEWMODE { All, Unread, Adaptive, Marked, Updated }
public enum SORTORDER { Default, OldestFirst, NewestFirst } 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) 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)
{ {
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); 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) 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)
{ {
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); 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);
} }
@ -149,7 +146,7 @@ namespace ttrss_co_client.ttrss
public async Task GetLabels(int? article_id) public async Task GetLabels(int? article_id)
{ {
assertInitialized(); assertInitialized();
if(article_id != null) if (article_id != null)
{ {
assertApiLevel(5); assertApiLevel(5);
} }
@ -165,7 +162,7 @@ namespace ttrss_co_client.ttrss
{ {
assertInitialized(); assertInitialized();
assertApiLevel(4); assertApiLevel(4);
if(!sanitize) if (!sanitize)
assertApiLevel(20); assertApiLevel(20);
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -200,10 +197,37 @@ namespace ttrss_co_client.ttrss
} }
private void assertApiLevel(int ApiLevel) private void assertApiLevel(int ApiLevel)
{ {
if(ApiLevel > this.api_level) if (ApiLevel > this.api_level)
{ {
throw new NotSupportedException($"method requires api level {ApiLevel}, have {this.api_level}"); throw new NotSupportedException($"method requires api level {ApiLevel}, have {this.api_level}");
} }
} }
private async Task<T> oneValueGet<T>(string op, string key)
{
//mostly you post {"op": "aThingToDo", "sid": "sessionId", "some other param": "some other value"}
//and get back something like {"seq": 0, "status", "content": {"the value you asked for": 0}}
var json = JsonContent.Create(new
{
op = op,
sid = this.SessionId
});
var response = await (await httpClient.PostAsync(BaseURI, json)).Content.ReadAsStringAsync();
var apiResult = JsonConvert.DeserializeObject<ttrss.messages.GenericApiResponse>(response);
try
{
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
return (T)converter.ConvertFromString(apiResult.Content[key]);
}
return default(T);
}
catch (NotSupportedException)
{
return default(T);
}
}
} }
} }

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace ttrss_co_client.ttrss.messages
{
public abstract class ApiResponse
{
public int seq { get; set; }
public int status { get; set; }
}
public class GenericApiResponse : ApiResponse
{
public Dictionary<string, string> Content{get; set;}
}
}

View File

@ -1,9 +1,7 @@
namespace ttrss_co_client.ttrss.messages namespace ttrss_co_client.ttrss.messages
{ {
public class LoginResponse public class LoginResponse : ApiResponse
{ {
public int seq { get; set; }
public int status { get; set; }
public Content content { get; set; } public Content content { get; set; }
public class Content public class Content