Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# DevBase Agent Guide

This document helps AI agents work effectively with the DevBase solution.

## Solution Overview

DevBase is a multi-project .NET solution providing utilities, API clients, and helpers. The solution targets **.NET 9.0**.

## Project Structure

```
DevBase/
├── DevBase/ # Core utilities (AList, IO, async tasks)
├── DevBase.Api/ # API clients (Deezer, Tidal, AppleMusic, etc.)
├── DevBase.Avalonia/ # Avalonia UI utilities (color analysis)
├── DevBase.Cryptography/ # Basic cryptography (Blowfish, MD5)
├── DevBase.Cryptography.BouncyCastle/ # BouncyCastle crypto wrappers
├── DevBase.Extensions/ # .NET type extensions
├── DevBase.Format/ # File format parsers (LRC, SRT, ENV)
├── DevBase.Logging/ # Lightweight logging
├── DevBase.Net/ # HTTP client library (main networking)
├── DevBase.Test/ # Unit tests (NUnit)
├── DevBaseLive/ # Console app for testing
└── docs/ # Documentation
```

## Key Dependencies Between Projects

```
DevBase.Api → DevBase.Net → DevBase → DevBase.Cryptography
DevBase.Format → DevBase
DevBase.Test → All projects
```

## Common Patterns

### 1. HTTP Requests (DevBase.Net)
```csharp
using DevBase.Net.Core;

Response response = await new Request("https://api.example.com")
.WithHeader("Authorization", "Bearer token")
.WithTimeout(TimeSpan.FromSeconds(30))
.SendAsync();

var data = await response.ParseJsonAsync<MyType>();
```

### 2. API Client Error Handling (DevBase.Api)
All API clients extend `ApiClient` and use the `Throw<T>()` method:
```csharp
if (response.StatusCode != HttpStatusCode.OK)
return Throw<object>(new MyException(ExceptionType.NotFound));
```

For tuple return types, use `ThrowTuple()`:
```csharp
return ThrowTuple(new MyException(ExceptionType.NotFound));
```

### 3. Generic Collections (DevBase)
Use `AList<T>` instead of `List<T>` for enhanced functionality:
```csharp
AList<string> items = new AList<string>();
items.Add("item");
string first = items.Get(0);
bool isEmpty = items.IsEmpty();
```

## Important Classes

| Project | Key Classes |
|---------|-------------|
| DevBase.Net | `Request`, `Response`, `ProxyInfo`, `RetryPolicy` |
| DevBase.Api | `ApiClient`, `Deezer`, `Tidal`, `AppleMusic`, `NetEase` |
| DevBase | `AList<T>`, `AFile`, `AFileObject` |
| DevBase.Format | `LrcParser`, `SrtParser`, `TimeStampedLyric` |

## Namespaces

- **DevBase.Net.Core** - Request/Response classes
- **DevBase.Net.Proxy** - Proxy support
- **DevBase.Api.Apis.[Service]** - API clients
- **DevBase.Generics** - Generic collections
- **DevBase.Format.Formats** - File parsers

## Testing

Run all tests:
```bash
dotnet test
```

Run specific test class:
```bash
dotnet test --filter "FullyQualifiedName~ClassName"
```

## Building NuGet Packages

Packages are generated on build with `GeneratePackageOnBuild=true`:
```bash
dotnet build -c Release
```

Packages output to: `bin/Release/*.nupkg`

## Tips for AI Agents

1. **Use `DevBase.Net.Core.Request`** for HTTP operations, not `HttpClient` directly
2. **Extend `ApiClient`** when creating new API clients
3. **Use `Throw<T>()`** for error handling in API clients
4. **Use `ThrowTuple()`** for methods returning `ValueTuple` types
5. **Check `StrictErrorHandling`** property for exception behavior
6. **Use `AList<T>`** from DevBase.Generics for collections
7. **External API tests** should handle unavailable services gracefully
8. **README.md files** are included in NuGet packages

## Error Handling Pattern

```csharp
// In API client methods
if (condition_failed)
return Throw<object>(new MyException(ExceptionType.Reason));

// For tuple returns
if (condition_failed)
return ThrowTuple(new MyException(ExceptionType.Reason));
```

