multiple discord senders
This commit is contained in:
@@ -1,16 +1,19 @@
|
|||||||
WIKI_BASE_URL=
|
WIKI_BASE_URL=
|
||||||
WIKI_TOKEN=
|
WIKI_TOKEN=
|
||||||
WIKI_CONTENT_LIMIT=10
|
WIKI_CONTENT_LIMIT=10
|
||||||
|
WIKI_DISCORD_WEBHOOK=
|
||||||
|
|
||||||
|
|
||||||
REDMINE_BASE_URL=
|
REDMINE_BASE_URL=
|
||||||
REDMINE_KEY=
|
REDMINE_KEY=
|
||||||
REDMINE_CONTENT_LIMIT=10
|
REDMINE_CONTENT_LIMIT=10
|
||||||
|
REDMINE_DISCORD_WEBHOOK=
|
||||||
|
|
||||||
GITEA_TOKEN=
|
GITEA_TOKEN=
|
||||||
GITEA_BASE_URL=
|
GITEA_BASE_URL=
|
||||||
GITEA_REPOS=org/repo1,org/repo2
|
GITEA_REPOS=org/repo1,org/repo2
|
||||||
GITEA_CONTENT_LIMIT=10
|
GITEA_CONTENT_LIMIT=10
|
||||||
|
GITEA_DISCORD_WEBHOOK=
|
||||||
|
|
||||||
|
|
||||||
DISCORD_WEBHOOK=
|
DISCORD_WEBHOOK=
|
||||||
|
|||||||
@@ -10,19 +10,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
WikiBaseURL string
|
WikiBaseURL string
|
||||||
WikiToken string
|
WikiToken string
|
||||||
WikiContentLimit int
|
WikiContentLimit int
|
||||||
RedmineBaseURL string
|
WikiDiscordWebhook string
|
||||||
RedmineKey string
|
RedmineBaseURL string
|
||||||
RedmineContentLimit int
|
RedmineKey string
|
||||||
GiteaToken string
|
RedmineContentLimit int
|
||||||
GiteaBaseURL string
|
RedmineDiscordWebhook string
|
||||||
GiteaRepos []string
|
GiteaToken string
|
||||||
GiteaContentLimit int
|
GiteaBaseURL string
|
||||||
DiscordWebhook string
|
GiteaRepos []string
|
||||||
DiscordFake bool
|
GiteaContentLimit int
|
||||||
Interval time.Duration
|
GiteaDiscordWebhook string
|
||||||
|
DiscordWebhook string
|
||||||
|
DiscordFake bool
|
||||||
|
Interval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func envToInteger(key string, defaultValue int) int {
|
func envToInteger(key string, defaultValue int) int {
|
||||||
@@ -40,6 +43,6 @@ func envToInteger(key string, defaultValue int) int {
|
|||||||
|
|
||||||
func loadEnv() {
|
func loadEnv() {
|
||||||
if err := godotenv.Load(); err != nil {
|
if err := godotenv.Load(); err != nil {
|
||||||
log.Println("Warning: .env file not found, using environment variables")
|
log.Println("[BOOT] .env file not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ func (f *GiteaFetcher) Name() string {
|
|||||||
return "Gitea"
|
return "Gitea"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *GiteaFetcher) Fetch() []Entry {
|
func (f *GiteaFetcher) Fetch() []Message {
|
||||||
var entries []Entry
|
var messages []Message
|
||||||
|
|
||||||
for _, repo := range f.Repos {
|
for _, repo := range f.Repos {
|
||||||
repo = strings.TrimSpace(repo)
|
repo = strings.TrimSpace(repo)
|
||||||
@@ -54,18 +54,19 @@ func (f *GiteaFetcher) Fetch() []Entry {
|
|||||||
for _, content := range response {
|
for _, content := range response {
|
||||||
cacheKey := "gitea_commit_" + url.QueryEscape(f.BaseURL+repo+"_"+content.Sha)
|
cacheKey := "gitea_commit_" + url.QueryEscape(f.BaseURL+repo+"_"+content.Sha)
|
||||||
|
|
||||||
entry := f.TryCreateEntry(
|
message := f.TryCreateMessage(
|
||||||
|
"gitea",
|
||||||
cacheKey,
|
cacheKey,
|
||||||
content.Sha,
|
content.Sha,
|
||||||
fmt.Sprintf("📝 [%s] - (%s) %s", f.Name(), repo, content.Commit.Message),
|
fmt.Sprintf("📝 [%s] - (%s) %s", f.Name(), repo, content.Commit.Message),
|
||||||
content.HTMLURL,
|
content.HTMLURL,
|
||||||
)
|
)
|
||||||
|
|
||||||
if entry != nil {
|
if message != nil {
|
||||||
entries = append(entries, *entry)
|
messages = append(messages, *message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries
|
return messages
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,10 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Entry represents a single fetched item.
|
|
||||||
type Entry struct {
|
|
||||||
Title string
|
|
||||||
URL string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetcher is the interface for a fetcher.
|
// Fetcher is the interface for a fetcher.
|
||||||
type Fetcher interface {
|
type Fetcher interface {
|
||||||
Name() string
|
Name() string
|
||||||
Fetch() []Entry
|
Fetch() []Message
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaseFetcher contains common fields for all fetchers.
|
// BaseFetcher contains common fields for all fetchers.
|
||||||
@@ -27,10 +21,14 @@ type BaseFetcher struct {
|
|||||||
ContentLimit int
|
ContentLimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryCreateEntry checks the cache and creates an Entry if the value has changed.
|
// TryCreateMessage checks the cache and creates a Message if the value has changed.
|
||||||
func (b *BaseFetcher) TryCreateEntry(cacheKey, cacheValue, title, url string) *Entry {
|
func (b *BaseFetcher) TryCreateMessage(channel, cacheKey, cacheValue, title, url string) *Message {
|
||||||
if b.Cache.TryUpdate(cacheKey, cacheValue) {
|
if b.Cache.TryUpdate(cacheKey, cacheValue) {
|
||||||
return &Entry{Title: title, URL: url}
|
return &Message{
|
||||||
|
Channel: channel,
|
||||||
|
Title: title,
|
||||||
|
URL: url,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ func (f *RedmineFetcher) Name() string {
|
|||||||
return "Redmine"
|
return "Redmine"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *RedmineFetcher) Fetch() []Entry {
|
func (f *RedmineFetcher) Fetch() []Message {
|
||||||
var entries []Entry
|
var messages []Message
|
||||||
path := fmt.Sprintf("/issues.json?limit=%d&sort=updated_on:desc", f.ContentLimit)
|
path := fmt.Sprintf("/issues.json?limit=%d&sort=updated_on:desc", f.ContentLimit)
|
||||||
req := FetcherRequest{
|
req := FetcherRequest{
|
||||||
BaseURL: f.BaseURL,
|
BaseURL: f.BaseURL,
|
||||||
@@ -43,16 +43,17 @@ func (f *RedmineFetcher) Fetch() []Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, content := range response.Issues {
|
for _, content := range response.Issues {
|
||||||
entry := f.TryCreateEntry(
|
message := f.TryCreateMessage(
|
||||||
|
"redmine",
|
||||||
fmt.Sprintf("redmine_%d", content.ID),
|
fmt.Sprintf("redmine_%d", content.ID),
|
||||||
content.UpdatedOn,
|
content.UpdatedOn,
|
||||||
fmt.Sprintf("🎫 [%s] - #%d %s", f.Name(), content.ID, content.Subject),
|
fmt.Sprintf("🎫 [%s] - #%d %s", f.Name(), content.ID, content.Subject),
|
||||||
fmt.Sprintf("%s/issues/%d", f.BaseURL, content.ID),
|
fmt.Sprintf("%s/issues/%d", f.BaseURL, content.ID),
|
||||||
)
|
)
|
||||||
if entry != nil {
|
if message != nil {
|
||||||
entries = append(entries, *entry)
|
messages = append(messages, *message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries
|
return messages
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ func (f *WikiFetcher) Name() string {
|
|||||||
return "WikiJS"
|
return "WikiJS"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *WikiFetcher) Fetch() []Entry {
|
func (f *WikiFetcher) Fetch() []Message {
|
||||||
var entries []Entry
|
var messages []Message
|
||||||
query := fmt.Sprintf(`{"query":"{ pages { list(orderBy: UPDATED, orderByDirection: DESC, limit: %d){ path, updatedAt, title }}}"}`, f.ContentLimit)
|
query := fmt.Sprintf(`{"query":"{ pages { list(orderBy: UPDATED, orderByDirection: DESC, limit: %d){ path, updatedAt, title }}}"}`, f.ContentLimit)
|
||||||
|
|
||||||
req := FetcherRequest{
|
req := FetcherRequest{
|
||||||
@@ -50,17 +50,18 @@ func (f *WikiFetcher) Fetch() []Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, content := range response.Data.Pages.List {
|
for _, content := range response.Data.Pages.List {
|
||||||
entry := f.TryCreateEntry(
|
message := f.TryCreateMessage(
|
||||||
|
"wiki",
|
||||||
"wiki_"+content.Path,
|
"wiki_"+content.Path,
|
||||||
content.UpdatedAt,
|
content.UpdatedAt,
|
||||||
fmt.Sprintf("📖 [%s] - %s", f.Name(), content.Title),
|
fmt.Sprintf("📖 [%s] - %s", f.Name(), content.Title),
|
||||||
fmt.Sprintf("%s/%s", f.BaseURL, content.Path),
|
fmt.Sprintf("%s/%s", f.BaseURL, content.Path),
|
||||||
)
|
)
|
||||||
|
|
||||||
if entry != nil {
|
if message != nil {
|
||||||
entries = append(entries, *entry)
|
messages = append(messages, *message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries
|
return messages
|
||||||
}
|
}
|
||||||
|
|||||||
13
lib/message.go
Normal file
13
lib/message.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
Channel string
|
||||||
|
Title string
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Message) ToDiscord() string {
|
||||||
|
return fmt.Sprintf("[%s](%s)", m.Title, m.URL)
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -62,34 +61,50 @@ func getCache() Cache {
|
|||||||
return cache
|
return cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDiscordSender(config Config) DiscordSender {
|
func getMessages(fetchers []Fetcher) []Message {
|
||||||
return DiscordSender{
|
messages := []Message{}
|
||||||
Webhook: config.DiscordWebhook,
|
|
||||||
Fake: config.DiscordFake,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMessages(fetchers []Fetcher) []string {
|
|
||||||
messages := []string{}
|
|
||||||
for _, fetcher := range fetchers {
|
for _, fetcher := range fetchers {
|
||||||
entries := fetcher.Fetch()
|
fetchedMessages := fetcher.Fetch()
|
||||||
for _, entry := range entries {
|
for _, message := range fetchedMessages {
|
||||||
messages = append(messages, fmt.Sprintf("[%s](%s)", entry.Title, entry.URL))
|
messages = append(messages, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendMessageToDiscord(sender DiscordSender, message Message) {
|
||||||
|
log.Printf("[SCHEDULED] [SEND] (%s) %s\n", message.Channel, message.ToDiscord())
|
||||||
|
if sender.Fake {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sender.Send(message.ToDiscord())
|
||||||
|
}
|
||||||
|
|
||||||
func Runner() {
|
func Runner() {
|
||||||
loadEnv()
|
loadEnv()
|
||||||
config := getConfig()
|
config := getConfig()
|
||||||
cache := getCache()
|
cache := getCache()
|
||||||
discord_sender := getDiscordSender(config)
|
|
||||||
fetchers := getFetchers(&config, &cache)
|
fetchers := getFetchers(&config, &cache)
|
||||||
|
|
||||||
|
default_discord_sender := NewDiscordSender(config.DiscordWebhook, config.DiscordFake)
|
||||||
|
wiki_discord_sender := NewDiscordSender(config.WikiDiscordWebhook, config.DiscordFake)
|
||||||
|
redmine_discord_sender := NewDiscordSender(config.RedmineDiscordWebhook, config.DiscordFake)
|
||||||
|
gita_discord_sender := NewDiscordSender(config.GiteaDiscordWebhook, config.DiscordFake)
|
||||||
for {
|
for {
|
||||||
log.Println("Run updater...")
|
log.Println("[SCHEDULED] Run updater...")
|
||||||
messages := getMessages(fetchers)
|
messages := getMessages(fetchers)
|
||||||
discord_sender.SendBatch(messages)
|
for _, message := range messages {
|
||||||
|
switch message.Channel {
|
||||||
|
case "wiki":
|
||||||
|
sendMessageToDiscord(wiki_discord_sender, message)
|
||||||
|
case "redmine":
|
||||||
|
sendMessageToDiscord(redmine_discord_sender, message)
|
||||||
|
case "gitea":
|
||||||
|
sendMessageToDiscord(gita_discord_sender, message)
|
||||||
|
default:
|
||||||
|
sendMessageToDiscord(default_discord_sender, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
cache.Save()
|
cache.Save()
|
||||||
time.Sleep(config.Interval)
|
time.Sleep(config.Interval)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,16 @@ package lib
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewDiscordSender(webhook string, fake bool) DiscordSender {
|
||||||
|
return DiscordSender{
|
||||||
|
Webhook: webhook,
|
||||||
|
Fake: fake,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type DiscordSender struct {
|
type DiscordSender struct {
|
||||||
Webhook string
|
Webhook string
|
||||||
Fake bool
|
Fake bool
|
||||||
@@ -19,13 +25,3 @@ func (d DiscordSender) Send(msg string) {
|
|||||||
}
|
}
|
||||||
http.Post(d.Webhook, "application/json", bytes.NewBuffer(b))
|
http.Post(d.Webhook, "application/json", bytes.NewBuffer(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DiscordSender) SendBatch(msgs []string) {
|
|
||||||
for _, msg := range msgs {
|
|
||||||
log.Println("Sending to Discord:", msg)
|
|
||||||
if d.Fake {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
d.Send(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user