168 lines
4.8 KiB
Markdown
168 lines
4.8 KiB
Markdown
# AllAnime Client Decomposition Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Decompose the monolithic `api/playback/allanime_client.go` into focused, maintainable units.
|
|
|
|
**Architecture:**
|
|
1. Move uTLS networking logic to `pkg/net/utls`.
|
|
2. Move crypto and key discovery to `api/playback/allanime_crypto.go`.
|
|
3. Move data extraction and stream detection to `api/playback/allanime_extractor.go`.
|
|
4. Keep core API and GraphQL logic in `api/playback/allanime_client.go`.
|
|
|
|
**Tech Stack:** Go (uTLS, SHA256, AES-CTR)
|
|
|
|
---
|
|
|
|
### Task 1: Move uTLS RoundTripper to pkg/net/utls
|
|
|
|
**Files:**
|
|
- Create: `pkg/net/utls/utls.go`
|
|
- Modify: `api/playback/allanime_client.go`
|
|
|
|
- [ ] **Step 1: Create pkg/net/utls/utls.go**
|
|
|
|
```go
|
|
package utls
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
utls "github.com/refraction-networking/utls"
|
|
"golang.org/x/net/http2"
|
|
)
|
|
|
|
type UtlsRoundTripper struct{}
|
|
|
|
func (rt *UtlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
port := req.URL.Port()
|
|
if port == "" {
|
|
if req.URL.Scheme == "https" {
|
|
port = "443"
|
|
} else {
|
|
port = "80"
|
|
}
|
|
}
|
|
|
|
addr := net.JoinHostPort(req.URL.Hostname(), port)
|
|
conn, err := net.DialTimeout("tcp", addr, 10*time.Second)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
config := &utls.Config{ServerName: req.URL.Hostname()}
|
|
uConn := utls.UClient(conn, config, utls.HelloFirefox_Auto)
|
|
|
|
if err := uConn.Handshake(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var httpRT http.RoundTripper
|
|
switch uConn.ConnectionState().NegotiatedProtocol {
|
|
case http2.NextProtoTLS:
|
|
t2 := &http2.Transport{
|
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *utls.Config) (net.Conn, error) {
|
|
return uConn, nil
|
|
},
|
|
}
|
|
httpRT = t2
|
|
default:
|
|
t1 := &http.Transport{
|
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return uConn, nil
|
|
},
|
|
}
|
|
httpRT = t1
|
|
}
|
|
|
|
return httpRT.RoundTrip(req)
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 2: Update allanime_client.go to use the new package**
|
|
|
|
Remove `utlsRoundTripper` from `api/playback/allanime_client.go` and update `newAllAnimeClient` to use `&utls.UtlsRoundTripper{}`.
|
|
|
|
- [ ] **Step 3: Verify build and commit**
|
|
|
|
Run: `go build ./api/playback/...`
|
|
Expected: PASS
|
|
|
|
```bash
|
|
git add pkg/net/utls/utls.go api/playback/allanime_client.go
|
|
git commit -m "refactor: move utls roundtripper to pkg/net/utls"
|
|
```
|
|
|
|
### Task 2: Extract Crypto and Key Discovery
|
|
|
|
**Files:**
|
|
- Create: `api/playback/allanime_crypto.go`
|
|
- Modify: `api/playback/allanime_client.go`
|
|
|
|
- [ ] **Step 1: Move crypto logic to allanime_crypto.go**
|
|
|
|
Extract constants (`allAnimeAESKey`, `aniCliRawSourceURL`, etc.) and functions (`decryptTobeparsed`, `tryDecryptCTR`, `getAESKey`, `fetchKeyFromForks`, `extractKey`, `getTestPayload`, `validateKeys`, `getAllKeys`) to `api/playback/allanime_crypto.go`.
|
|
|
|
- [ ] **Step 2: Update allanime_client.go**
|
|
|
|
Remove the extracted code from `api/playback/allanime_client.go`.
|
|
|
|
- [ ] **Step 3: Verify build and commit**
|
|
|
|
Run: `go build ./api/playback/...`
|
|
Expected: PASS
|
|
|
|
```bash
|
|
git add api/playback/allanime_crypto.go api/playback/allanime_client.go
|
|
git commit -m "refactor: extract allanime crypto and key discovery"
|
|
```
|
|
|
|
### Task 3: Extract Data Extraction and Stream Detection
|
|
|
|
**Files:**
|
|
- Create: `api/playback/allanime_extractor.go`
|
|
- Modify: `api/playback/allanime_client.go`
|
|
|
|
- [ ] **Step 1: Move extraction logic to allanime_extractor.go**
|
|
|
|
Extract functions (`extractSourceURLsFromData`, `buildStreamSource`, `sourceReference` struct, `buildSourceReferences`, `extractEpisodeData`, `decodeSourceURL`, `detectStreamType`, `detectEmbedType`, `getMapKeys`) to `api/playback/allanime_extractor.go`.
|
|
|
|
- [ ] **Step 2: Update allanime_client.go**
|
|
|
|
Remove the extracted code from `api/playback/allanime_client.go`. Ensure `allAnimeClient` methods still call these (now package-level) functions.
|
|
|
|
- [ ] **Step 3: Verify build and commit**
|
|
|
|
Run: `go build ./api/playback/...`
|
|
Expected: PASS
|
|
|
|
```bash
|
|
git add api/playback/allanime_extractor.go api/playback/allanime_client.go
|
|
git commit -m "refactor: extract allanime data extraction logic"
|
|
```
|
|
|
|
### Task 4: Final Cleanup and Verification
|
|
|
|
**Files:**
|
|
- Modify: `api/playback/allanime_client.go`
|
|
|
|
- [ ] **Step 1: Final review of allanime_client.go**
|
|
|
|
Ensure only `allAnimeClient` struct, `newAllAnimeClient`, `graphqlRequest`, `graphqlRequestWithHash`, `Search`, `GetEpisodes`, `GetAvailableEpisodes`, and `GetEpisodeMetadata` remain.
|
|
|
|
- [ ] **Step 2: Run all tests**
|
|
|
|
Run: `go test -v ./api/playback/...`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 3: Commit final cleanup**
|
|
|
|
```bash
|
|
git add api/playback/allanime_client.go
|
|
git commit -m "refactor: final cleanup of allanime_client.go"
|
|
```
|