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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ CLAUDE.md

*tmp.json
*.log
*.out
11 changes: 10 additions & 1 deletion anilist.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type AnilistClient struct {
}

func NewAnilistClient(ctx context.Context, oauth *OAuth, username string) *AnilistClient {
httpClient := oauth2.NewClient(ctx, oauth.TokenSource())
httpClient := oauth2.NewClient(ctx, oauth.TokenSource(ctx))
httpClient.Timeout = 10 * time.Minute

v := verniy.New()
Expand Down Expand Up @@ -108,12 +108,17 @@ func (c *AnilistClient) GetUserMangaList(ctx context.Context) ([]verniy.MediaLis
}

func NewAnilistOAuth(ctx context.Context, config Config) (*OAuth, error) {
// Generate PKCE code verifier using oauth2 package
verifier := oauth2.GenerateVerifier()

oauthAnilist, err := NewOAuth(
config.Anilist,
config.OAuth.RedirectURI,
"anilist",
[]oauth2.AuthCodeOption{
oauth2.AccessTypeOffline,
oauth2.S256ChallengeOption(verifier), // S256 challenge for auth URL
oauth2.VerifierOption(verifier), // Verifier for token exchange
},
config.TokenFilePath,
)
Expand All @@ -123,6 +128,10 @@ func NewAnilistOAuth(ctx context.Context, config Config) (*OAuth, error) {

if oauthAnilist.NeedInit() {
getToken(ctx, oauthAnilist, config.OAuth.Port)
// Check if context was cancelled during OAuth flow
if ctx.Err() != nil {
return nil, ctx.Err()
}
} else {
log.Println("Token already set, no need to start server")
}
Expand Down
18 changes: 10 additions & 8 deletions myanimelist.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ import (
"context"
"errors"
"log"
"net/url"
"time"

"github.com/nstratos/go-myanimelist/mal"
"golang.org/x/oauth2"
)

const randNumb = 43

var errEmptyMalID = errors.New("mal id is empty")

var animeFields = mal.Fields{
Expand All @@ -37,7 +34,7 @@ type MyAnimeListClient struct {
}

func NewMyAnimeListClient(ctx context.Context, oauth *OAuth, username string) *MyAnimeListClient {
httpClient := oauth2.NewClient(ctx, oauth.TokenSource())
httpClient := oauth2.NewClient(ctx, oauth.TokenSource(ctx))
httpClient.Timeout = 10 * time.Minute

client := mal.NewClient(httpClient)
Expand Down Expand Up @@ -154,16 +151,17 @@ func (c *MyAnimeListClient) UpdateMangaByIDAndOptions(ctx context.Context, id in
}

func NewMyAnimeListOAuth(ctx context.Context, config Config) (*OAuth, error) {
code := url.QueryEscape(randHTTPParamString(randNumb))
// Generate PKCE code verifier using oauth2 package
verifier := oauth2.GenerateVerifier()

oauthMAL, err := NewOAuth(
config.MyAnimeList,
config.OAuth.RedirectURI,
"myanimelist",
[]oauth2.AuthCodeOption{
oauth2.SetAuthURLParam("code_challenge", code),
oauth2.SetAuthURLParam("code_verifier", code),
oauth2.SetAuthURLParam("code_challenge_method", "plain"),
oauth2.SetAuthURLParam("code_challenge", verifier), // Plain challenge (same as verifier)
oauth2.SetAuthURLParam("code_challenge_method", "plain"), // Explicit plain method
oauth2.VerifierOption(verifier), // Verifier for token exchange
},
config.TokenFilePath,
)
Expand All @@ -173,6 +171,10 @@ func NewMyAnimeListOAuth(ctx context.Context, config Config) (*OAuth, error) {

if oauthMAL.NeedInit() {
getToken(ctx, oauthMAL, config.OAuth.Port)
// Check if context was cancelled during OAuth flow
if ctx.Err() != nil {
return nil, ctx.Err()
}
} else {
log.Println("Token already set, no need to start server")
}
Expand Down
Loading