-
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.
- Loading branch information
0 parents
commit aac92c9
Showing
28 changed files
with
1,413 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: "Cronjob" | ||
on: | ||
schedule: | ||
- cron: '15 */6 * * *' | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
update-weather: | ||
permissions: write-all | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Update articles | ||
uses: huantt/[email protected] | ||
with: | ||
template-file: 'README.md.template' | ||
out-file: 'README.md' | ||
- name: Commit | ||
run: | | ||
git config user.name github-actions | ||
git config user.email [email protected] | ||
git add . | ||
git commit -m "update" | ||
git push origin main |
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,2 @@ | ||
.idea/ | ||
.test/ |
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,20 @@ | ||
FROM golang:1.21-bullseye as builder | ||
|
||
ENV CGO_ENABLED=1 | ||
ENV GOOS=linux | ||
ENV GOARCH=amd64 | ||
ENV GO111MODULE=on | ||
WORKDIR /app | ||
COPY go.mod . | ||
COPY go.sum . | ||
RUN go mod download | ||
COPY . . | ||
RUN go build -o app | ||
|
||
FROM ubuntu:22.04 | ||
RUN apt-get update && apt-get install -y tzdata ca-certificates | ||
RUN mkdir /app | ||
WORKDIR /app | ||
COPY --from=builder /app/app . | ||
RUN ln -s /app/app /bin/articles-updater | ||
ENTRYPOINT ["articles-updater", "update-articles"] |
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 @@ | ||
## About | ||
Collect your latest articles from sources such as [dev.to](https://dev.to), and then update the `README.md`. | ||
|
||
## Use GitHub Action to update your README | ||
|
||
**Step 1:** In your repository, create a file named `README.md.template`. | ||
|
||
**Step 2:** Write anything you want within the `README.md.template` file. | ||
|
||
**Step 3:** Embed one of the following entities within your `README.md.template`: | ||
|
||
- **Article listing:** | ||
```shell | ||
{{ template "article-list" .Articles }} | ||
``` | ||
|
||
If you are familiar with Go templates, you have access to the `root` variable, which includes the following fields: | ||
|
||
- `Articles`: An array of Article. You can view the Article struct definition in [model/article.go](model/article.go). | ||
- `Time`: Updated Time | ||
|
||
**Step 4**: Register Github Action | ||
- Create a file `.github/workflows/update-articles.yml` in your repository. | ||
```yml | ||
name: "Cronjob" | ||
on: | ||
schedule: | ||
- cron: '15 0 * * *' | ||
|
||
jobs: | ||
update-articles: | ||
permissions: write-all | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Generate README | ||
uses: huantt/[email protected] | ||
with: | ||
username: YOUR_USERNAME_ON_DEV_TO | ||
template-file: 'README.md.template' | ||
out-file: 'README.md' | ||
limit: 5 | ||
- name: Commit | ||
run: | | ||
git config user.name github-actions | ||
git config user.email [email protected] | ||
git add . | ||
git commit -m "update articles" | ||
git push origin main | ||
``` | ||
**Step 5**: Commit your change, then Github actions will run as your specified cron to update Articles into your README.md file | ||
## Below is my recent articles Jack collected from dev.to | ||
- [Creating Dynamic README.md File](https://dev.to/jacktt/creating-dynamic-readmemd-file-388o) - 09/09/2023 | ||
- [Search Goole Like a Pro [Cheat sheet]](https://dev.to/jacktt/search-goole-like-a-pro-cheat-sheet-555g) - 30/08/2023 | ||
- [Advanced Go Build Techniques](https://dev.to/jacktt/go-build-in-advance-4o8n) - 30/08/2023 | ||
- [Load Private Module in Golang Project](https://dev.to/jacktt/load-private-module-in-golang-project-122l) - 12/08/2023 | ||
- [Speed up your query in Postgres](https://dev.to/jacktt/speed-up-your-query-in-postgres-48e3) - 23/06/2023 | ||
*Updated at: 2023-09-13T19:51:42+07:00* |
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,58 @@ | ||
## About | ||
Collect your latest articles from sources such as [dev.to](https://dev.to), and then update the `README.md`. | ||
|
||
## Use GitHub Action to update your README | ||
|
||
**Step 1:** In your repository, create a file named `README.md.template`. | ||
|
||
**Step 2:** Write anything you want within the `README.md.template` file. | ||
|
||
**Step 3:** Embed one of the following entities within your `README.md.template`: | ||
|
||
- **Article listing:** | ||
```shell | ||
{{`{{`}} template "article-list" .Articles {{`}}`}} | ||
``` | ||
|
||
If you are familiar with Go templates, you have access to the `root` variable, which includes the following fields: | ||
|
||
- `Articles`: An array of Article. You can view the Article struct definition in [model/article.go](model/article.go). | ||
- `Time`: Updated Time | ||
|
||
**Step 4**: Register Github Action | ||
- Create a file `.github/workflows/update-articles.yml` in your repository. | ||
```yml | ||
name: "Cronjob" | ||
on: | ||
schedule: | ||
- cron: '15 0 * * *' | ||
|
||
jobs: | ||
update-articles: | ||
permissions: write-all | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Generate README | ||
uses: huantt/[email protected] | ||
with: | ||
username: YOUR_USERNAME_ON_DEV_TO | ||
template-file: 'README.md.template' | ||
out-file: 'README.md' | ||
limit: 5 | ||
- name: Commit | ||
run: | | ||
git config user.name github-actions | ||
git config user.email [email protected] | ||
git add . | ||
git commit -m "update articles" | ||
git push origin main | ||
``` | ||
|
||
**Step 5**: Commit your change, then Github actions will run as your specified cron to update Articles into your README.md file | ||
|
||
## Below is my recent articles {{ .Author }} collected from dev.to | ||
|
||
{{ template "article-list" .Articles }} | ||
|
||
*Updated at: {{ formatTime .Time }}* |
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 @@ | ||
name: 'Article updater' | ||
description: 'Collect articles then lists to README.md' | ||
inputs: | ||
username: | ||
description: 'Username' | ||
required: true | ||
template-file: | ||
description: 'Template file path' | ||
required: true | ||
out-file: | ||
description: 'Output file path' | ||
required: true | ||
limit: | ||
description: 'Limit number of articles' | ||
required: false | ||
default: '5' | ||
runs: | ||
using: 'docker' | ||
image: 'Dockerfile' | ||
args: | ||
- --limit=${{ inputs.limit }} | ||
- --username=${{ inputs.username }} | ||
- --template-file=${{ inputs.template-file }} | ||
- --out-file=${{ inputs.out-file }} |
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,54 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"github.com/huantt/article-listing/handler/collector" | ||
"github.com/huantt/article-listing/impl/article_service/forem" | ||
foremsrv "github.com/huantt/article-listing/pkg/forem" | ||
"github.com/spf13/cobra" | ||
"log/slog" | ||
"os" | ||
) | ||
|
||
func UpdateWeather(use string) *cobra.Command { | ||
var templateFilePath string | ||
var outputFilePath string | ||
var username string | ||
var limit int | ||
|
||
command := &cobra.Command{ | ||
Use: use, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
devToService := forem.NewService(foremsrv.NewService(foremsrv.DevToEndpoint)) | ||
handler := collector.NewHandler(devToService) | ||
err := handler.Collect(context.Background(), username, limit, templateFilePath, outputFilePath) | ||
if err != nil { | ||
slog.Error(err.Error()) | ||
os.Exit(1) | ||
} | ||
slog.Info("Updated!") | ||
}, | ||
} | ||
|
||
command.Flags().StringVarP(&templateFilePath, "template-file", "f", "", "Readme template file path") | ||
command.Flags().StringVarP(&outputFilePath, "out-file", "o", "", "Output file path") | ||
command.Flags().StringVarP(&username, "username", "u", "", "Username") | ||
command.Flags().IntVar(&limit, "limit", 5, "Limit number of articles") | ||
err := command.MarkFlagRequired("username") | ||
if err != nil { | ||
slog.Error(err.Error()) | ||
os.Exit(1) | ||
} | ||
err = command.MarkFlagRequired("template-file") | ||
if err != nil { | ||
slog.Error(err.Error()) | ||
os.Exit(1) | ||
} | ||
err = command.MarkFlagRequired("out-file") | ||
if err != nil { | ||
slog.Error(err.Error()) | ||
os.Exit(1) | ||
} | ||
|
||
return command | ||
} |
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 @@ | ||
## Top articles | ||
|
||
{{ template "article-list" $.Articles }} |
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,16 @@ | ||
module github.com/huantt/article-listing | ||
|
||
go 1.21 | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/go-resty/resty/v2 v2.7.0 // indirect | ||
github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/spf13/cobra v1.7.0 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
github.com/stretchr/objx v0.5.0 // indirect | ||
github.com/stretchr/testify v1.8.4 // indirect | ||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
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,34 @@ | ||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= | ||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= | ||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | ||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= | ||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= | ||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= | ||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM= | ||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
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,76 @@ | ||
package collector | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"fmt" | ||
"github.com/huantt/article-listing/model" | ||
"html/template" | ||
"log/slog" | ||
"os" | ||
"time" | ||
) | ||
|
||
type Handler struct { | ||
articleService ArticleService | ||
} | ||
|
||
func NewHandler(articleService ArticleService) *Handler { | ||
return &Handler{articleService} | ||
} | ||
|
||
func (h *Handler) Collect(ctx context.Context, username string, limit int, templateFilePath, outputFilePath string) error { | ||
articles, err := h.articleService.GetArticles(ctx, username, 1, limit) | ||
if err != nil { | ||
return err | ||
} | ||
slog.Info(fmt.Sprintf("Got %d article from %s", len(articles), username)) | ||
|
||
templateStr, err := os.ReadFile(templateFilePath) | ||
if err != nil { | ||
return err | ||
} | ||
output, err := generateOutput(articles, string(templateStr), templates...) | ||
if err != nil { | ||
return err | ||
} | ||
return os.WriteFile(outputFilePath, []byte(*output), 0644) | ||
} | ||
|
||
func generateOutput(articles []model.Article, readmeTemplate string, templates ...string) (*string, error) { | ||
if len(articles) == 0 { | ||
return nil, errors.New("articles must be not empty") | ||
} | ||
tmpl, err := template. | ||
New("article"). | ||
Funcs(template.FuncMap{ | ||
"formatDate": formatDate, | ||
"formatHour": formatHour, | ||
"formatTime": formatTime, | ||
"truncateByWords": truncateByWords, | ||
}). | ||
Parse(readmeTemplate) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, t := range templates { | ||
tmpl, err = tmpl.Parse(t) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
var result bytes.Buffer | ||
err = tmpl.ExecuteTemplate(&result, "article", map[string]any{ | ||
"Articles": articles, | ||
"Author": articles[0].Author, | ||
"Time": time.Now(), | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
stringResult := result.String() | ||
return &stringResult, nil | ||
} |
Oops, something went wrong.