When `StrictErrorHandling = true`, exceptions are thrown.
When `StrictErrorHandling = false`, default values are returned.
107 changes: 107 additions & 0 deletions DevBase.Api/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# DevBase.Api Agent Guide

## Overview
DevBase.Api provides ready-to-use API clients for music streaming services, AI platforms, and lyrics providers.

## Key Classes

| Class | Namespace | Purpose |
|-------|-----------|---------|
| `ApiClient` | `DevBase.Api.Apis` | Base class for all API clients |
| `Deezer` | `DevBase.Api.Apis.Deezer` | Deezer music API |
| `Tidal` | `DevBase.Api.Apis.Tidal` | Tidal music API |
| `AppleMusic` | `DevBase.Api.Apis.AppleMusic` | Apple Music API |
| `NetEase` | `DevBase.Api.Apis.NetEase` | NetEase music API |
| `BeautifulLyrics` | `DevBase.Api.Apis.BeautifulLyrics` | Lyrics provider |

## Error Handling Pattern

All API clients extend `ApiClient` which provides error handling:

```csharp
public class MyApiClient : ApiClient
{
public async Task<MyResult> GetData()
{
if (errorCondition)
return Throw<object>(new MyException(ExceptionType.Reason));

// Normal return
return result;
}

// For tuple return types
public async Task<(string Data, bool Flag)> GetTuple()
{
if (errorCondition)
return ThrowTuple(new MyException(ExceptionType.Reason));

return (data, true);
}
}
```

### Error Handling Modes
- `StrictErrorHandling = true` → Exceptions are thrown
- `StrictErrorHandling = false` → Default values returned (null, empty, false)

## Quick Reference

### Deezer
```csharp
var deezer = new Deezer(arlToken: "optional");
var results = await deezer.Search("artist name");
var track = await deezer.GetSong("trackId");
```

### NetEase
```csharp
var netease = new NetEase();
var results = await netease.Search("keyword");
var lyrics = await netease.Lyrics("trackId");
```

### BeautifulLyrics
```csharp
var lyrics = new BeautifulLyrics();
var (rawLyrics, isRichSync) = await lyrics.GetRawLyrics("isrc");
var parsedLyrics = await lyrics.GetLyrics("isrc");
```

### AppleMusic
```csharp
var apple = await AppleMusic.WithAccessToken();
var results = await apple.Search("query");
```

## File Structure
```
DevBase.Api/
├── Apis/
│ ├── ApiClient.cs # Base class with Throw methods
│ ├── Deezer/
│ │ ├── Deezer.cs
│ │ └── Structure/ # JSON response types
│ ├── Tidal/
│ ├── AppleMusic/
│ ├── NetEase/
│ ├── BeautifulLyrics/
│ └── ...
├── Enums/ # Exception type enums
├── Exceptions/ # Custom exceptions
└── Serializer/ # JSON deserializer
```

## Important Notes

1. **Always extend `ApiClient`** for new API clients
2. **Use `Throw<object>()`** for reference type returns
3. **Use `ThrowTuple()`** for `ValueTuple` returns
4. **JSON types are in `Structure/Json/` folders**
5. **Use `JsonDeserializer<T>`** for JSON parsing
6. **External APIs may be unavailable** - handle gracefully in tests

## Dependencies
- **DevBase.Net** for HTTP requests
- **DevBase.Format** for lyrics parsing
- **Newtonsoft.Json** for JSON serialization
12 changes: 12 additions & 0 deletions DevBase.Api/Apis/ApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ protected dynamic Throw<T>(
return ToType<T>();
}

protected (string, bool) ThrowTuple(
System.Exception exception,
[CallerMemberName] string callerMember = "",
[CallerFilePath] string callerFilePath = "",
[CallerLineNumber] int callerLineNumber = 0)
{
if (StrictErrorHandling)
throw exception;

return (string.Empty, false);
}

private dynamic ToType<T>()
{
T type = (T)Activator.CreateInstance(typeof(T));
Expand Down
Loading
Loading