diff options
Diffstat (limited to 'internal/platforms/linkedin')
6 files changed, 42 insertions, 5 deletions
diff --git a/internal/platforms/linkedin/linkedin.go b/internal/platforms/linkedin/linkedin.go index 11291fb..16688d5 100644 --- a/internal/platforms/linkedin/linkedin.go +++ b/internal/platforms/linkedin/linkedin.go @@ -27,9 +27,10 @@ func addCommonHeaders(req *http.Request, accessToken, liVersion string) { req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-RestLi-Protocol-Version", "2.0.0") - if liVersion != "" { - req.Header.Set("LinkedIn-Version", liVersion) + if liVersion == "" { + liVersion = "202601" // Default to latest stable version } + req.Header.Set("LinkedIn-Version", liVersion) } func Post(ctx context.Context, args config.Args, sizeLimit int, en entry.Entry) error { @@ -147,7 +148,7 @@ func postMessageToLinkedInAPI(ctx context.Context, personID, accessToken, conten } else if resp.StatusCode == http.StatusUpgradeRequired { // 426 often indicates a non-active LinkedIn-Version header. // Provide a clear hint to configure a valid version. - err = fmt.Errorf("%w; LinkedIn API version likely inactive. Set an active 'LinkedInVersion' in config (e.g. 202502) or remove to use default. Response: %s", err, string(body)) + err = fmt.Errorf("%w; LinkedIn API version likely inactive. Set an active 'LinkedInVersion' in config (e.g. 202601) or remove to use default. Response: %s", err, string(body)) } } return err @@ -191,6 +192,24 @@ func initializeImageUpload(ctx context.Context, personURN, accessToken string, l } defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", "", fmt.Errorf("error reading response: %w", err) + } + + if resp.StatusCode != http.StatusOK { + err := fmt.Errorf("image upload initialization failed. Status: %s\n%s\n", + resp.Status, string(body)) + if resp.StatusCode == http.StatusUnauthorized { + err = errors.Join(err, errUnauthorized) + } else if resp.StatusCode == http.StatusUpgradeRequired { + // 426 often indicates a non-active LinkedIn-Version header. + // Provide a clear hint to configure a valid version. + err = fmt.Errorf("%w; LinkedIn API version likely inactive. Set an active 'LinkedInVersion' in config (e.g. 202601) or remove to use default. Response: %s", err, string(body)) + } + return "", "", err + } + type InitializeUploadResponse struct { Value struct { UploadURL string `json:"uploadUrl"` @@ -198,7 +217,7 @@ func initializeImageUpload(ctx context.Context, personURN, accessToken string, l } `json:"value"` } var response InitializeUploadResponse - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + if err := json.Unmarshal(body, &response); err != nil { return "", "", fmt.Errorf("error decoding response: %w", err) } diff --git a/internal/platforms/linkedin/oauth2/oauth2.go b/internal/platforms/linkedin/oauth2/oauth2.go index 8fe25ab..45cb9b7 100644 --- a/internal/platforms/linkedin/oauth2/oauth2.go +++ b/internal/platforms/linkedin/oauth2/oauth2.go @@ -93,7 +93,13 @@ func oauthCallbackHandler(w http.ResponseWriter, r *http.Request) { func LinkedInCreds(ctx context.Context, args config.Args) (string, string, error) { conf := args.Config if conf.LinkedInAccessToken != "" && conf.LinkedInPersonID != "" { - return conf.LinkedInPersonID, conf.LinkedInAccessToken, nil + // Validate cached token before using it + token := &oauth2.Token{AccessToken: conf.LinkedInAccessToken} + if _, err := getOauthPersonID(token); err == nil { + return conf.LinkedInPersonID, conf.LinkedInAccessToken, nil + } + // Cached token is invalid, clear it to trigger re-auth + conf.LinkedInAccessToken = "" } oauthConfig = &oauth2.Config{ diff --git a/internal/platforms/linkedin/preview.go b/internal/platforms/linkedin/preview.go index a583c7a..125a4bf 100644 --- a/internal/platforms/linkedin/preview.go +++ b/internal/platforms/linkedin/preview.go @@ -73,6 +73,12 @@ func (p preview) Thumbnail() (string, bool) { } func (p preview) DownloadImage(destPath string) (string, error) { + // Skip data URIs - they can't be downloaded and don't provide meaningful images + if u, err := url.Parse(p.thumbnailURL); err == nil && u.Scheme == "data" { + colour.Infoln("Skipping data URI image, using article metadata instead") + return "", nil + } + if err := oi.EnsureDir(destPath); err != nil { return "", err } diff --git a/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/5ffd3a9d58497377 b/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/5ffd3a9d58497377 new file mode 100644 index 0000000..2eecaf6 --- /dev/null +++ b/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/5ffd3a9d58497377 @@ -0,0 +1,2 @@ +go test fuzz v1 +string("\n\n\n") diff --git a/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/771e938e4458e983 b/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/771e938e4458e983 new file mode 100644 index 0000000..ee3f339 --- /dev/null +++ b/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/771e938e4458e983 @@ -0,0 +1,2 @@ +go test fuzz v1 +string("0") diff --git a/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/b0118fa98fb2891d b/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/b0118fa98fb2891d new file mode 100644 index 0000000..190e0f4 --- /dev/null +++ b/internal/platforms/linkedin/testdata/fuzz/FuzzLinkedInURLExtract/b0118fa98fb2891d @@ -0,0 +1,2 @@ +go test fuzz v1 +string("0 0") |
