commit
c8681ba96c
6 changed files with 156 additions and 0 deletions
-
1.gitignore
-
13Dockerfile
-
35Feed.go
-
73JsonFeedToTelegram.go
-
31Telegram.go
-
3go.mod
@ -0,0 +1 @@ |
|||
.idea/ |
@ -0,0 +1,13 @@ |
|||
FROM golang:1.14-alpine as build |
|||
ADD . /app |
|||
WORKDIR /app |
|||
RUN go build |
|||
|
|||
FROM alpine:3.11 |
|||
RUN apk add --no-cache tzdata ca-certificates |
|||
COPY --from=build /app/JsonFeedToTelegram /bin/ |
|||
WORKDIR /app |
|||
VOLUME /app/storage |
|||
EXPOSE 8080 |
|||
ENV LAST_ARTICLE_FILE /app/storage/lastarticle |
|||
CMD ["JsonFeedToTelegram"] |
@ -0,0 +1,35 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"errors" |
|||
"net/http" |
|||
) |
|||
|
|||
type Article struct { |
|||
Title string `json:"title"` |
|||
Url string `json:"url"` |
|||
} |
|||
|
|||
func LatestArticle(url string) (*Article, error) { |
|||
jsonFeed := &struct { |
|||
Items []Article `json:"items"` |
|||
}{} |
|||
req, err := http.NewRequest(http.MethodGet, url, nil) |
|||
if err != nil { |
|||
return nil, errors.New("failed to create req to get json feed") |
|||
} |
|||
req.Header.Add("User-Agent", "JsonFeedToTelegram") |
|||
resp, err := http.DefaultClient.Do(req) |
|||
if err != nil { |
|||
return nil, errors.New("failed to get json feed") |
|||
} |
|||
err = json.NewDecoder(resp.Body).Decode(&jsonFeed) |
|||
if err != nil { |
|||
return nil, errors.New("failed to parse json feed") |
|||
} |
|||
if len(jsonFeed.Items) < 1 { |
|||
return nil, errors.New("no articles in feed") |
|||
} |
|||
return &jsonFeed.Items[0], nil |
|||
} |
@ -0,0 +1,73 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"bytes" |
|||
"errors" |
|||
"fmt" |
|||
"io/ioutil" |
|||
"log" |
|||
"net/http" |
|||
"os" |
|||
"time" |
|||
) |
|||
|
|||
func main() { |
|||
lastArticleFile, lastArticleFileSet := os.LookupEnv("LAST_ARTICLE_FILE") |
|||
feed, feedSet := os.LookupEnv("FEED") |
|||
botToken, botTokenSet := os.LookupEnv("BOT_TOKEN") |
|||
channel, channelSet := os.LookupEnv("CHANNEL") |
|||
if lastArticleFileSet && feedSet && botTokenSet && channelSet { |
|||
telegram := Telegram{botToken: botToken, channel: channel} |
|||
http.HandleFunc("/hook", func(w http.ResponseWriter, r *http.Request) { |
|||
if r.Method != http.MethodPost { |
|||
http.Error(w, "Wrong HTTP method", http.StatusMethodNotAllowed) |
|||
return |
|||
} |
|||
fmt.Println("Fetch feed: ", time.Now().Format(time.RFC3339)) |
|||
article, err := LatestArticle(feed) |
|||
if err != nil { |
|||
http.Error(w, err.Error(), http.StatusInternalServerError) |
|||
return |
|||
} |
|||
if lastArticle := lastArticleUrl(lastArticleFile); lastArticle != article.Url { |
|||
err = telegram.Post(createMessage(article)) |
|||
if err != nil { |
|||
http.Error(w, err.Error(), http.StatusInternalServerError) |
|||
return |
|||
} |
|||
err = updateLastArticleUrl(lastArticleFile, article.Url) |
|||
if err != nil { |
|||
http.Error(w, err.Error(), http.StatusInternalServerError) |
|||
return |
|||
} |
|||
} else { |
|||
http.Error(w, errors.New("no new article").Error(), http.StatusInternalServerError) |
|||
return |
|||
} |
|||
}) |
|||
log.Fatal(http.ListenAndServe(":8080", nil)) |
|||
} else { |
|||
log.Fatal("Not configured") |
|||
} |
|||
} |
|||
|
|||
func lastArticleUrl(filename string) string { |
|||
fileContent, _ := ioutil.ReadFile(filename) |
|||
return string(fileContent) |
|||
} |
|||
|
|||
func updateLastArticleUrl(filename, url string) error { |
|||
return ioutil.WriteFile(filename, []byte(url), 0644) |
|||
} |
|||
|
|||
func createMessage(article *Article) string { |
|||
var message bytes.Buffer |
|||
message.WriteString("🔔 Something new was published") |
|||
message.WriteString("\n\n") |
|||
if article.Title != "" { |
|||
message.WriteString(article.Title) |
|||
message.WriteString("\n\n") |
|||
} |
|||
message.WriteString(article.Url) |
|||
return message.String() |
|||
} |
@ -0,0 +1,31 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"errors" |
|||
"net/http" |
|||
"net/url" |
|||
) |
|||
|
|||
type Telegram struct { |
|||
channel string |
|||
botToken string |
|||
} |
|||
|
|||
var telegramBaseUrl = "https://api.telegram.org/bot" |
|||
|
|||
func (t *Telegram) Post(message string) error { |
|||
params := url.Values{} |
|||
params.Add("chat_id", t.channel) |
|||
params.Add("text", message) |
|||
tgUrl, err := url.Parse(telegramBaseUrl + t.botToken + "/sendMessage") |
|||
if err != nil { |
|||
return errors.New("failed to create Telegram request") |
|||
} |
|||
tgUrl.RawQuery = params.Encode() |
|||
req, _ := http.NewRequest(http.MethodPost, tgUrl.String(), nil) |
|||
resp, err := http.DefaultClient.Do(req) |
|||
if err != nil || resp.StatusCode != 200 { |
|||
return errors.New("failed to send Telegram message") |
|||
} |
|||
return nil |
|||
} |
@ -0,0 +1,3 @@ |
|||
module git.jlel.se/jlelse/JsonFeedToTelegram |
|||
|
|||
go 1.14 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue