Files
mal/docs/superpowers/plans/2026-05-06-allanime-decomposition.md

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"
```