summaryrefslogtreecommitdiff
path: root/internal/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'internal/platforms')
-rw-r--r--internal/platforms/linkedin/linkedin.go61
-rw-r--r--internal/platforms/linkedin/oauth2.go145
2 files changed, 60 insertions, 146 deletions
diff --git a/internal/platforms/linkedin/linkedin.go b/internal/platforms/linkedin/linkedin.go
index 0f6ef2c..6205234 100644
--- a/internal/platforms/linkedin/linkedin.go
+++ b/internal/platforms/linkedin/linkedin.go
@@ -1,12 +1,71 @@
package linkedin
import (
+ "bytes"
"context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "codeberg.org/snonux/gos/gosdir/db/platforms/linkedin/oauth2"
"codeberg.org/snonux/gos/internal/config"
"codeberg.org/snonux/gos/internal/entry"
)
+// TODO: Also implemebt a Text Platform output, which then laster can be
+// processed by Gemtexter as a page
func Post(ctx context.Context, args config.Args, ent entry.Entry) error {
- return oauth(args)
+ secrets, err := oauth2.AccessToken(args)
+ if err != err {
+ return err
+ }
+ // TODO: Don't log this anymore
+ log.Println("DEBUG", "Got access token", secrets)
+ return nil
+}
+
+func postMessage(secrets config.Secrets, message string) error {
+ const url = "https://api.linkedin.com/v2/posts"
+
+ post := map[string]interface{}{
+ "author": fmt.Sprintf("urn:li:person:%s", secrets.LinkedInPesonID),
+ "commentary": message,
+ "visibility": "PUBLIC",
+ "distribution": map[string]interface{}{
+ "feedDistribution": "MAIN_FEED",
+ "targetEntities": []string{},
+ "thirdPartyDistributionChannels": []string{},
+ },
+ "lifecycleState": "PUBLISHED",
+ "isReshareDisabledByAuthor": false,
+ }
+
+ payload, err := json.Marshal(post)
+ if err != nil {
+ return fmt.Errorf("Error encoding JSON:%w", err)
+ }
+
+ req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload))
+ if err != nil {
+ return fmt.Errorf("Error creating request: %w", err)
+ }
+
+ req.Header.Add("Authorization", "Bearer "+secrets.LinkedInAccessToken)
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Add("X-RestLi-Protocol-Version", "2.0.0")
+
+ client := &http.Client{}
+ resp, err := client.Do(req)
+ if err != nil {
+ return fmt.Errorf("Error sending request: %w", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusCreated {
+ body, _ := io.ReadAll(resp.Body)
+ return fmt.Errorf("Failed to post to LinkedIn. Status: %s\n%s\n\n", resp.Status, body)
+ }
+ return nil
}
diff --git a/internal/platforms/linkedin/oauth2.go b/internal/platforms/linkedin/oauth2.go
deleted file mode 100644
index 0492059..0000000
--- a/internal/platforms/linkedin/oauth2.go
+++ /dev/null
@@ -1,145 +0,0 @@
-package linkedin
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "io"
- "log"
- "net/http"
-
- "codeberg.org/snonux/gos/internal/config"
- "golang.org/x/oauth2"
- "golang.org/x/oauth2/linkedin"
-)
-
-var oauthConfig *oauth2.Config
-
-func getLinkedInID(token *oauth2.Token) (string, error) {
- const url = "https://api.linkedin.com/v2/userinfo"
-
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return "", fmt.Errorf("Error creating request:%w", err)
- }
-
- req.Header.Set("Authorization", "Bearer "+token.AccessToken)
- req.Header.Set("X-RestLi-Protocol-Version", "2.0.0")
-
- client := &http.Client{}
- resp, err := client.Do(req)
- if err != nil {
- return "", fmt.Errorf("Error making the request:%w", err)
- }
- defer resp.Body.Close()
-
- body, _ := io.ReadAll(resp.Body)
- if resp.StatusCode != http.StatusOK {
- return "", fmt.Errorf("Failed to retrieve user profile. Status: %s\n%s\n", resp.Status, string(body))
- }
-
- type User struct {
- Sub string `json:"sub"`
- }
- var user User
- if err := json.Unmarshal(body, &user); err != nil {
- return "", fmt.Errorf("Error unmarshalling JSON: %w", err)
- }
-
- return user.Sub, nil
-}
-
-func postMessage(token *oauth2.Token, linkedInID, message string) error {
- const url = "https://api.linkedin.com/v2/posts"
-
- post := map[string]interface{}{
- "author": fmt.Sprintf("urn:li:person:%s", linkedInID),
- "commentary": message,
- "visibility": "PUBLIC",
- "distribution": map[string]interface{}{
- "feedDistribution": "MAIN_FEED",
- "targetEntities": []string{},
- "thirdPartyDistributionChannels": []string{},
- },
- "lifecycleState": "PUBLISHED",
- "isReshareDisabledByAuthor": false,
- }
-
- payload, err := json.Marshal(post)
- if err != nil {
- return fmt.Errorf("Error encoding JSON:%w", err)
- }
-
- req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload))
- if err != nil {
- return fmt.Errorf("Error creating request: %w", err)
- }
-
- req.Header.Add("Authorization", "Bearer "+token.AccessToken)
- req.Header.Set("Content-Type", "application/json")
- req.Header.Add("X-RestLi-Protocol-Version", "2.0.0")
-
- client := &http.Client{}
- resp, err := client.Do(req)
- if err != nil {
- return fmt.Errorf("Error sending request: %w", err)
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusCreated {
- body, _ := io.ReadAll(resp.Body)
- return fmt.Errorf("Failed to post to LinkedIn. Status: %s\n%s\n\n", resp.Status, body)
- }
- return nil
-}
-
-func oauthIndexHandler(w http.ResponseWriter, r *http.Request) {
- url := oauthConfig.AuthCodeURL("state", oauth2.AccessTypeOffline)
- http.Redirect(w, r, url, http.StatusTemporaryRedirect)
-}
-
-func oauthCallbackHandler(w http.ResponseWriter, r *http.Request) {
- code := r.URL.Query().Get("code")
-
- token, err := oauthConfig.Exchange(context.Background(), code)
- if err != nil {
- http.Error(w, "Failed to exchange token", http.StatusInternalServerError)
- return
- }
-
- linkedInID, err := getLinkedInID(token)
- if err != nil {
- fmt.Println(err)
- _, _ = w.Write([]byte(err.Error()))
- return
- }
- _, _ = w.Write([]byte("Successfully fetched the LinkedInID\n"))
-
- if err := postMessage(token, linkedInID, "test"); err != nil {
- fmt.Println(err)
- _, _ = w.Write([]byte(err.Error()))
- return
- }
- _, _ = w.Write([]byte("Successfully posted a message to LinkedIn!\n"))
-}
-
-// TODO: Check for how logn the access token is valid for
-// TODO: Fetch the access token and user ID and store it i na file in .config/gos/...
-// TODO: Refresh access token when it is about to expire or expired
-// TODO: Separate posting of the message and fetching of the userID and access token
-func oauth(args config.Args) error {
- oauthConfig = &oauth2.Config{
- ClientID: args.Secrets.LinkedInClientID,
- ClientSecret: args.Secrets.LinkedInSecret,
- RedirectURL: args.Secrets.LinkedInRedirectURL,
- Scopes: []string{"openid", "profile", "w_member_social"},
- Endpoint: linkedin.Endpoint,
- }
-
- http.HandleFunc("/", oauthIndexHandler)
- http.HandleFunc("/callback", oauthCallbackHandler)
-
- log.Println("Listening on http://localhost:8080 for LinkedIn oauth2")
- return http.ListenAndServe(":8080", nil)
-}