Skip to content

Commit 0065352

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 22ad264 + 032d417 commit 0065352

File tree

8 files changed

+385
-32
lines changed

8 files changed

+385
-32
lines changed

.github/workflows/dotnet.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,14 @@ jobs:
2626
run: dotnet build --no-restore
2727
- name: Test
2828
env:
29-
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
30-
run: dotnet test --no-build --verbosity normal
29+
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN || '' }}
30+
run: |
31+
if [ "${{ github.event_name }}" == "pull_request" ]; then
32+
if [ -n "${{ secrets.MODRINTH_TOKEN }}" ]; then
33+
dotnet test --no-build --verbosity normal
34+
else
35+
echo "MODRINTH_TOKEN is not set, skipping tests."
36+
fi
37+
else
38+
dotnet test --no-build --verbosity normal
39+
fi

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![GitHub](https://img.shields.io/github/license/Zechiax/Modrinth.Net?style=for-the-badge)](https://github.com/Zechiax/Modrinth.Net)
44
[![Nuget](https://img.shields.io/nuget/v/Modrinth.Net?style=for-the-badge)](https://www.nuget.org/packages/Modrinth.Net)
55
[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/Modrinth.Net?label=NuGet%20Pre-release&style=for-the-badge)](https://www.nuget.org/packages/Modrinth.Net)
6-
[![Modrinth API](https://img.shields.io/badge/Modrinth%20API-v2.7.0-449C59?style=for-the-badge)](https://docs.modrinth.com/api-spec/)
6+
[![Modrinth API](https://img.shields.io/badge/Modrinth%20API-v2.7.0-449C59?style=for-the-badge)](https://docs.modrinth.com/api/)
77

88
C# Wrapper for the [Modrinth API](https://docs.modrinth.com/)
99

docs/index.md

Lines changed: 298 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,299 @@
1-
# Modrinth.Net Documentation
1+
# Modrinth.Net
22

3-
- Placeholder text :)
3+
[![GitHub](https://img.shields.io/github/license/Zechiax/Modrinth.Net?style=for-the-badge)](https://github.com/Zechiax/Modrinth.Net)
4+
[![Nuget](https://img.shields.io/nuget/v/Modrinth.Net?style=for-the-badge)](https://www.nuget.org/packages/Modrinth.Net)
5+
[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/Modrinth.Net?label=NuGet%20Pre-release&style=for-the-badge)](https://www.nuget.org/packages/Modrinth.Net)
6+
[![Modrinth API](https://img.shields.io/badge/Modrinth%20API-v2.7.0-449C59?style=for-the-badge)](https://docs.modrinth.com/api-spec/)
7+
8+
C# Wrapper for the [Modrinth API](https://docs.modrinth.com/)
9+
10+
- For list of supported endpoints,
11+
see [List of endpoints and their support in this library](#list-of-endpoints-and-their-support-in-this-library)
12+
- The plan is to eventually cover all endpoints
13+
14+
## Main attributes
15+
16+
- Automatic rate limiting
17+
- Retry count is configurable
18+
- No dependencies
19+
- Fully documented
20+
- Support for .NET 8.0 and newer
21+
22+
## Usage
23+
24+
- Install the [NuGet package](https://www.nuget.org/packages/Modrinth.Net)
25+
26+
```csharp
27+
using Modrinth;
28+
29+
var options = new ModrinthClientConfig
30+
{
31+
// Optional, if you want to access authenticated API endpoints
32+
ModrinthToken = "Your_Authentication_Token",
33+
// For Modrinth API, you must specify a user-agent
34+
// There is a default library user-agent, but it is recommended to specify your own
35+
UserAgent = "MyAwesomeProject"
36+
};
37+
38+
var client = new ModrinthClient(options);
39+
40+
var project = await client.Project.GetAsync("sodium");
41+
42+
Console.WriteLine(project.Description);
43+
```
44+
45+
But you don't have to provide options at all, you can just create a client with the default options:
46+
47+
```csharp
48+
var client = new ModrinthClient();
49+
```
50+
51+
### User-Agent
52+
53+
- You can also use the UserAgent class to help you create a valid user-agent
54+
- User-Agent currently cannot be changed after the client has been created
55+
- More info about the User-Agent can be found [here](https://docs.modrinth.com/api-spec/#section/User-Agents)
56+
57+
```csharp
58+
using Modrinth;
59+
60+
// Note: All properties are optional, and will be ignored if they are null or empty
61+
var userAgent = new UserAgent
62+
{
63+
ProjectName = "ProjectName",
64+
ProjectVersion = "1.0.0",
65+
GitHubUsername = "Username",
66+
Contact = "contact@contact.com"
67+
};
68+
69+
var options = new ModrinthClientOptions
70+
{
71+
UserAgent = userAgent.ToString()
72+
};
73+
74+
var client = new ModrinthClient(options);
75+
```
76+
77+
### Search
78+
79+
- You can search for projects using the `SearchAsync` method, in the `Project` endpoint
80+
81+
```csharp
82+
using Modrinth;
83+
84+
var client = new ModrinthClient(userAgent: "My_Awesome_Project");
85+
86+
var search = await client.Project.SearchAsync("sodium");
87+
88+
foreach (var project in search.Hits)
89+
{
90+
Console.WriteLine(project.Title);
91+
}
92+
```
93+
94+
#### Search with facets/filtering
95+
96+
- You can filter the search results by using facets, which are a way to filter the results by certain criteria
97+
- You can read more about facets [here](https://docs.modrinth.com/docs/tutorials/api_search/#facets)
98+
- You can create a `FacetCollection` and add facets to it, and then pass it to the `SearchAsync` method
99+
100+
Example:
101+
102+
```csharp
103+
// For search with facets, you first need to create a FacetCollection
104+
var facets = new FacetCollection();
105+
106+
// Then you can add facets to it
107+
// You add a facet by calling the Add method on the FacetCollection
108+
// In one call, you can add multiple facets, they will be combined in an OR statement
109+
// If you call Add again, the new facets will be combined in an AND statement with the previous ones
110+
111+
// Example:
112+
facets.Add(Facet.Category("adventure"), Facet.Category("magic"));
113+
facets.Add(Facet.Version("1.19.4"));
114+
115+
// This will create a query that looks like this:
116+
// (category:adventure OR category:magic) AND version:1.19.4
117+
// Basically it will search for projects that have the category "adventure" or "magic" on Minecraft version 1.19.4
118+
119+
// Then you can pass the FacetCollection to the SearchAsync method
120+
var search = await _client.Project.SearchAsync("", facets: facets);
121+
```
122+
123+
As `FacetCollection` implements `ICollection<T>`, you can use collection initializers to add facets to it, like this:
124+
125+
```csharp
126+
var facets = new FacetCollection
127+
{
128+
{ Facet.Category("adventure"), Facet.Category("magic") },
129+
{ Facet.Version("1.19.4") }
130+
};
131+
```
132+
133+
Which will create the same query as the previous example.
134+
135+
### Unsuccesful API calls
136+
137+
- If the API call was unsuccessful, the client will throw an `ModrinthApiException` exception
138+
- This will be thrown if the API call return non-200 status code
139+
140+
```csharp
141+
using Modrinth;
142+
using Modrinth.Exceptions;
143+
using System.Net;
144+
145+
var client = new ModrinthClient(userAgent: "My_Awesome_Project");
146+
147+
try
148+
{
149+
var project = await _client.Project.GetAsync("non-existent-project");
150+
151+
Console.WriteLine(project.Title);
152+
}
153+
// You can catch the exception and only handle the 404 status code
154+
catch (ModrinthApiException e) when (e.Response.StatusCode == HttpStatusCode.NotFound)
155+
{
156+
Console.WriteLine("Project not found");
157+
}
158+
// Or you can catch the exception and handle all non-200 status codes
159+
catch (ModrinthApiException e)
160+
{
161+
Console.WriteLine($"API call failed with status code {e.Response.StatusCode}");
162+
}
163+
```
164+
165+
## List of endpoints and their support in this library
166+
167+
| Icon | Meaning | Comment |
168+
|------|-----------------|------------------------------------------------------------------------------|
169+
|| Implemented | |
170+
|| Not implemented | |
171+
| ⚠️ | Untested | The endpoint has been implemented, but no tests have been written for it yet |
172+
173+
### Project endpoints
174+
175+
| Name | Method | Implemented |
176+
|-------------------------------------|--------|-------------|
177+
| Search projects | GET ||
178+
| Get a project | GET ||
179+
| Modify a project | PATCH ||
180+
| Delete a project | DELETE | ⚠️ |
181+
| Get multiple projects | GET ||
182+
| Bulk-edit multiple projects | PATCH ||
183+
| Get a list of random projects | GET ||
184+
| Create a project | POST ||
185+
| Change project's icon | PATCH ||
186+
| Delete project's icon | DELETE ||
187+
| Check project slug/ID validity | GET ||
188+
| Add a gallery image | POST ||
189+
| Modify a gallery image | PATCH ||
190+
| Delete a gallery image | DELETE ||
191+
| Get all of a project's dependencies | GET ||
192+
| Follow a project | POST ||
193+
| Unfollow a project | DELETE ||
194+
| Schedule a project | POST ||
195+
196+
### Version endpoints
197+
198+
| Name | Method | Implemented |
199+
|--------------------------------------------|--------|-------------|
200+
| List project's versions | GET ||
201+
| Get a version | GET ||
202+
| Modify a version | PATCH ||
203+
| Delete a version | DELETE | ⚠️ |
204+
| Get a version given a version number or ID | GET ||
205+
| Create a version | POST ||
206+
| Schedule a version | POST | ⚠️ |
207+
| Get multiple versions | GET ||
208+
| Add files to version | POST ||
209+
210+
### Version file endpoints
211+
212+
| Name | Method | Implemented |
213+
|----------------------------------------------------------------------------------|--------|-------------|
214+
| Get version from hash | GET | ✅️ |
215+
| Delete a file from its hash | DELETE | ⚠️ |
216+
| Latest version of a project from a hash, loader(s), and game version(s) | POST | ✅️ |
217+
| Get versions from hashes | POST | ✅️ |
218+
| Latest versions of multiple projects from hashes, loader(s), and game version(s) | POST | ✅️ |
219+
220+
### User endpoints
221+
222+
| Name | Method | Implemented |
223+
|--------------------------------------------|--------|-------------|
224+
| Get a user | GET ||
225+
| Modify a user | PATCH ||
226+
| Get user from authorization header | GET ||
227+
| Get multiple users | GET ||
228+
| Change user's avatar | PATCH ||
229+
| Get user's projects | GET ||
230+
| Get user's followed projects | GET ||
231+
| Get user's payout history | GET ||
232+
| Withdraw payout balance to PayPal or Venmo | POST ||
233+
234+
### Threads endpoints
235+
236+
🔐 All of the endpoints in this section require authentication.
237+
238+
| Name | Method | Implemented |
239+
|------------------------------------|--------|-------------|
240+
| Report a project, user, or version | POST ||
241+
| Get your open reports | GET ||
242+
| Get report from ID | GET ||
243+
| Modify a report | PATCH ||
244+
| Get multiple reports | GET ||
245+
| Get a thread | GET ||
246+
| Send a text message to a thread | POST ||
247+
| Get multiple threads | GET ||
248+
| Delete a thread | DELETE ||
249+
250+
### Notifications endpoints
251+
252+
🔐 All of the endpoints in this section require authentication.
253+
254+
| Name | Method | Implemented |
255+
|-------------------------------------|--------|-------------|
256+
| Get user's notifications | GET ||
257+
| Get notification from ID | GET ||
258+
| Mark notification as read | PATCH ||
259+
| Delete a notification | DELETE ||
260+
| Get multiple notifications | GET ||
261+
| Mark multiple notifications as read | PATCH ||
262+
| Delete multiple notifications | DELETE ||
263+
264+
### Team endpoints
265+
266+
| Name | Method | Implemented |
267+
|-------------------------------------------|--------|-------------|
268+
| Get a project's team members | GET ||
269+
| Get a team's members | GET ||
270+
| Add a user to a team | POST | ⚠️ |
271+
| Get the members of multiple teams | GET ||
272+
| Join a team | POST | ⚠️ |
273+
| Modify a team member's information | PATCH | ⚠️ |
274+
| Remove a member from a team | DELETE | ⚠️ |
275+
| Transfer team's ownership to another user | PATCH | ⚠️ |
276+
277+
### Tag endpoints
278+
279+
| Name | Method | Implemented | Comment |
280+
|-------------------------------------|--------|-------------|---------|
281+
| Get a list of categories | GET || |
282+
| Get a list of loaders | GET || |
283+
| Get a list of game versions | GET || |
284+
| Get the text and title of a license | GET || |
285+
| Get a list of donation platforms | GET || |
286+
| Get a list of report types | GET || |
287+
| Get a list of project types | GET || |
288+
| Get a list of side types | GET || |
289+
290+
### Miscellaneous endpoints
291+
292+
| Name | Method | Implemented |
293+
|-------------------------------------------------|--------|-------------|
294+
| Forge Updates JSON file | GET ||
295+
| Various statistics about this Modrinth instance | GET ||
296+
297+
## Disclaimer
298+
299+
This is not an official Modrinth project. This is a third-party project that is not affiliated with Modrinth in any way.

src/Modrinth.Net/Endpoints/Project/IProjectEndpoint.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public interface IProjectEndpoint
2323
Task<SearchResponse> SearchAsync(
2424
string query,
2525
Index index = Index.Downloads,
26-
ulong offset = 0,
27-
ulong limit = 10,
26+
int offset = 0,
27+
int limit = 10,
2828
FacetCollection? facets = null, CancellationToken cancellationToken = default);
2929

3030
/// <summary>
@@ -43,7 +43,7 @@ Task<SearchResponse> SearchAsync(
4343
/// <param name="cancellationToken"> The cancellation token to cancel operation </param>
4444
/// <returns></returns>
4545
/// <exception cref="ModrinthApiException"> Thrown when the API returns an error or the request fails </exception>
46-
Task<Models.Project[]> GetRandomAsync(ulong count = 10, CancellationToken cancellationToken = default);
46+
Task<Models.Project[]> GetRandomAsync(int count = 10, CancellationToken cancellationToken = default);
4747

4848
/// <summary>
4949
/// Deletes project by slug or ID
@@ -132,7 +132,7 @@ Task<SearchResponse> SearchAsync(
132132
/// <returns></returns>
133133
/// <exception cref="ModrinthApiException"> Thrown when the API returns an error or the request fails </exception>
134134
Task AddGalleryImageAsync(string slugOrId, string imagePath, bool featured, string? title = null,
135-
string? description = null, ulong? ordering = null, CancellationToken cancellationToken = default);
135+
string? description = null, int? ordering = null, CancellationToken cancellationToken = default);
136136

137137
/// <summary>
138138
/// Modifies an existing gallery image
@@ -147,7 +147,7 @@ Task AddGalleryImageAsync(string slugOrId, string imagePath, bool featured, stri
147147
/// <returns></returns>
148148
/// <exception cref="ModrinthApiException"> Thrown when the API returns an error or the request fails </exception>
149149
Task ModifyGalleryImageAsync(string slugOrId, string url, bool? featured = null, string? title = null,
150-
string? description = null, ulong? ordering = null, CancellationToken cancellationToken = default);
150+
string? description = null, int? ordering = null, CancellationToken cancellationToken = default);
151151

152152
/// <summary>
153153
/// Deletes an existing gallery image

0 commit comments

Comments
 (0)