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 (
github.com/PuerkitoBio/goquery v1.8.1
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/lib/pq v1.10.9
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/procfs v0.10.1 // 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/text v0.12.0 // 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/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-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.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0=
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.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA=
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)
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.
func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *model.Integration) {
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)
if err != nil {
@ -193,16 +193,23 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode
if userIntegrations.TelegramBotEnabled || userIntegrations.AppriseEnabled {
for _, entry := range entries {
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 != nil {
logger.Error("[Integration] push entry to telegram bot failed: %v", err)
if err := telegrambot.PushEntry(
feed,
entry,
userIntegrations.TelegramBotToken,
userIntegrations.TelegramBotChatID,
userIntegrations.TelegramBotTopicID,
userIntegrations.TelegramBotDisableWebPagePreview,
userIntegrations.TelegramBotDisableNotification,
); err != nil {
logger.Error("[Integration] %v", err)
}
}
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
if feed.AppriseServiceURLs != "" {
@ -215,7 +222,7 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode
)
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"
import (
"bytes"
"fmt"
"html/template"
"strconv"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
"miniflux.app/v2/internal/model"
)
// PushEntry pushes entry to telegram chat using integration settings provided
func PushEntry(entry *model.Entry, botToken, chatID string) error {
bot, err := tgbotapi.NewBotAPI(botToken)
if err != nil {
return fmt.Errorf("telegrambot: bot creation failed: %w", err)
func PushEntry(feed *model.Feed, entry *model.Entry, botToken, chatID string, topicID *int64, disableWebPagePreview, disableNotification bool) error {
textTemplate := `<b><a href=%q>%s</a></b> - <a href=%q>%s</a>`
formattedText := fmt.Sprintf(
textTemplate,
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 err != nil {
return fmt.Errorf("telegrambot: template parsing failed: %w", err)
if topicID != nil {
message.MessageThreadID = *topicID
}
var result bytes.Buffer
if err := tpl.Execute(&result, entry); err != nil {
return fmt.Errorf("telegrambot: template execution failed: %w", err)
}
var markupRow []*InlineKeyboardButton
chatIDInt, _ := strconv.ParseInt(chatID, 10, 64)
msg := tgbotapi.NewMessage(chatIDInt, result.String())
msg.ParseMode = tgbotapi.ModeHTML
msg.DisableWebPagePreview = false
minifluxURLButton := InlineKeyboardButton{Text: "Go to article", URL: entry.URL}
markupRow = append(markupRow, &minifluxURLButton)
if entry.CommentsURL != "" {
msg.ReplyMarkup = tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonURL("Comments", entry.CommentsURL),
))
commentButton := InlineKeyboardButton{Text: "Comments", URL: entry.CommentsURL}
markupRow = append(markupRow, &commentButton)
}
if _, err := bot.Send(msg); err != nil {
return fmt.Errorf("telegrambot: sending message failed: %w", err)
}
message.ReplyMarkup = &InlineKeyboard{}
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_token": "Bot token",
"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_endpoint": "Linkding API-Endpunkt",
"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_token": "Διακριτικό bot",
"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_endpoint": "Τελικό σημείο Linkding API",
"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_token": "Bot token",
"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_endpoint": "Linkding API Endpoint",
"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_token": "Token de bot",
"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_endpoint": "Acceso 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_token": "Bot-tunnus",
"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_endpoint": "Linkding API-päätepiste",
"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_token": "Jeton de sécurité de l'API du Bot Telegram",
"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_endpoint": "URL de l'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_token": "बॉट टोकन",
"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_endpoint": "लिंकिंग एपीआई समापन बिंदु",
"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_token": "Token Bot",
"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_endpoint": "Titik URL 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_token": "Token bot",
"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_endpoint": "Endpoint dell'API di 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_token": "ボットトークン",
"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_endpoint": "Linkding の API Endpoint",
"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_token": "Bot token",
"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_endpoint": "Linkding URL",
"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_token": "Token bota",
"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_endpoint": "Linkding URL",
"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_token": "Token de bot",
"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_endpoint": "Endpoint 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_token": "Токен бота",
"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_endpoint": "Конечная точка Linkding API",
"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_token": "Bot jetonu",
"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_endpoint": "Linkding API Uç Noktası",
"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.telegram_bot_activate": "Відправляти нові статті до чату Telegram",
"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.linkding_activate": "Зберігати статті до Linkding",
"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.telegram_bot_activate": "将新文章推送到 Telegram",
"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.linkding_activate": "保存文章到 Linkding",
"form.integration.linkding_endpoint": "Linkding API 端点",

View File

@ -372,6 +372,9 @@
"form.integration.telegram_bot_activate": "將新文章推送到 Telegram",
"form.integration.telegram_bot_token": "Bot token",
"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_endpoint": "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.
type Integration struct {
UserID int64
PinboardEnabled bool
PinboardToken string
PinboardTags string
PinboardMarkAsUnread bool
InstapaperEnabled bool
InstapaperUsername string
InstapaperPassword string
FeverEnabled bool
FeverUsername string
FeverToken string
GoogleReaderEnabled bool
GoogleReaderUsername string
GoogleReaderPassword string
WallabagEnabled bool
WallabagOnlyURL bool
WallabagURL string
WallabagClientID string
WallabagClientSecret string
WallabagUsername string
WallabagPassword string
NunuxKeeperEnabled bool
NunuxKeeperURL string
NunuxKeeperAPIKey string
NotionEnabled bool
NotionToken string
NotionPageID string
EspialEnabled bool
EspialURL string
EspialAPIKey string
EspialTags string
ReadwiseEnabled bool
ReadwiseAPIKey string
PocketEnabled bool
PocketAccessToken string
PocketConsumerKey string
TelegramBotEnabled bool
TelegramBotToken string
TelegramBotChatID string
LinkdingEnabled bool
LinkdingURL string
LinkdingAPIKey string
LinkdingTags string
LinkdingMarkAsUnread bool
MatrixBotEnabled bool
MatrixBotUser string
MatrixBotPassword string
MatrixBotURL string
MatrixBotChatID string
AppriseEnabled bool
AppriseURL string
AppriseServicesURL string
ShioriEnabled bool
ShioriURL string
ShioriUsername string
ShioriPassword string
ShaarliEnabled bool
ShaarliURL string
ShaarliAPISecret string
WebhookEnabled bool
WebhookURL string
WebhookSecret string
UserID int64
PinboardEnabled bool
PinboardToken string
PinboardTags string
PinboardMarkAsUnread bool
InstapaperEnabled bool
InstapaperUsername string
InstapaperPassword string
FeverEnabled bool
FeverUsername string
FeverToken string
GoogleReaderEnabled bool
GoogleReaderUsername string
GoogleReaderPassword string
WallabagEnabled bool
WallabagOnlyURL bool
WallabagURL string
WallabagClientID string
WallabagClientSecret string
WallabagUsername string
WallabagPassword string
NunuxKeeperEnabled bool
NunuxKeeperURL string
NunuxKeeperAPIKey string
NotionEnabled bool
NotionToken string
NotionPageID string
EspialEnabled bool
EspialURL string
EspialAPIKey string
EspialTags string
ReadwiseEnabled bool
ReadwiseAPIKey string
PocketEnabled bool
PocketAccessToken string
PocketConsumerKey string
TelegramBotEnabled bool
TelegramBotToken string
TelegramBotChatID string
TelegramBotTopicID *int64
TelegramBotDisableWebPagePreview bool
TelegramBotDisableNotification bool
LinkdingEnabled bool
LinkdingURL string
LinkdingAPIKey string
LinkdingTags string
LinkdingMarkAsUnread bool
MatrixBotEnabled bool
MatrixBotUser string
MatrixBotPassword string
MatrixBotURL string
MatrixBotChatID string
AppriseEnabled bool
AppriseURL string
AppriseServicesURL string
ShioriEnabled bool
ShioriURL string
ShioriUsername string
ShioriPassword string
ShaarliEnabled bool
ShaarliURL 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_token,
telegram_bot_chat_id,
telegram_bot_topic_id,
telegram_bot_disable_web_page_preview,
telegram_bot_disable_notification,
linkding_enabled,
linkding_url,
linkding_api_key,
@ -217,6 +220,9 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
&integration.TelegramBotEnabled,
&integration.TelegramBotToken,
&integration.TelegramBotChatID,
&integration.TelegramBotTopicID,
&integration.TelegramBotDisableWebPagePreview,
&integration.TelegramBotDisableNotification,
&integration.LinkdingEnabled,
&integration.LinkdingURL,
&integration.LinkdingAPIKey,
@ -286,40 +292,43 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
telegram_bot_enabled=$27,
telegram_bot_token=$28,
telegram_bot_chat_id=$29,
espial_enabled=$30,
espial_url=$31,
espial_api_key=$32,
espial_tags=$33,
linkding_enabled=$34,
linkding_url=$35,
linkding_api_key=$36,
linkding_tags=$37,
linkding_mark_as_unread=$38,
matrix_bot_enabled=$39,
matrix_bot_user=$40,
matrix_bot_password=$41,
matrix_bot_url=$42,
matrix_bot_chat_id=$43,
notion_enabled=$44,
notion_token=$45,
notion_page_id=$46,
readwise_enabled=$47,
readwise_api_key=$48,
apprise_enabled=$49,
apprise_url=$50,
apprise_services_url=$51,
shiori_enabled=$52,
shiori_url=$53,
shiori_username=$54,
shiori_password=$55,
shaarli_enabled=$56,
shaarli_url=$57,
shaarli_api_secret=$58,
webhook_enabled=$59,
webhook_url=$60,
webhook_secret=$61
telegram_bot_topic_id=$30,
telegram_bot_disable_web_page_preview=$31,
telegram_bot_disable_notification=$32,
espial_enabled=$33,
espial_url=$34,
espial_api_key=$35,
espial_tags=$36,
linkding_enabled=$37,
linkding_url=$38,
linkding_api_key=$39,
linkding_tags=$40,
linkding_mark_as_unread=$41,
matrix_bot_enabled=$42,
matrix_bot_user=$43,
matrix_bot_password=$44,
matrix_bot_url=$45,
matrix_bot_chat_id=$46,
notion_enabled=$47,
notion_token=$48,
notion_page_id=$49,
readwise_enabled=$50,
readwise_api_key=$51,
apprise_enabled=$52,
apprise_url=$53,
apprise_services_url=$54,
shiori_enabled=$55,
shiori_url=$56,
shiori_username=$57,
shiori_password=$58,
shaarli_enabled=$59,
shaarli_url=$60,
shaarli_api_secret=$61,
webhook_enabled=$62,
webhook_url=$63,
webhook_secret=$64
WHERE
user_id=$62
user_id=$65
`
_, err := s.db.Exec(
query,
@ -352,6 +361,9 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
integration.TelegramBotEnabled,
integration.TelegramBotToken,
integration.TelegramBotChatID,
integration.TelegramBotTopicID,
integration.TelegramBotDisableWebPagePreview,
integration.TelegramBotDisableNotification,
integration.EspialEnabled,
integration.EspialURL,
integration.EspialAPIKey,

View File

@ -328,6 +328,17 @@
<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">
<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">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>

View File

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