1
0
Fork 0

Improve Telegram integration

- Remove dependency on `go-telegram-bot-api`
- Add new options: optional topic ID, disable page preview, disable notifications
- Add new button to go to article
This commit is contained in:
Frédéric Guillot 2023-09-10 11:22:32 -07:00
parent d33db40b39
commit cb228e73ad
29 changed files with 601 additions and 316 deletions

2
go.mod
View file

@ -5,7 +5,6 @@ module miniflux.app/v2
require ( require (
github.com/PuerkitoBio/goquery v1.8.1 github.com/PuerkitoBio/goquery v1.8.1
github.com/coreos/go-oidc/v3 v3.6.0 github.com/coreos/go-oidc/v3 v3.6.0
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/mccutchen/go-httpbin/v2 v2.11.0 github.com/mccutchen/go-httpbin/v2 v2.11.0
@ -31,7 +30,6 @@ require (
github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect github.com/prometheus/procfs v0.10.1 // indirect
github.com/tdewolff/parse/v2 v2.6.7 // indirect github.com/tdewolff/parse/v2 v2.6.7 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
golang.org/x/sys v0.11.0 // indirect golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect golang.org/x/text v0.12.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect

4
go.sum
View file

@ -13,8 +13,6 @@ 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
@ -55,8 +53,6 @@ github.com/tdewolff/parse/v2 v2.6.7 h1:WrFllrqmzAcrKHzoYgMupqgUBIfBVOb0yscFzDf8b
github.com/tdewolff/parse/v2 v2.6.7/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= github.com/tdewolff/parse/v2 v2.6.7/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM=
github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0= github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0=
github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA= github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA=
github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=

View file

@ -767,4 +767,13 @@ var migrations = []func(tx *sql.Tx) error{
_, err = tx.Exec(sql) _, err = tx.Exec(sql)
return err return err
}, },
func(tx *sql.Tx) (err error) {
sql := `
ALTER TABLE integrations ADD COLUMN telegram_bot_topic_id int;
ALTER TABLE integrations ADD COLUMN telegram_bot_disable_web_page_preview bool default 'f';
ALTER TABLE integrations ADD COLUMN telegram_bot_disable_notification bool default 'f';
`
_, err = tx.Exec(sql)
return err
},
} }

View file

