package torrent import ( "context" "fmt" "os" "sync" "time" ) type StubClient struct { logPath string savePath string mu sync.Mutex } func NewStubClient(logPath, savePath string) *StubClient { return &StubClient{ logPath: logPath, savePath: savePath, } } func (c *StubClient) log(format string, args ...any) { c.mu.Lock() defer c.mu.Unlock() f, err := os.OpenFile(c.logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return } defer f.Close() timestamp := time.Now().Format(time.RFC3339) msg := fmt.Sprintf(format, args...) fmt.Fprintf(f, "[%s] %s\n", timestamp, msg) } func (c *StubClient) Connect(ctx context.Context) error { c.log("CONNECT") return nil } func (c *StubClient) Disconnect(ctx context.Context) error { c.log("DISCONNECT") return nil } func (c *StubClient) ListTorrents(ctx context.Context) ([]TorrentInfo, error) { c.log("LIST_TORRENTS") return []TorrentInfo{}, nil } func (c *StubClient) GetTorrent(ctx context.Context, hash string) (*TorrentInfo, error) { c.log("GET_TORRENT hash=%s", hash) return nil, ErrTorrentNotFound } func (c *StubClient) AddTorrentURL(ctx context.Context, url string, savePath *string) error { path := c.savePath if savePath != nil { path = *savePath } c.log("ADD_TORRENT_URL url=%s save_path=%s", url, path) return nil } func (c *StubClient) AddTorrentFile(ctx context.Context, data []byte, savePath *string) error { path := c.savePath if savePath != nil { path = *savePath } c.log("ADD_TORRENT_FILE size=%d save_path=%s", len(data), path) return nil } func (c *StubClient) RemoveTorrent(ctx context.Context, hash string, deleteFiles bool) error { c.log("REMOVE_TORRENT hash=%s delete_files=%t", hash, deleteFiles) return nil } func (c *StubClient) PauseTorrent(ctx context.Context, hash string) error { c.log("PAUSE_TORRENT hash=%s", hash) return nil } func (c *StubClient) ResumeTorrent(ctx context.Context, hash string) error { c.log("RESUME_TORRENT hash=%s", hash) return nil }