-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Post on Mastodon when a new blog post is published (#6)
* test autotoot runs * Add push trigger for autotoot branch * fix i hope * dumb * xtra dumb * 2xtra dumb * test * . * . * . * . * . * perfected * IMPROVEMENTS * . * . * . * WORKING PERFECTLY * polish and test * . * TEST * minor fix * prepare
- Loading branch information
1 parent
5debde6
commit 659678c
Showing
8 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Auto-toot | ||
|
||
This is a simple Go app that checks the latest commit for new files added within the `/content/posts` directory. If there are new files, it will parse the Hugo blog post and automatically publish a Mastodon toot with the description, hashtags and link to the post. | ||
|
||
### Environment Variables | ||
|
||
| Variable | Description | Example | | ||
| ----------------------- | ---------------------------------------------------------- | --------------------------- | | ||
| `MASTODON_ACCESS_TOKEN` | The access token for your Mastodon account. | `a1b2c3d4e5f6g7h8i9j0` | | ||
| `MASTODON_ORIGIN` | The origin for your Mastodon instance. | `https://mas.to` | | ||
| `BLOG_ORIGIN` | The origin used when generating the link to the blog post. | `https://www.tobyscott.dev` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module auto-toot | ||
|
||
go 1.21.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package helpers | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os/exec" | ||
"strings" | ||
) | ||
|
||
// Returns a slice of strings representing the file paths of newly created files in the last commit. | ||
func GetNewFilesInLastCommit() ([]string, error) { | ||
// Use 'git diff' to get a list of added files in the last commit | ||
cmd := exec.Command("git", "diff", "--diff-filter=A", "--name-only", "HEAD~1", "HEAD") | ||
var out bytes.Buffer | ||
cmd.Stdout = &out | ||
err := cmd.Run() | ||
if err != nil { | ||
return nil, fmt.Errorf("error running git diff: %v", err) | ||
} | ||
|
||
// Split the output by new lines to get individual file paths | ||
files := strings.Split(strings.TrimSpace(out.String()), "\n") | ||
return files, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package helpers | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"net/url" | ||
"os" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
type HugoPost struct { | ||
Description string `json:"description"` | ||
Tags []string `json:"tags"` | ||
URL string `json:"url"` | ||
} | ||
|
||
func ParseHugoPost(filePath string, blogUrl string) (HugoPost, error) { | ||
|
||
file, err := os.Open(filePath) | ||
if err != nil { | ||
fmt.Printf("Error opening file: %v\n", err) | ||
return HugoPost{}, err | ||
} | ||
defer file.Close() | ||
|
||
var fileContent strings.Builder | ||
scanner := bufio.NewScanner(file) | ||
for scanner.Scan() { | ||
fileContent.WriteString(scanner.Text() + "\n") | ||
} | ||
if err := scanner.Err(); err != nil { | ||
fmt.Printf("Error reading file: %v\n", err) | ||
return HugoPost{}, err | ||
} | ||
|
||
// Convert the builder to a string for regex processing | ||
contentString := fileContent.String() | ||
|
||
// Convert the file path to a blog post URL | ||
postSlug := strings.TrimPrefix(filePath, "../content/posts/") | ||
postSlug = strings.TrimSuffix(postSlug, ".md") | ||
postSlug = strings.TrimSuffix(postSlug, "/index") // Remove '/index' if present | ||
|
||
// Use url.QueryEscape to encode spaces and other characters in the post slug | ||
postSlug = url.QueryEscape(postSlug) | ||
|
||
blogPostURL := fmt.Sprintf(blogUrl+"/posts/%s", postSlug) | ||
|
||
// Use regex to find the description block | ||
descriptionRegex := regexp.MustCompile(`description: "(.*?)"`) | ||
descriptionMatch := descriptionRegex.FindStringSubmatch(contentString) | ||
|
||
description := "" | ||
if len(descriptionMatch) > 1 { | ||
description = descriptionMatch[1] | ||
} | ||
|
||
// Use regex to find the tags block (taking new lines into account) | ||
tagsRegex := regexp.MustCompile(`(?s)tags:\s+\[(.*?)\]`) | ||
tagsMatch := tagsRegex.FindStringSubmatch(contentString) | ||
|
||
// Process tags | ||
var tags []string | ||
if len(tagsMatch) > 1 { | ||
// Remove the square brackets and split the string by comma | ||
tagsStr := strings.Trim(tagsMatch[1], "[]") | ||
tagsStr = strings.Replace(tagsStr, " \"", "\"", -1) // Remove 4-space indentations | ||
tagsStr = strings.Replace(tagsStr, "\"", "", -1) // Remove quotes | ||
tagsStr = strings.Replace(tagsStr, "\n", "", -1) // Remove newlines | ||
tagsStr = strings.Replace(tagsStr, " ", "", -1) // Remove spaces | ||
|
||
// Remove trailing comma | ||
if strings.HasSuffix(tagsStr, ",") { | ||
tagsStr = tagsStr[:len(tagsStr)-1] | ||
} | ||
tags = strings.Split(tagsStr, ",") | ||
|
||
} | ||
|
||
post := HugoPost{ | ||
Description: description, | ||
Tags: tags, | ||
URL: blogPostURL, | ||
} | ||
|
||
return post, nil | ||
} | ||
|
||
func (p HugoPost) GetHashtagString() string { | ||
var hashtags []string | ||
for _, tag := range p.Tags { | ||
hashtags = append(hashtags, fmt.Sprintf("#%s", tag)) | ||
} | ||
hashtagsStr := strings.Join(hashtags, " ") | ||
hashtagsStr = strings.TrimSpace(hashtagsStr) // Trim the trailing space | ||
return hashtagsStr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package helpers | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"strings" | ||
) | ||
|
||
// Structure to parse the response from Mastodon API | ||
type MastodonStatusResponse struct { | ||
URL string `json:"url"` | ||
} | ||
|
||
func SendToot(mastodonURL string, accessToken string, status string) error { | ||
data := url.Values{} | ||
data.Set("status", status) | ||
|
||
// Create a new request | ||
req, err := http.NewRequest("POST", mastodonURL+"/api/v1/statuses", strings.NewReader(data.Encode())) | ||
if err != nil { | ||
fmt.Printf("Error creating request: %v\n", err) | ||
return err | ||
} | ||
|
||
// Set headers | ||
req.Header.Set("Authorization", "Bearer "+accessToken) | ||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") | ||
|
||
// Send the request | ||
client := &http.Client{} | ||
resp, err := client.Do(req) | ||
if err != nil { | ||
fmt.Printf("Error posting to Mastodon: %v\n", err) | ||
return err | ||
} | ||
defer resp.Body.Close() | ||
|
||
// Check the response | ||
if resp.StatusCode != http.StatusOK { | ||
fmt.Printf("Error response from Mastodon: %v\n", resp.Status) | ||
return err | ||
} | ||
|
||
// Read response body | ||
respBody, error := io.ReadAll(resp.Body) | ||
if error != nil { | ||
fmt.Println(error) | ||
} | ||
|
||
// Parse the JSON response | ||
var mastodonResp MastodonStatusResponse | ||
if err := json.Unmarshal(respBody, &mastodonResp); err != nil { | ||
fmt.Printf("Error parsing JSON response: %v\n", err) | ||
return err | ||
} | ||
|
||
fmt.Printf("Successfully posted to Mastodon: %s \n", mastodonResp.URL) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package main | ||
|
||
import ( | ||
"auto-toot/helpers" | ||
"fmt" | ||
"os" | ||
"strings" | ||
) | ||
|
||
func main() { | ||
|
||
mastodonOrigin := os.Getenv("MASTODON_ORIGIN") | ||
blogOrigin := os.Getenv("BLOG_ORIGIN") | ||
accessToken := os.Getenv("MASTODON_ACCESS_TOKEN") | ||
|
||
newFiles, err := helpers.GetNewFilesInLastCommit() | ||
if err != nil { | ||
fmt.Printf("Error getting new files: %v\n", err) | ||
return | ||
} | ||
|
||
for _, file := range newFiles { | ||
|
||
if strings.HasPrefix(file, "content/posts/") { | ||
|
||
filePath := "../" + file | ||
|
||
hugoPostDetails, err := helpers.ParseHugoPost(filePath, blogOrigin) | ||
if err != nil { | ||
fmt.Printf("Error parsing Hugo post: %v\n", err) | ||
return | ||
} | ||
|
||
hashtagString := hugoPostDetails.GetHashtagString() | ||
status := fmt.Sprintf("%s\n\n%s\n\n%s", hugoPostDetails.Description, hugoPostDetails.URL, hashtagString) | ||
|
||
helpers.SendToot(mastodonOrigin, accessToken, status) | ||
if err != nil { | ||
fmt.Printf("Error posting about %s to Mastodon: %v\n", filePath, err) | ||
} else { | ||
fmt.Printf("Successfully posted about %s to Mastodon.\n", filePath) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
go 1.21.1 | ||
|
||
use ( | ||
./auto-toot | ||
) |