@ -172,7 +172,7 @@ func SendEntry(entry *model.Entry, integration *model.Integration) {
// PushEntries pushes a list of entries to activated third-party providers during feed refreshes. // PushEntries pushes a list of entries to activated third-party providers during feed refreshes.
func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *model.Integration) { func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *model.Integration) {
if userIntegrations.MatrixBotEnabled { if userIntegrations.MatrixBotEnabled {
logger.Debug("[Integration] Sending %d entries for User #%d to Matrix", len(entries), userIntegrations.UserID) logger.Debug("[Integration] Sending %d entries for user #%d to Matrix", len(entries), userIntegrations.UserID)
err := matrixbot.PushEntries(feed, entries, userIntegrations.MatrixBotURL, userIntegrations.MatrixBotUser, userIntegrations.MatrixBotPassword, userIntegrations.MatrixBotChatID) err := matrixbot.PushEntries(feed, entries, userIntegrations.MatrixBotURL, userIntegrations.MatrixBotUser, userIntegrations.MatrixBotPassword, userIntegrations.MatrixBotChatID)
if err != nil { if err != nil {
@ -193,16 +193,23 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode
if userIntegrations.TelegramBotEnabled || userIntegrations.AppriseEnabled { if userIntegrations.TelegramBotEnabled || userIntegrations.AppriseEnabled {
for _, entry := range entries { for _, entry := range entries {
if userIntegrations.TelegramBotEnabled { if userIntegrations.TelegramBotEnabled {
logger.Debug("[Integration] Sending Entry %q for User #%d to Telegram", entry.URL, userIntegrations.UserID) logger.Debug("[Integration] Sending entry %q for user #%d to Telegram", entry.URL, userIntegrations.UserID)
err := telegrambot.PushEntry(entry, userIntegrations.TelegramBotToken, userIntegrations.TelegramBotChatID) if err := telegrambot.PushEntry(
if err != nil { feed,
logger.Error("[Integration] push entry to telegram bot failed: %v", err) entry,
userIntegrations.TelegramBotToken,
userIntegrations.TelegramBotChatID,
userIntegrations.TelegramBotTopicID,
userIntegrations.TelegramBotDisableWebPagePreview,
userIntegrations.TelegramBotDisableNotification,
); err != nil {
logger.Error("[Integration] %v", err)
} }
} }
if userIntegrations.AppriseEnabled { if userIntegrations.AppriseEnabled {
logger.Debug("[Integration] Sending Entry %q for User #%d to apprise", entry.URL, userIntegrations.UserID) logger.Debug("[Integration] Sending entry %q for user #%d to Apprise", entry.URL, userIntegrations.UserID)
appriseServiceURLs := userIntegrations.AppriseURL appriseServiceURLs := userIntegrations.AppriseURL
if feed.AppriseServiceURLs != "" { if feed.AppriseServiceURLs != "" {
@ -215,7 +222,7 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode
) )
if err := client.SendNotification(entry); err != nil { if err := client.SendNotification(entry); err != nil {
logger.Error("[Integration] push entry to apprise failed: %v", err) logger.Error("[Integration] %v", err)
} }
} }
} }

View file

@ -0,0 +1,174 @@
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package telegrambot // import "miniflux.app/v2/internal/integration/telegrambot"
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
"miniflux.app/v2/internal/version"
)
const (
defaultClientTimeout = 10 * time.Second
telegramAPIEndpoint = "https://api.telegram.org"
MarkdownFormatting = "Markdown"
MarkdownV2Formatting = "MarkdownV2"
HTMLFormatting = "HTML"
)
type Client struct {
botToken string
chatID string
}
func NewClient(botToken, chatID string) *Client {
return &Client{
botToken: botToken,
chatID: chatID,
}
}
// Specs: https://core.telegram.org/bots/api#getme
func (c *Client) GetMe() (*User, error) {
endpointURL, err := url.JoinPath(telegramAPIEndpoint, "/bot"+c.botToken, "/getMe")
if err != nil {
return nil, fmt.Errorf("telegram: unable to join base URL and path: %w", err)
}
request, err := http.NewRequest(http.MethodGet, endpointURL, nil)
if err != nil {
return nil, fmt.Errorf("telegram: unable to create request: %v", err)
}
request.Header.Set("Accept", "application/json")
request.Header.Set("User-Agent", "Miniflux/"+version.Version)
httpClient := &http.Client{Timeout: defaultClientTimeout}
response, err := httpClient.Do(request)
if err != nil {
return nil, fmt.Errorf("telegram: unable to send request: %v", err)
}
defer response.Body.Close()
var userResponse UserResponse
if err := json.NewDecoder(response.Body).Decode(&userResponse); err != nil {
return nil, fmt.Errorf("telegram: unable to decode user response: %w", err)
}
if !userResponse.Ok {
return nil, fmt.Errorf("telegram: unable to send message: %s (error code is %d)", userResponse.Description, userResponse.ErrorCode)
}
return &userResponse.Result, nil
}
// Specs: https://core.telegram.org/bots/api#sendmessage
func (c *Client) SendMessage(message *MessageRequest) (*Message, error) {
endpointURL, err := url.JoinPath(telegramAPIEndpoint, "/bot"+c.botToken, "/sendMessage")
if err != nil {
return nil, fmt.Errorf("telegram: unable to join base URL and path: %w", err)
}
requestBody, err := json.Marshal(message)
if err != nil {
return nil, fmt.Errorf("telegram: unable to encode request body: %v", err)
}
request, err := http.NewRequest(http.MethodPost, endpointURL, bytes.NewReader(requestBody))
if err != nil {
return nil, fmt.Errorf("telegram: unable to create request: %v", err)
}
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Accept", "application/json")
request.Header.Set("User-Agent", "Miniflux/"+version.Version)
httpClient := &http.Client{Timeout: defaultClientTimeout}
response, err := httpClient.Do(request)
if err != nil {
return nil, fmt.Errorf("telegram: unable to send request: %v", err)
}
defer response.Body.Close()
var messageResponse MessageResponse
if err := json.NewDecoder(response.Body).Decode(&messageResponse); err != nil {
return nil, fmt.Errorf("telegram: unable to decode discovery response: %w", err)
}
if !messageResponse.Ok {
return nil, fmt.Errorf("telegram: unable to send message: %s (error code is %d)", messageResponse.Description, messageResponse.ErrorCode)
}
return &messageResponse.Result, nil
}
type InlineKeyboard struct {
InlineKeyboard []InlineKeyboardRow `json:"inline_keyboard"`
}
type InlineKeyboardRow []*InlineKeyboardButton
type InlineKeyboardButton struct {
Text string `json:"text"`
URL string `json:"url,omitempty"`
}
type User struct {
ID int64 `json:"id"`
IsBot bool `json:"is_bot"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Username string `json:"username"`
LanguageCode string `json:"language_code"`
IsPremium bool `json:"is_premium"`
CanJoinGroups bool `json:"can_join_groups"`
CanReadAllGroupMessages bool `json:"can_read_all_group_messages"`
SupportsInlineQueries bool `json:"supports_inline_queries"`
}
type Chat struct {
ID int64 `json:"id"`
Type string `json:"type"`
Title string `json:"title"`
}
type Message struct {
MessageID int64 `json:"message_id"`
From User `json:"from"`
Chat Chat `json:"chat"`
MessageThreadID int64 `json:"message_thread_id"`
Date int64 `json:"date"`
}
type BaseResponse struct {
Ok bool `json:"ok"`
ErrorCode int `json:"error_code"`
Description string `json:"description"`
}
type UserResponse struct {
BaseResponse
Result User `json:"result"`
}
type MessageRequest struct {
ChatID string `json:"chat_id"`
MessageThreadID int64 `json:"message_thread_id,omitempty"`
Text string `json:"text"`
ParseMode string `json:"parse_mode,omitempty"`
DisableWebPagePreview bool `json:"disable_web_page_preview"`
DisableNotification bool `json:"disable_notification"`
ReplyMarkup *InlineKeyboard `json:"reply_markup,omitempty"`
}
type MessageResponse struct {
BaseResponse
Result Message `json:"result"`
}

View file

@ -4,47 +4,47 @@
package telegrambot // import "miniflux.app/v2/internal/integration/telegrambot" package telegrambot // import "miniflux.app/v2/internal/integration/telegrambot"
import ( import (
"bytes"
"fmt" "fmt"
"html/template"
"strconv"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
"miniflux.app/v2/internal/model" "miniflux.app/v2/internal/model"
) )
// PushEntry pushes entry to telegram chat using integration settings provided func PushEntry(feed *model.Feed, entry *model.Entry, botToken, chatID string, topicID *int64, disableWebPagePreview, disableNotification bool) error {
func PushEntry(entry *model.Entry, botToken, chatID string) error { textTemplate := `<b><a href=%q>%s</a></b> - <a href=%q>%s</a>`
bot, err := tgbotapi.NewBotAPI(botToken) formattedText := fmt.Sprintf(
if err != nil { textTemplate,
return fmt.Errorf("telegrambot: bot creation failed: %w", err) feed.SiteURL,
feed.Title,
entry.URL,
entry.Title,
)
message := &MessageRequest{
ChatID: chatID,
Text: formattedText,
ParseMode: HTMLFormatting,
DisableWebPagePreview: disableWebPagePreview,
DisableNotification: disableNotification,
} }
tpl, err := template.New("message").Parse("{{ .Title }}\n<a href=\"{{ .URL }}\">{{ .URL }}</a>") if topicID != nil {
if err != nil { message.MessageThreadID = *topicID
return fmt.Errorf("telegrambot: template parsing failed: %w", err)
} }
var result bytes.Buffer var markupRow []*InlineKeyboardButton
if err := tpl.Execute(&result, entry); err != nil {
return fmt.Errorf("telegrambot: template execution failed: %w", err)
}
chatIDInt, _ := strconv.ParseInt(chatID, 10, 64) minifluxURLButton := InlineKeyboardButton{Text: "Go to article", URL: entry.URL}
msg := tgbotapi.NewMessage(chatIDInt, result.String()) markupRow = append(markupRow, &minifluxURLButton)
msg.ParseMode = tgbotapi.ModeHTML
msg.DisableWebPagePreview = false
if entry.CommentsURL != "" { if entry.CommentsURL != "" {
msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup( commentButton := InlineKeyboardButton{Text: "Comments", URL: entry.CommentsURL}
tgbotapi.NewInlineKeyboardRow( markupRow = append(markupRow, &commentButton)
tgbotapi.NewInlineKeyboardButtonURL("Comments", entry.CommentsURL),
))
} }
if _, err := bot.Send(msg); err != nil { message.ReplyMarkup = &InlineKeyboard{}
return fmt.Errorf("telegrambot: sending message failed: %w", err) message.ReplyMarkup.InlineKeyboard = append(message.ReplyMarkup.InlineKeyboard, markupRow)
}
return nil client := NewClient(botToken, chatID)
_, err := client.SendMessage(message)
return err
} }

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Pushen Sie neue Artikel in den Telegram-Chat", "form.integration.telegram_bot_activate": "Pushen Sie neue Artikel in den Telegram-Chat",
"form.integration.telegram_bot_token": "Bot token", "form.integration.telegram_bot_token": "Bot token",
"form.integration.telegram_chat_id": "Chat ID", "form.integration.telegram_chat_id": "Chat ID",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Artikel in Linkding speichern", "form.integration.linkding_activate": "Artikel in Linkding speichern",
"form.integration.linkding_endpoint": "Linkding API-Endpunkt", "form.integration.linkding_endpoint": "Linkding API-Endpunkt",
"form.integration.linkding_api_key": "Linkding API-Schlüssel", "form.integration.linkding_api_key": "Linkding API-Schlüssel",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Προωθήστε νέα άρθρα στη συνομιλία Telegram", "form.integration.telegram_bot_activate": "Προωθήστε νέα άρθρα στη συνομιλία Telegram",
"form.integration.telegram_bot_token": "Διακριτικό bot", "form.integration.telegram_bot_token": "Διακριτικό bot",
"form.integration.telegram_chat_id": "Αναγνωριστικό συνομιλίας", "form.integration.telegram_chat_id": "Αναγνωριστικό συνομιλίας",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Αποθήκευση άρθρων στο Linkding", "form.integration.linkding_activate": "Αποθήκευση άρθρων στο Linkding",
"form.integration.linkding_endpoint": "Τελικό σημείο Linkding API", "form.integration.linkding_endpoint": "Τελικό σημείο Linkding API",
"form.integration.linkding_api_key": "Κλειδί API Linkding", "form.integration.linkding_api_key": "Κλειδί API Linkding",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Push new entries to Telegram chat", "form.integration.telegram_bot_activate": "Push new entries to Telegram chat",
"form.integration.telegram_bot_token": "Bot token", "form.integration.telegram_bot_token": "Bot token",
"form.integration.telegram_chat_id": "Chat ID", "form.integration.telegram_chat_id": "Chat ID",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Save entries to Linkding", "form.integration.linkding_activate": "Save entries to Linkding",
"form.integration.linkding_endpoint": "Linkding API Endpoint", "form.integration.linkding_endpoint": "Linkding API Endpoint",
"form.integration.linkding_api_key": "Linkding API key", "form.integration.linkding_api_key": "Linkding API key",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Envíe nuevos artículos al chat de Telegram", "form.integration.telegram_bot_activate": "Envíe nuevos artículos al chat de Telegram",
"form.integration.telegram_bot_token": "Token de bot", "form.integration.telegram_bot_token": "Token de bot",
"form.integration.telegram_chat_id": "ID de chat", "form.integration.telegram_chat_id": "ID de chat",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Enviar artículos a Linkding", "form.integration.linkding_activate": "Enviar artículos a Linkding",
"form.integration.linkding_endpoint": "Acceso API de Linkding", "form.integration.linkding_endpoint": "Acceso API de Linkding",
"form.integration.linkding_api_key": "Clave de API de Linkding", "form.integration.linkding_api_key": "Clave de API de Linkding",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Lähetä uusia artikkeleita Telegram-chatiin", "form.integration.telegram_bot_activate": "Lähetä uusia artikkeleita Telegram-chatiin",
"form.integration.telegram_bot_token": "Bot-tunnus", "form.integration.telegram_bot_token": "Bot-tunnus",
"form.integration.telegram_chat_id": "Chat ID", "form.integration.telegram_chat_id": "Chat ID",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Tallenna artikkelit Linkkiin", "form.integration.linkding_activate": "Tallenna artikkelit Linkkiin",
"form.integration.linkding_endpoint": "Linkding API-päätepiste", "form.integration.linkding_endpoint": "Linkding API-päätepiste",
"form.integration.linkding_api_key": "Linkding API-avain", "form.integration.linkding_api_key": "Linkding API-avain",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Envoyer les nouveaux articles vers Telegram", "form.integration.telegram_bot_activate": "Envoyer les nouveaux articles vers Telegram",
"form.integration.telegram_bot_token": "Jeton de sécurité de l'API du Bot Telegram", "form.integration.telegram_bot_token": "Jeton de sécurité de l'API du Bot Telegram",
"form.integration.telegram_chat_id": "Identifiant de discussion", "form.integration.telegram_chat_id": "Identifiant de discussion",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Désactiver l'aperçu de la page Web",
"form.integration.telegram_bot_disable_notification": "Désactiver les notifications",
"form.integration.linkding_activate": "Sauvegarder les articles vers Linkding", "form.integration.linkding_activate": "Sauvegarder les articles vers Linkding",
"form.integration.linkding_endpoint": "URL de l'API de Linkding", "form.integration.linkding_endpoint": "URL de l'API de Linkding",
"form.integration.linkding_api_key": "Clé d'API de Linkding", "form.integration.linkding_api_key": "Clé d'API de Linkding",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "टेलीग्राम चैट के लिए नई विषय-कविता पुश करें", "form.integration.telegram_bot_activate": "टेलीग्राम चैट के लिए नई विषय-कविता पुश करें",
"form.integration.telegram_bot_token": "बॉट टोकन", "form.integration.telegram_bot_token": "बॉट टोकन",
"form.integration.telegram_chat_id": "चैट आईडी", "form.integration.telegram_chat_id": "चैट आईडी",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "लिंक्डिन में विषयवस्तु सहेजें", "form.integration.linkding_activate": "लिंक्डिन में विषयवस्तु सहेजें",
"form.integration.linkding_endpoint": "लिंकिंग एपीआई समापन बिंदु", "form.integration.linkding_endpoint": "लिंकिंग एपीआई समापन बिंदु",
"form.integration.linkding_api_key": "लिंकिंग एपीआई कुंजी", "form.integration.linkding_api_key": "लिंकिंग एपीआई कुंजी",

View file

@ -369,6 +369,9 @@
"form.integration.telegram_bot_activate": "Kirim artikel baru ke percakapan Telegram", "form.integration.telegram_bot_activate": "Kirim artikel baru ke percakapan Telegram",
"form.integration.telegram_bot_token": "Token Bot", "form.integration.telegram_bot_token": "Token Bot",
"form.integration.telegram_chat_id": "ID Obrolan", "form.integration.telegram_chat_id": "ID Obrolan",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Simpan artikel ke Linkding", "form.integration.linkding_activate": "Simpan artikel ke Linkding",
"form.integration.linkding_endpoint": "Titik URL API Linkding", "form.integration.linkding_endpoint": "Titik URL API Linkding",
"form.integration.linkding_api_key": "Kunci API Linkding", "form.integration.linkding_api_key": "Kunci API Linkding",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Invia nuovi articoli alla chat di Telegram", "form.integration.telegram_bot_activate": "Invia nuovi articoli alla chat di Telegram",
"form.integration.telegram_bot_token": "Token bot", "form.integration.telegram_bot_token": "Token bot",
"form.integration.telegram_chat_id": "ID chat", "form.integration.telegram_chat_id": "ID chat",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Salva gli articoli su Linkding", "form.integration.linkding_activate": "Salva gli articoli su Linkding",
"form.integration.linkding_endpoint": "Endpoint dell'API di Linkding", "form.integration.linkding_endpoint": "Endpoint dell'API di Linkding",
"form.integration.linkding_api_key": "API key dell'account Linkding", "form.integration.linkding_api_key": "API key dell'account Linkding",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "新しい記事を Telegram チャットにプッシュする", "form.integration.telegram_bot_activate": "新しい記事を Telegram チャットにプッシュする",
"form.integration.telegram_bot_token": "ボットトークン", "form.integration.telegram_bot_token": "ボットトークン",
"form.integration.telegram_chat_id": "チャット ID", "form.integration.telegram_chat_id": "チャット ID",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Linkding に記事を保存する", "form.integration.linkding_activate": "Linkding に記事を保存する",
"form.integration.linkding_endpoint": "Linkding の API Endpoint", "form.integration.linkding_endpoint": "Linkding の API Endpoint",
"form.integration.linkding_api_key": "Linkding の API key", "form.integration.linkding_api_key": "Linkding の API key",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Push nieuwe artikelen naar Telegram-chat", "form.integration.telegram_bot_activate": "Push nieuwe artikelen naar Telegram-chat",
"form.integration.telegram_bot_token": "Bot token", "form.integration.telegram_bot_token": "Bot token",
"form.integration.telegram_chat_id": "Chat ID", "form.integration.telegram_chat_id": "Chat ID",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Opslaan naar Linkding", "form.integration.linkding_activate": "Opslaan naar Linkding",
"form.integration.linkding_endpoint": "Linkding URL", "form.integration.linkding_endpoint": "Linkding URL",
"form.integration.linkding_api_key": "Linkding API-sleutel", "form.integration.linkding_api_key": "Linkding API-sleutel",

View file

@ -374,6 +374,9 @@
"form.integration.telegram_bot_activate": "Przesyłaj nowe artykuły do czatu Telegram", "form.integration.telegram_bot_activate": "Przesyłaj nowe artykuły do czatu Telegram",
"form.integration.telegram_bot_token": "Token bota", "form.integration.telegram_bot_token": "Token bota",
"form.integration.telegram_chat_id": "Identyfikator czatu", "form.integration.telegram_chat_id": "Identyfikator czatu",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Zapisz artykuły do Linkding", "form.integration.linkding_activate": "Zapisz artykuły do Linkding",
"form.integration.linkding_endpoint": "Linkding URL", "form.integration.linkding_endpoint": "Linkding URL",
"form.integration.linkding_api_key": "Linkding API key", "form.integration.linkding_api_key": "Linkding API key",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Envie novos artigos para o chat do Telegram", "form.integration.telegram_bot_activate": "Envie novos artigos para o chat do Telegram",
"form.integration.telegram_bot_token": "Token de bot", "form.integration.telegram_bot_token": "Token de bot",
"form.integration.telegram_chat_id": "ID de bate-papo", "form.integration.telegram_chat_id": "ID de bate-papo",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Salvar itens no Linkding", "form.integration.linkding_activate": "Salvar itens no Linkding",
"form.integration.linkding_endpoint": "Endpoint de API do Linkding", "form.integration.linkding_endpoint": "Endpoint de API do Linkding",
"form.integration.linkding_api_key": "Chave de API do Linkding", "form.integration.linkding_api_key": "Chave de API do Linkding",

View file

@ -374,6 +374,9 @@
"form.integration.telegram_bot_activate": "Репостить новые статьи в Telegram-чат", "form.integration.telegram_bot_activate": "Репостить новые статьи в Telegram-чат",
"form.integration.telegram_bot_token": "Токен бота", "form.integration.telegram_bot_token": "Токен бота",
"form.integration.telegram_chat_id": "ID чата", "form.integration.telegram_chat_id": "ID чата",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Сохранять статьи в Linkding", "form.integration.linkding_activate": "Сохранять статьи в Linkding",
"form.integration.linkding_endpoint": "Конечная точка Linkding API", "form.integration.linkding_endpoint": "Конечная точка Linkding API",
"form.integration.linkding_api_key": "API-ключ Linkding", "form.integration.linkding_api_key": "API-ключ Linkding",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "Yeni makaleleri Telegram sohbetine gönderin", "form.integration.telegram_bot_activate": "Yeni makaleleri Telegram sohbetine gönderin",
"form.integration.telegram_bot_token": "Bot jetonu", "form.integration.telegram_bot_token": "Bot jetonu",
"form.integration.telegram_chat_id": "Sohbet kimliği", "form.integration.telegram_chat_id": "Sohbet kimliği",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "Makaleleri Linkding'e kaydet", "form.integration.linkding_activate": "Makaleleri Linkding'e kaydet",
"form.integration.linkding_endpoint": "Linkding API Uç Noktası", "form.integration.linkding_endpoint": "Linkding API Uç Noktası",
"form.integration.linkding_api_key": "Linkding API Anahtarı", "form.integration.linkding_api_key": "Linkding API Anahtarı",

View file

@ -374,6 +374,9 @@
"form.integration.readwise_api_key_link": "Get your Readwise Access Token", "form.integration.readwise_api_key_link": "Get your Readwise Access Token",
"form.integration.telegram_bot_activate": "Відправляти нові статті до чату Telegram", "form.integration.telegram_bot_activate": "Відправляти нові статті до чату Telegram",
"form.integration.telegram_bot_token": "Токен боту", "form.integration.telegram_bot_token": "Токен боту",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.telegram_chat_id": "ID чату", "form.integration.telegram_chat_id": "ID чату",
"form.integration.linkding_activate": "Зберігати статті до Linkding", "form.integration.linkding_activate": "Зберігати статті до Linkding",
"form.integration.linkding_endpoint": "Linkding API Endpoint", "form.integration.linkding_endpoint": "Linkding API Endpoint",

View file

@ -369,6 +369,9 @@
"form.integration.readwise_api_key_link": "Get your Readwise Access Token", "form.integration.readwise_api_key_link": "Get your Readwise Access Token",
"form.integration.telegram_bot_activate": "将新文章推送到 Telegram", "form.integration.telegram_bot_activate": "将新文章推送到 Telegram",
"form.integration.telegram_bot_token": "机器人令牌", "form.integration.telegram_bot_token": "机器人令牌",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.telegram_chat_id": "聊天ID", "form.integration.telegram_chat_id": "聊天ID",
"form.integration.linkding_activate": "保存文章到 Linkding", "form.integration.linkding_activate": "保存文章到 Linkding",
"form.integration.linkding_endpoint": "Linkding API 端点", "form.integration.linkding_endpoint": "Linkding API 端点",

View file

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "將新文章推送到 Telegram", "form.integration.telegram_bot_activate": "將新文章推送到 Telegram",
"form.integration.telegram_bot_token": "Bot token", "form.integration.telegram_bot_token": "Bot token",
"form.integration.telegram_chat_id": "Chat ID", "form.integration.telegram_chat_id": "Chat ID",
"form.integration.telegram_topic_id": "Topic ID",
"form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview",
"form.integration.telegram_bot_disable_notification": "Disable notification",
"form.integration.linkding_activate": "儲存文章到 Linkding", "form.integration.linkding_activate": "儲存文章到 Linkding",
"form.integration.linkding_endpoint": "Linkding API 端點", "form.integration.linkding_endpoint": "Linkding API 端點",
"form.integration.linkding_api_key": "Linkding API 金鑰", "form.integration.linkding_api_key": "Linkding API 金鑰",

View file

@ -5,66 +5,69 @@ package model // import "miniflux.app/v2/internal/model"
// Integration represents user integration settings. // Integration represents user integration settings.
type Integration struct { type Integration struct {
UserID int64 UserID int64
PinboardEnabled bool PinboardEnabled bool
PinboardToken string PinboardToken string
PinboardTags string PinboardTags string
PinboardMarkAsUnread bool PinboardMarkAsUnread bool
InstapaperEnabled bool InstapaperEnabled bool
InstapaperUsername string InstapaperUsername string
InstapaperPassword string InstapaperPassword string
FeverEnabled bool FeverEnabled bool
FeverUsername string FeverUsername string
FeverToken string FeverToken string
GoogleReaderEnabled bool GoogleReaderEnabled bool
GoogleReaderUsername string GoogleReaderUsername string
GoogleReaderPassword string GoogleReaderPassword string
WallabagEnabled bool WallabagEnabled bool
WallabagOnlyURL bool WallabagOnlyURL bool
WallabagURL string WallabagURL string
WallabagClientID string WallabagClientID string
WallabagClientSecret string WallabagClientSecret string
WallabagUsername string WallabagUsername string
WallabagPassword string WallabagPassword string
NunuxKeeperEnabled bool NunuxKeeperEnabled bool
NunuxKeeperURL string NunuxKeeperURL string
NunuxKeeperAPIKey string NunuxKeeperAPIKey string
NotionEnabled bool NotionEnabled bool
NotionToken string NotionToken string
NotionPageID string NotionPageID string
EspialEnabled bool EspialEnabled bool
EspialURL string EspialURL string
EspialAPIKey string EspialAPIKey string
EspialTags string EspialTags string
ReadwiseEnabled bool ReadwiseEnabled bool
ReadwiseAPIKey string ReadwiseAPIKey string
PocketEnabled bool PocketEnabled bool
PocketAccessToken string PocketAccessToken string
PocketConsumerKey string PocketConsumerKey string
TelegramBotEnabled bool TelegramBotEnabled bool
TelegramBotToken string TelegramBotToken string
TelegramBotChatID string TelegramBotChatID string
LinkdingEnabled bool TelegramBotTopicID *int64
LinkdingURL string TelegramBotDisableWebPagePreview bool
LinkdingAPIKey string TelegramBotDisableNotification bool
LinkdingTags string LinkdingEnabled bool
LinkdingMarkAsUnread bool LinkdingURL string
MatrixBotEnabled bool LinkdingAPIKey string
MatrixBotUser string LinkdingTags string
MatrixBotPassword string LinkdingMarkAsUnread bool
MatrixBotURL string MatrixBotEnabled bool
MatrixBotChatID string MatrixBotUser string
AppriseEnabled bool MatrixBotPassword string
AppriseURL string MatrixBotURL string
AppriseServicesURL string MatrixBotChatID string
ShioriEnabled bool AppriseEnabled bool
ShioriURL string AppriseURL string
ShioriUsername string AppriseServicesURL string
ShioriPassword string ShioriEnabled bool
ShaarliEnabled bool ShioriURL string
ShaarliURL string ShioriUsername string
ShaarliAPISecret string ShioriPassword string
WebhookEnabled bool ShaarliEnabled bool
WebhookURL string ShaarliURL string
WebhookSecret string ShaarliAPISecret string
WebhookEnabled bool
WebhookURL string
WebhookSecret string
} }

View file

@ -148,6 +148,9 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
telegram_bot_enabled, telegram_bot_enabled,
telegram_bot_token, telegram_bot_token,
telegram_bot_chat_id, telegram_bot_chat_id,
telegram_bot_topic_id,
telegram_bot_disable_web_page_preview,
telegram_bot_disable_notification,
linkding_enabled, linkding_enabled,
linkding_url, linkding_url,
linkding_api_key, linkding_api_key,
@ -217,6 +220,9 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
&integration.TelegramBotEnabled, &integration.TelegramBotEnabled,
&integration.TelegramBotToken, &integration.TelegramBotToken,
&integration.TelegramBotChatID, &integration.TelegramBotChatID,
&integration.TelegramBotTopicID,
&integration.TelegramBotDisableWebPagePreview,
&integration.TelegramBotDisableNotification,
&integration.LinkdingEnabled, &integration.LinkdingEnabled,
&integration.LinkdingURL, &integration.LinkdingURL,
&integration.LinkdingAPIKey, &integration.LinkdingAPIKey,
@ -286,40 +292,43 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
telegram_bot_enabled=$27, telegram_bot_enabled=$27,
telegram_bot_token=$28, telegram_bot_token=$28,
telegram_bot_chat_id=$29, telegram_bot_chat_id=$29,
espial_enabled=$30, telegram_bot_topic_id=$30,
espial_url=$31, telegram_bot_disable_web_page_preview=$31,
espial_api_key=$32, telegram_bot_disable_notification=$32,
espial_tags=$33, espial_enabled=$33,
linkding_enabled=$34, espial_url=$34,
linkding_url=$35, espial_api_key=$35,
linkding_api_key=$36, espial_tags=$36,
linkding_tags=$37, linkding_enabled=$37,
linkding_mark_as_unread=$38, linkding_url=$38,
matrix_bot_enabled=$39, linkding_api_key=$39,
matrix_bot_user=$40, linkding_tags=$40,
matrix_bot_password=$41, linkding_mark_as_unread=$41,
matrix_bot_url=$42, matrix_bot_enabled=$42,
matrix_bot_chat_id=$43, matrix_bot_user=$43,
notion_enabled=$44, matrix_bot_password=$44,
notion_token=$45, matrix_bot_url=$45,
notion_page_id=$46, matrix_bot_chat_id=$46,
readwise_enabled=$47, notion_enabled=$47,
readwise_api_key=$48, notion_token=$48,
apprise_enabled=$49, notion_page_id=$49,
apprise_url=$50, readwise_enabled=$50,
apprise_services_url=$51, readwise_api_key=$51,
shiori_enabled=$52, apprise_enabled=$52,
shiori_url=$53, apprise_url=$53,
shiori_username=$54, apprise_services_url=$54,
shiori_password=$55, shiori_enabled=$55,
shaarli_enabled=$56, shiori_url=$56,
shaarli_url=$57, shiori_username=$57,
shaarli_api_secret=$58, shiori_password=$58,
webhook_enabled=$59, shaarli_enabled=$59,
webhook_url=$60, shaarli_url=$60,
webhook_secret=$61 shaarli_api_secret=$61,
webhook_enabled=$62,
webhook_url=$63,
webhook_secret=$64
WHERE WHERE
user_id=$62 user_id=$65
` `
_, err := s.db.Exec( _, err := s.db.Exec(
query, query,
@ -352,6 +361,9 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
integration.TelegramBotEnabled, integration.TelegramBotEnabled,
integration.TelegramBotToken, integration.TelegramBotToken,
integration.TelegramBotChatID, integration.TelegramBotChatID,
integration.TelegramBotTopicID,
integration.TelegramBotDisableWebPagePreview,
integration.TelegramBotDisableNotification,
integration.EspialEnabled, integration.EspialEnabled,
integration.EspialURL, integration.EspialURL,
integration.EspialAPIKey, integration.EspialAPIKey,

View file

@ -328,6 +328,17 @@
<label for="form-telegram-chat-id">{{ t "form.integration.telegram_chat_id" }}</label> <label for="form-telegram-chat-id">{{ t "form.integration.telegram_chat_id" }}</label>
<input type="text" name="telegram_bot_chat_id" id="form-telegram-chat-id" value="{{ .form.TelegramBotChatID }}" spellcheck="false"> <input type="text" name="telegram_bot_chat_id" id="form-telegram-chat-id" value="{{ .form.TelegramBotChatID }}" spellcheck="false">
<label for="form-telegram-topic-id">{{ t "form.integration.telegram_topic_id" }}</label>
<input type="number" name="telegram_bot_topic_id" id="form-telegram-topic-id" {{ if .form.TelegramBotTopicID }}value="{{ .form.TelegramBotTopicID }}"{{ end }}>
<label>
<input type="checkbox" name="telegram_bot_disable_web_page_preview" value="1" {{ if .form.TelegramBotDisableWebPagePreview }}checked{{ end }}> {{ t "form.integration.telegram_bot_disable_web_page_preview" }}
</label>
<label>
<input type="checkbox" name="telegram_bot_disable_notification" value="1" {{ if .form.TelegramBotDisableNotification }}checked{{ end }}> {{ t "form.integration.telegram_bot_disable_notification" }}
</label>
<div class="buttons"> <div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button> <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div> </div>

View file

@ -5,73 +5,77 @@ package form // import "miniflux.app/v2/internal/ui/form"
import ( import (
"net/http" "net/http"
"strconv"
"miniflux.app/v2/internal/model" "miniflux.app/v2/internal/model"
) )
// IntegrationForm represents user integration settings form. // IntegrationForm represents user integration settings form.
type IntegrationForm struct { type IntegrationForm struct {
PinboardEnabled bool PinboardEnabled bool
PinboardToken string PinboardToken string
PinboardTags string PinboardTags string
PinboardMarkAsUnread bool PinboardMarkAsUnread bool
InstapaperEnabled bool InstapaperEnabled bool
InstapaperUsername string InstapaperUsername string
InstapaperPassword string InstapaperPassword string
FeverEnabled bool FeverEnabled bool
FeverUsername string FeverUsername string
FeverPassword string FeverPassword string
GoogleReaderEnabled bool GoogleReaderEnabled bool
GoogleReaderUsername string GoogleReaderUsername string
GoogleReaderPassword string GoogleReaderPassword string
WallabagEnabled bool WallabagEnabled bool
WallabagOnlyURL bool WallabagOnlyURL bool
WallabagURL string WallabagURL string
WallabagClientID string WallabagClientID string
WallabagClientSecret string WallabagClientSecret string
WallabagUsername string WallabagUsername string
WallabagPassword string WallabagPassword string
NotionEnabled bool NotionEnabled bool
NotionPageID string NotionPageID string
NotionToken string NotionToken string
NunuxKeeperEnabled bool NunuxKeeperEnabled bool
NunuxKeeperURL string NunuxKeeperURL string
NunuxKeeperAPIKey string NunuxKeeperAPIKey string
EspialEnabled bool EspialEnabled bool
EspialURL string EspialURL string
EspialAPIKey string EspialAPIKey string
EspialTags string EspialTags string
ReadwiseEnabled bool ReadwiseEnabled bool
ReadwiseAPIKey string ReadwiseAPIKey string
PocketEnabled bool PocketEnabled bool
PocketAccessToken string PocketAccessToken string
PocketConsumerKey string PocketConsumerKey string
TelegramBotEnabled bool TelegramBotEnabled bool
TelegramBotToken string TelegramBotToken string
TelegramBotChatID string TelegramBotChatID string
LinkdingEnabled bool TelegramBotTopicID *int64
LinkdingURL string TelegramBotDisableWebPagePreview bool
LinkdingAPIKey string TelegramBotDisableNotification bool
LinkdingTags string LinkdingEnabled bool
LinkdingMarkAsUnread bool LinkdingURL string
MatrixBotEnabled bool LinkdingAPIKey string
MatrixBotUser string LinkdingTags string
MatrixBotPassword string LinkdingMarkAsUnread bool
MatrixBotURL string MatrixBotEnabled bool
MatrixBotChatID string MatrixBotUser string
AppriseEnabled bool MatrixBotPassword string
AppriseURL string MatrixBotURL string
AppriseServicesURL string MatrixBotChatID string
ShioriEnabled bool AppriseEnabled bool
ShioriURL string AppriseURL string
ShioriUsername string AppriseServicesURL string
ShioriPassword string ShioriEnabled bool
ShaarliEnabled bool ShioriURL string
ShaarliURL string ShioriUsername string
ShaarliAPISecret string ShioriPassword string
WebhookEnabled bool ShaarliEnabled bool
WebhookURL string ShaarliURL string
WebhookSecret string ShaarliAPISecret string
WebhookEnabled bool
WebhookURL string
WebhookSecret string
} }
// Merge copy form values to the model. // Merge copy form values to the model.
@ -112,6 +116,9 @@ func (i IntegrationForm) Merge(integration *model.Integration) {
integration.TelegramBotEnabled = i.TelegramBotEnabled integration.TelegramBotEnabled = i.TelegramBotEnabled
integration.TelegramBotToken = i.TelegramBotToken integration.TelegramBotToken = i.TelegramBotToken
integration.TelegramBotChatID = i.TelegramBotChatID integration.TelegramBotChatID = i.TelegramBotChatID
integration.TelegramBotTopicID = i.TelegramBotTopicID
integration.TelegramBotDisableWebPagePreview = i.TelegramBotDisableWebPagePreview
integration.TelegramBotDisableNotification = i.TelegramBotDisableNotification
integration.LinkdingEnabled = i.LinkdingEnabled integration.LinkdingEnabled = i.LinkdingEnabled
integration.LinkdingURL = i.LinkdingURL integration.LinkdingURL = i.LinkdingURL
integration.LinkdingAPIKey = i.LinkdingAPIKey integration.LinkdingAPIKey = i.LinkdingAPIKey
@ -139,65 +146,76 @@ func (i IntegrationForm) Merge(integration *model.Integration) {
// NewIntegrationForm returns a new IntegrationForm. // NewIntegrationForm returns a new IntegrationForm.
func NewIntegrationForm(r *http.Request) *IntegrationForm { func NewIntegrationForm(r *http.Request) *IntegrationForm {
return &IntegrationForm{ return &IntegrationForm{
PinboardEnabled: r.FormValue("pinboard_enabled") == "1", PinboardEnabled: r.FormValue("pinboard_enabled") == "1",
PinboardToken: r.FormValue("pinboard_token"), PinboardToken: r.FormValue("pinboard_token"),
PinboardTags: r.FormValue("pinboard_tags"), PinboardTags: r.FormValue("pinboard_tags"),
PinboardMarkAsUnread: r.FormValue("pinboard_mark_as_unread") == "1", PinboardMarkAsUnread: r.FormValue("pinboard_mark_as_unread") == "1",
InstapaperEnabled: r.FormValue("instapaper_enabled") == "1", InstapaperEnabled: r.FormValue("instapaper_enabled") == "1",
InstapaperUsername: r.FormValue("instapaper_username"), InstapaperUsername: r.FormValue("instapaper_username"),
InstapaperPassword: r.FormValue("instapaper_password"), InstapaperPassword: r.FormValue("instapaper_password"),
FeverEnabled: r.FormValue("fever_enabled") == "1", FeverEnabled: r.FormValue("fever_enabled") == "1",
FeverUsername: r.FormValue("fever_username"), FeverUsername: r.FormValue("fever_username"),
FeverPassword: r.FormValue("fever_password"), FeverPassword: r.FormValue("fever_password"),
GoogleReaderEnabled: r.FormValue("googlereader_enabled") == "1", GoogleReaderEnabled: r.FormValue("googlereader_enabled") == "1",
GoogleReaderUsername: r.FormValue("googlereader_username"), GoogleReaderUsername: r.FormValue("googlereader_username"),
GoogleReaderPassword: r.FormValue("googlereader_password"), GoogleReaderPassword: r.FormValue("googlereader_password"),
WallabagEnabled: r.FormValue("wallabag_enabled") == "1", WallabagEnabled: r.FormValue("wallabag_enabled") == "1",
WallabagOnlyURL: r.FormValue("wallabag_only_url") == "1", WallabagOnlyURL: r.FormValue("wallabag_only_url") == "1",
WallabagURL: r.FormValue("wallabag_url"), WallabagURL: r.FormValue("wallabag_url"),
WallabagClientID: r.FormValue("wallabag_client_id"), WallabagClientID: r.FormValue("wallabag_client_id"),
WallabagClientSecret: r.FormValue("wallabag_client_secret"), WallabagClientSecret: r.FormValue("wallabag_client_secret"),
WallabagUsername: r.FormValue("wallabag_username"), WallabagUsername: r.FormValue("wallabag_username"),
WallabagPassword: r.FormValue("wallabag_password"), WallabagPassword: r.FormValue("wallabag_password"),
NotionEnabled: r.FormValue("notion_enabled") == "1", NotionEnabled: r.FormValue("notion_enabled") == "1",
NotionPageID: r.FormValue("notion_page_id"), NotionPageID: r.FormValue("notion_page_id"),
NotionToken: r.FormValue("notion_token"), NotionToken: r.FormValue("notion_token"),
NunuxKeeperEnabled: r.FormValue("nunux_keeper_enabled") == "1", NunuxKeeperEnabled: r.FormValue("nunux_keeper_enabled") == "1",
NunuxKeeperURL: r.FormValue("nunux_keeper_url"), NunuxKeeperURL: r.FormValue("nunux_keeper_url"),
NunuxKeeperAPIKey: r.FormValue("nunux_keeper_api_key"), NunuxKeeperAPIKey: r.FormValue("nunux_keeper_api_key"),
EspialEnabled: r.FormValue("espial_enabled") == "1", EspialEnabled: r.FormValue("espial_enabled") == "1",
EspialURL: r.FormValue("espial_url"), EspialURL: r.FormValue("espial_url"),
EspialAPIKey: r.FormValue("espial_api_key"), EspialAPIKey: r.FormValue("espial_api_key"),
EspialTags: r.FormValue("espial_tags"), EspialTags: r.FormValue("espial_tags"),
ReadwiseEnabled: r.FormValue("readwise_enabled") == "1", ReadwiseEnabled: r.FormValue("readwise_enabled") == "1",
ReadwiseAPIKey: r.FormValue("readwise_api_key"), ReadwiseAPIKey: r.FormValue("readwise_api_key"),
PocketEnabled: r.FormValue("pocket_enabled") == "1", PocketEnabled: r.FormValue("pocket_enabled") == "1",
PocketAccessToken: r.FormValue("pocket_access_token"), PocketAccessToken: r.FormValue("pocket_access_token"),
PocketConsumerKey: r.FormValue("pocket_consumer_key"), PocketConsumerKey: r.FormValue("pocket_consumer_key"),
TelegramBotEnabled: r.FormValue("telegram_bot_enabled") == "1", TelegramBotEnabled: r.FormValue("telegram_bot_enabled") == "1",
TelegramBotToken: r.FormValue("telegram_bot_token"), TelegramBotToken: r.FormValue("telegram_bot_token"),
TelegramBotChatID: r.FormValue("telegram_bot_chat_id"), TelegramBotChatID: r.FormValue("telegram_bot_chat_id"),
LinkdingEnabled: r.FormValue("linkding_enabled") == "1", TelegramBotTopicID: optionalInt64Field(r.FormValue("telegram_bot_topic_id")),
LinkdingURL: r.FormValue("linkding_url"), TelegramBotDisableWebPagePreview: r.FormValue("telegram_bot_disable_web_page_preview") == "1",
LinkdingAPIKey: r.FormValue("linkding_api_key"), TelegramBotDisableNotification: r.FormValue("telegram_bot_disable_notification") == "1",
LinkdingTags: r.FormValue("linkding_tags"), LinkdingEnabled: r.FormValue("linkding_enabled") == "1",
LinkdingMarkAsUnread: r.FormValue("linkding_mark_as_unread") == "1", LinkdingURL: r.FormValue("linkding_url"),
MatrixBotEnabled: r.FormValue("matrix_bot_enabled") == "1", LinkdingAPIKey: r.FormValue("linkding_api_key"),
MatrixBotUser: r.FormValue("matrix_bot_user"), LinkdingTags: r.FormValue("linkding_tags"),
MatrixBotPassword: r.FormValue("matrix_bot_password"), LinkdingMarkAsUnread: r.FormValue("linkding_mark_as_unread") == "1",
MatrixBotURL: r.FormValue("matrix_bot_url"), MatrixBotEnabled: r.FormValue("matrix_bot_enabled") == "1",
MatrixBotChatID: r.FormValue("matrix_bot_chat_id"), MatrixBotUser: r.FormValue("matrix_bot_user"),
AppriseEnabled: r.FormValue("apprise_enabled") == "1", MatrixBotPassword: r.FormValue("matrix_bot_password"),
AppriseURL: r.FormValue("apprise_url"), MatrixBotURL: r.FormValue("matrix_bot_url"),
AppriseServicesURL: r.FormValue("apprise_services_url"), MatrixBotChatID: r.FormValue("matrix_bot_chat_id"),
ShioriEnabled: r.FormValue("shiori_enabled") == "1", AppriseEnabled: r.FormValue("apprise_enabled") == "1",
ShioriURL: r.FormValue("shiori_url"), AppriseURL: r.FormValue("apprise_url"),
ShioriUsername: r.FormValue("shiori_username"), AppriseServicesURL: r.FormValue("apprise_services_url"),
ShioriPassword: r.FormValue("shiori_password"), ShioriEnabled: r.FormValue("shiori_enabled") == "1",
ShaarliEnabled: r.FormValue("shaarli_enabled") == "1", ShioriURL: r.FormValue("shiori_url"),
ShaarliURL: r.FormValue("shaarli_url"), ShioriUsername: r.FormValue("shiori_username"),
ShaarliAPISecret: r.FormValue("shaarli_api_secret"), ShioriPassword: r.FormValue("shiori_password"),
WebhookEnabled: r.FormValue("webhook_enabled") == "1", ShaarliEnabled: r.FormValue("shaarli_enabled") == "1",
WebhookURL: r.FormValue("webhook_url"), ShaarliURL: r.FormValue("shaarli_url"),
ShaarliAPISecret: r.FormValue("shaarli_api_secret"),
WebhookEnabled: r.FormValue("webhook_enabled") == "1",
WebhookURL: r.FormValue("webhook_url"),
} }
} }
func optionalInt64Field(formValue string) *int64 {
if formValue == "" {
return nil
}
value, _ := strconv.ParseInt(formValue, 10, 64)
return &value
}

View file

@ -28,65 +28,68 @@ func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) {
} }
integrationForm := form.IntegrationForm{ integrationForm := form.IntegrationForm{
PinboardEnabled: integration.PinboardEnabled, PinboardEnabled: integration.PinboardEnabled,
PinboardToken: integration.PinboardToken, PinboardToken: integration.PinboardToken,
PinboardTags: integration.PinboardTags, PinboardTags: integration.PinboardTags,
PinboardMarkAsUnread: integration.PinboardMarkAsUnread, PinboardMarkAsUnread: integration.PinboardMarkAsUnread,
InstapaperEnabled: integration.InstapaperEnabled, InstapaperEnabled: integration.InstapaperEnabled,
InstapaperUsername: integration.InstapaperUsername, InstapaperUsername: integration.InstapaperUsername,
InstapaperPassword: integration.InstapaperPassword, InstapaperPassword: integration.InstapaperPassword,
FeverEnabled: integration.FeverEnabled, FeverEnabled: integration.FeverEnabled,
FeverUsername: integration.FeverUsername, FeverUsername: integration.FeverUsername,
GoogleReaderEnabled: integration.GoogleReaderEnabled, GoogleReaderEnabled: integration.GoogleReaderEnabled,
GoogleReaderUsername: integration.GoogleReaderUsername, GoogleReaderUsername: integration.GoogleReaderUsername,
WallabagEnabled: integration.WallabagEnabled, WallabagEnabled: integration.WallabagEnabled,
WallabagOnlyURL: integration.WallabagOnlyURL, WallabagOnlyURL: integration.WallabagOnlyURL,
WallabagURL: integration.WallabagURL, WallabagURL: integration.WallabagURL,
WallabagClientID: integration.WallabagClientID, WallabagClientID: integration.WallabagClientID,
WallabagClientSecret: integration.WallabagClientSecret, WallabagClientSecret: integration.WallabagClientSecret,
WallabagUsername: integration.WallabagUsername, WallabagUsername: integration.WallabagUsername,
WallabagPassword: integration.WallabagPassword, WallabagPassword: integration.WallabagPassword,
NotionEnabled: integration.NotionEnabled, NotionEnabled: integration.NotionEnabled,
NotionPageID: integration.NotionPageID, NotionPageID: integration.NotionPageID,
NotionToken: integration.NotionToken, NotionToken: integration.NotionToken,
NunuxKeeperEnabled: integration.NunuxKeeperEnabled, NunuxKeeperEnabled: integration.NunuxKeeperEnabled,
NunuxKeeperURL: integration.NunuxKeeperURL, NunuxKeeperURL: integration.NunuxKeeperURL,
NunuxKeeperAPIKey: integration.NunuxKeeperAPIKey, NunuxKeeperAPIKey: integration.NunuxKeeperAPIKey,
EspialEnabled: integration.EspialEnabled, EspialEnabled: integration.EspialEnabled,
EspialURL: integration.EspialURL, EspialURL: integration.EspialURL,
EspialAPIKey: integration.EspialAPIKey, EspialAPIKey: integration.EspialAPIKey,
EspialTags: integration.EspialTags, EspialTags: integration.EspialTags,
ReadwiseEnabled: integration.ReadwiseEnabled, ReadwiseEnabled: integration.ReadwiseEnabled,
ReadwiseAPIKey: integration.ReadwiseAPIKey, ReadwiseAPIKey: integration.ReadwiseAPIKey,
PocketEnabled: integration.PocketEnabled, PocketEnabled: integration.PocketEnabled,
PocketAccessToken: integration.PocketAccessToken, PocketAccessToken: integration.PocketAccessToken,
PocketConsumerKey: integration.PocketConsumerKey, PocketConsumerKey: integration.PocketConsumerKey,
TelegramBotEnabled: integration.TelegramBotEnabled, TelegramBotEnabled: integration.TelegramBotEnabled,
TelegramBotToken: integration.TelegramBotToken, TelegramBotToken: integration.TelegramBotToken,
TelegramBotChatID: integration.TelegramBotChatID, TelegramBotChatID: integration.TelegramBotChatID,
LinkdingEnabled: integration.LinkdingEnabled, TelegramBotTopicID: integration.TelegramBotTopicID,
LinkdingURL: integration.LinkdingURL, TelegramBotDisableWebPagePreview: integration.TelegramBotDisableWebPagePreview,
LinkdingAPIKey: integration.LinkdingAPIKey, TelegramBotDisableNotification: integration.TelegramBotDisableNotification,
LinkdingTags: integration.LinkdingTags, LinkdingEnabled: integration.LinkdingEnabled,
LinkdingMarkAsUnread: integration.LinkdingMarkAsUnread, LinkdingURL: integration.LinkdingURL,
MatrixBotEnabled: integration.MatrixBotEnabled, LinkdingAPIKey: integration.LinkdingAPIKey,
MatrixBotUser: integration.MatrixBotUser, LinkdingTags: integration.LinkdingTags,
MatrixBotPassword: integration.MatrixBotPassword, LinkdingMarkAsUnread: integration.LinkdingMarkAsUnread,
MatrixBotURL: integration.MatrixBotURL, MatrixBotEnabled: integration.MatrixBotEnabled,
MatrixBotChatID: integration.MatrixBotChatID, MatrixBotUser: integration.MatrixBotUser,
AppriseEnabled: integration.AppriseEnabled, MatrixBotPassword: integration.MatrixBotPassword,
AppriseURL: integration.AppriseURL, MatrixBotURL: integration.MatrixBotURL,
AppriseServicesURL: integration.AppriseServicesURL, MatrixBotChatID: integration.MatrixBotChatID,
ShioriEnabled: integration.ShioriEnabled, AppriseEnabled: integration.AppriseEnabled,
ShioriURL: integration.ShioriURL, AppriseURL: integration.AppriseURL,
ShioriUsername: integration.ShioriUsername, AppriseServicesURL: integration.AppriseServicesURL,
ShioriPassword: integration.ShioriPassword, ShioriEnabled: integration.ShioriEnabled,
ShaarliEnabled: integration.ShaarliEnabled, ShioriURL: integration.ShioriURL,
ShaarliURL: integration.ShaarliURL, ShioriUsername: integration.ShioriUsername,
ShaarliAPISecret: integration.ShaarliAPISecret, ShioriPassword: integration.ShioriPassword,
WebhookEnabled: integration.WebhookEnabled, ShaarliEnabled: integration.ShaarliEnabled,
WebhookURL: integration.WebhookURL, ShaarliURL: integration.ShaarliURL,
WebhookSecret: integration.WebhookSecret, ShaarliAPISecret: integration.ShaarliAPISecret,
WebhookEnabled: integration.WebhookEnabled,
WebhookURL: integration.WebhookURL,
WebhookSecret: integration.WebhookSecret,
} }
sess := session.New(h.store, request.SessionID(r)) sess := session.New(h.store, request.SessionID(r))