-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DoAddCommand - Replacement for NonWorking .Object API #40
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<package> | ||
<metadata> | ||
<id>DreadIpfsHttpClient</id> | ||
<version>0.5.0</version> | ||
<title>IpfsHttpClient</title> | ||
<readme>docs\README.md</readme> | ||
<authors>DreadfulBot</authors> | ||
<requireLicenseAcceptance>false</requireLicenseAcceptance> | ||
<license type="expression">MIT</license> | ||
<!-- <icon>icon.png</icon> --> | ||
<projectUrl>https://github.com/DreadfulBot/net-ipfs-http-client</projectUrl> | ||
<description>IpfsClient with some improvements</description> | ||
<releaseNotes>Folder upload function fixed</releaseNotes> | ||
<copyright>DreadfulBot</copyright> | ||
<tags>ipfs files nft blockchain liberation</tags> | ||
<dependencies> | ||
<group targetFramework=".NETStandard2.0"> | ||
<dependency id="IpfsShipyard.Ipfs.Core" version="0.6.0" /> | ||
<dependency id="Microsoft.CSharp" version="4.7.0" /> | ||
<dependency id="Newtonsoft.Json" version="13.0.3" /> | ||
<dependency id="Multiformats.Base" version="2.0.2" /> | ||
<dependency id="PolySharp" version="1.14.1" /> | ||
</group> | ||
</dependencies> | ||
</metadata> | ||
<files> | ||
<file src="bin\Release\netstandard2.0\IpfsShipyard.Ipfs.Http.Client.dll" target="lib\netstandard2.0" /> | ||
<file src="..\README.md" target="docs\" /> | ||
</files> | ||
</package> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,16 @@ | ||
using Ipfs.CoreApi; | ||
using Newtonsoft.Json; | ||
using System; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Net.Http; | ||
using System.Net.Http.Headers; | ||
using System.Reflection; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Ipfs.CoreApi; | ||
using Newtonsoft.Json; | ||
|
||
namespace Ipfs.Http | ||
{ | ||
|
@@ -59,7 +60,8 @@ public IpfsClient() | |
var assembly = typeof(IpfsClient).GetTypeInfo().Assembly; | ||
var version = assembly.GetName().Version; | ||
|
||
UserAgent = string.Format("{0}/{1}.{2}.{3}", assembly.GetName().Name, version.Major, version.Minor, version.Revision); | ||
UserAgent = string.Format("{0}/{1}.{2}.{3}", assembly.GetName().Name, version.Major, version.Minor, | ||
version.Revision); | ||
TrustedPeers = new TrustedPeerCollection(this); | ||
|
||
Bootstrap = new BootstrapApi(this); | ||
|
@@ -229,7 +231,7 @@ HttpClient Api() | |
if (HttpMessageHandler is HttpClientHandler handler && handler.SupportsAutomaticDecompression) | ||
{ | ||
handler.AutomaticDecompression = DecompressionMethods.GZip | ||
| DecompressionMethods.Deflate; | ||
| DecompressionMethods.Deflate; | ||
} | ||
|
||
api = new HttpClient(HttpMessageHandler) | ||
|
@@ -241,6 +243,7 @@ HttpClient Api() | |
} | ||
} | ||
} | ||
|
||
return api; | ||
} | ||
|
||
|
@@ -271,7 +274,8 @@ HttpClient Api() | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<string> DoCommandAsync(string command, CancellationToken cancel, string arg = null, params string[] options) | ||
public async Task<string> DoCommandAsync(string command, CancellationToken cancel, string arg = null, | ||
params string[] options) | ||
{ | ||
var url = BuildCommand(command, arg, options); | ||
|
||
|
@@ -284,6 +288,74 @@ public async Task<string> DoCommandAsync(string command, CancellationToken cance | |
} | ||
} | ||
|
||
/// <summary> | ||
/// Executes /api/v0/add command | ||
/// See details here - https://docs.ipfs.tech/reference/kubo/rpc/#api-v0-add | ||
/// </summary> | ||
/// <param name="path">FileSystem path</param> | ||
/// <param name="cancel">Cancellation token</param> | ||
/// <param name="arg">Args</param> | ||
/// <param name="options">Options</param> | ||
/// <returns>Response</returns> | ||
public async Task<ICollection<IpfsFile>> DoAddCommand( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Instead of this, we should just fix the existing |
||
string path, | ||
CancellationToken cancel, | ||
string arg = null, | ||
params string[] options) | ||
{ | ||
var url = BuildCommand("add", arg, options); | ||
|
||
var dirInfo = new DirectoryInfo(Path.GetFullPath(path)); | ||
|
||
if (!dirInfo.Exists) | ||
{ | ||
throw new Exception("Directory does not exists"); | ||
} | ||
|
||
var upperLevelFolder = dirInfo.Parent?.FullName ?? Path.GetFullPath(path); | ||
|
||
string GetFileName(string cPath) | ||
{ | ||
// var relativePath = Path.GetRelativePath(upperLevelFolder, cPath); | ||
// var relativePath = Path.join(upperLevelFolder, cPath); | ||
|
||
var relativePath = cPath.Replace(upperLevelFolder, ""); | ||
return $"{Uri.EscapeDataString(relativePath)}"; | ||
} | ||
|
||
ByteArrayContent addFile(FileInfo cFile) | ||
{ | ||
var content = new ByteArrayContent(File.ReadAllBytes(cFile.FullName)); | ||
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") | ||
{ | ||
Name = "file", | ||
FileName = GetFileName(cFile.FullName) | ||
}; | ||
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); | ||
return content; | ||
} | ||
|
||
var content = new MultipartFormDataContent(); | ||
|
||
foreach (var file in dirInfo.EnumerateFiles()) | ||
{ | ||
content.Add(addFile(file)); | ||
} | ||
|
||
using var response = await Api().PostAsync(url, content, cancel); | ||
await ThrowOnErrorAsync(response); | ||
|
||
var strBody = await response.Content.ReadAsStringAsync(); | ||
|
||
var result = strBody | ||
.Split('\n') | ||
.Where(x => !string.IsNullOrWhiteSpace(x)) | ||
.Select(JsonConvert.DeserializeObject<IpfsFile>) | ||
.ToList(); | ||
|
||
return result; | ||
} | ||
|
||
internal Task DoCommandAsync(Uri url, byte[] bytes, CancellationToken cancel) | ||
{ | ||
return DoCommandAsync(url, new ByteArrayContent(bytes), cancel); | ||
|
@@ -299,13 +371,14 @@ internal Task DoCommandAsync(Uri url, string str, CancellationToken cancel) | |
return DoCommandAsync(url, new StringContent(str), cancel); | ||
} | ||
|
||
internal async Task DoCommandAsync(Uri url, HttpContent content, CancellationToken cancel) | ||
internal async Task<string> DoCommandAsync(Uri url, HttpContent content, CancellationToken cancel) | ||
{ | ||
using (var response = await Api().PostAsync(url, new MultipartFormDataContent { { content, "\"file\"" } }, cancel)) | ||
{ | ||
await ThrowOnErrorAsync(response); | ||
var body = await response.Content.ReadAsStringAsync(); | ||
} | ||
using var response = | ||
await Api().PostAsync(url, new MultipartFormDataContent {{content, "\"file\""}}, cancel); | ||
|
||
await ThrowOnErrorAsync(response); | ||
var body = await response.Content.ReadAsStringAsync(); | ||
return body; | ||
} | ||
|
||
|
||
|
@@ -339,7 +412,8 @@ internal async Task DoCommandAsync(Uri url, HttpContent content, CancellationTok | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<T> DoCommandAsync<T>(string command, CancellationToken cancel, string arg = null, params string[] options) | ||
public async Task<T> DoCommandAsync<T>(string command, CancellationToken cancel, string arg = null, | ||
params string[] options) | ||
{ | ||
var json = await DoCommandAsync(command, cancel, arg, options); | ||
return JsonConvert.DeserializeObject<T>(json); | ||
|
@@ -367,7 +441,8 @@ public async Task<T> DoCommandAsync<T>(string command, CancellationToken cancel, | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<Stream> PostDownloadAsync(string command, CancellationToken cancel, string arg = null, params string[] options) | ||
public async Task<Stream> PostDownloadAsync(string command, CancellationToken cancel, string arg = null, | ||
params string[] options) | ||
{ | ||
var url = BuildCommand(command, arg, options); | ||
|
||
|
@@ -402,7 +477,8 @@ public async Task<Stream> PostDownloadAsync(string command, CancellationToken ca | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<Stream> DownloadAsync(string command, CancellationToken cancel, string arg = null, params string[] options) | ||
public async Task<Stream> DownloadAsync(string command, CancellationToken cancel, string arg = null, | ||
params string[] options) | ||
{ | ||
var url = BuildCommand(command, arg, options); | ||
|
||
|
@@ -435,7 +511,8 @@ public async Task<Stream> DownloadAsync(string command, CancellationToken cancel | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<byte[]> DownloadBytesAsync(string command, CancellationToken cancel, string arg = null, params string[] options) | ||
public async Task<byte[]> DownloadBytesAsync(string command, CancellationToken cancel, string arg = null, | ||
params string[] options) | ||
{ | ||
var url = BuildCommand(command, arg, options); | ||
|
||
|
@@ -473,7 +550,8 @@ public async Task<byte[]> DownloadBytesAsync(string command, CancellationToken c | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<String> UploadAsync(string command, CancellationToken cancel, Stream data, string name, params string[] options) | ||
public async Task<String> UploadAsync(string command, CancellationToken cancel, Stream data, string name, | ||
params string[] options) | ||
{ | ||
var content = new MultipartFormDataContent(); | ||
var streamContent = new StreamContent(data); | ||
|
@@ -495,6 +573,7 @@ public async Task<String> UploadAsync(string command, CancellationToken cancel, | |
return json; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Perform an <see href="https://ipfs.io/docs/api/">IPFS API command</see> that | ||
/// requires uploading of a "file". | ||
|
@@ -523,7 +602,8 @@ public async Task<String> UploadAsync(string command, CancellationToken cancel, | |
/// <exception cref="HttpRequestException"> | ||
/// When the IPFS server indicates an error. | ||
/// </exception> | ||
public async Task<Stream> Upload2Async(string command, CancellationToken cancel, Stream data, string name, params string[] options) | ||
public async Task<Stream> Upload2Async(string command, CancellationToken cancel, Stream data, string name, | ||
params string[] options) | ||
{ | ||
var content = new MultipartFormDataContent(); | ||
var streamContent = new StreamContent(data); | ||
|
@@ -543,7 +623,8 @@ public async Task<Stream> Upload2Async(string command, CancellationToken cancel, | |
/// <summary> | ||
/// TODO | ||
/// </summary> | ||
public async Task<String> UploadAsync(string command, CancellationToken cancel, byte[] data, params string[] options) | ||
public async Task<String> UploadAsync(string command, CancellationToken cancel, byte[] data, | ||
params string[] options) | ||
{ | ||
var content = new MultipartFormDataContent(); | ||
var streamContent = new ByteArrayContent(data); | ||
|
@@ -593,17 +674,21 @@ async Task<bool> ThrowOnErrorAsync(HttpResponseMessage response) | |
try | ||
{ | ||
var res = JsonConvert.DeserializeObject<dynamic>(body); | ||
message = (string)res.Message; | ||
message = (string) res.Message; | ||
} | ||
catch | ||
{ | ||
} | ||
catch { } | ||
|
||
throw new HttpRequestException(message); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IAsyncEnumerable<PingResult> Ping(MultiHash peer, int count = 10, CancellationToken cancel = new CancellationToken()) => Generic.Ping(peer, count, cancel); | ||
public IAsyncEnumerable<PingResult> Ping(MultiHash peer, int count = 10, | ||
CancellationToken cancel = new CancellationToken()) => Generic.Ping(peer, count, cancel); | ||
|
||
/// <inheritdoc /> | ||
public IAsyncEnumerable<PingResult> Ping(MultiAddress address, int count = 10, CancellationToken cancel = new CancellationToken()) => Generic.Ping(address, count, cancel); | ||
public IAsyncEnumerable<PingResult> Ping(MultiAddress address, int count = 10, | ||
CancellationToken cancel = new CancellationToken()) => Generic.Ping(address, count, cancel); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System.Runtime.Serialization; | ||
|
||
namespace Ipfs.Http; | ||
|
||
/// <summary> | ||
/// IpfsFile | ||
/// </summary> | ||
[DataContract] | ||
public class IpfsFile | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this type was created for the |
||
{ | ||
/// <summary> | ||
/// Name | ||
/// </summary> | ||
[DataMember(Name = "Name")] | ||
public string Name { get; set; } | ||
|
||
/// <summary> | ||
/// Hash | ||
/// </summary> | ||
[DataMember(Name = "Hash")] | ||
public string Hash { get; set; } | ||
|
||
/// <summary> | ||
/// Size | ||
/// </summary> | ||
[DataMember(Name = "Size")] | ||
public string Size { get; set; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
include .env | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need to include a makefile. The underlying commands are already as simple as can be, and our CI handles publishing updates to nuget. |
||
nuget-push: | ||
nuget push bin/Release/$(PACKAGE_NAME).$(VERSION).nupkg -Source https://api.nuget.org/v3/index.json -ApiKey $(NUGET_API_KEY) | ||
nuget-pack: | ||
nuget pack $(PACKAGE_NAME).nuspec -Version $(VERSION) -Properties Configuration=Release -OutputDirectory bin/Release |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to add a nuspec here, and these values are different from our published package.