Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(integration): add cubox integration #2897

Merged
merged 1 commit into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions internal/database/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -952,4 +952,12 @@ 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 cubox_enabled bool default 'f';
ALTER TABLE integrations ADD COLUMN cubox_api_link text default '';
`
_, err = tx.Exec(sql)
return err
},
}
70 changes: 70 additions & 0 deletions internal/integration/cubox/cubox.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

// Cubox API documentation: https://help.cubox.cc/save/api/

package cubox // import "miniflux.app/v2/internal/integration/cubox"

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"time"

"miniflux.app/v2/internal/version"
)

const defaultClientTimeout = 10 * time.Second

type Client struct {
apiLink string
}

func NewClient(apiLink string) *Client {
return &Client{apiLink: apiLink}
}

func (c *Client) SaveLink(entryURL string) error {
if c.apiLink == "" {
return errors.New("cubox: missing API link")
}

requestBody, err := json.Marshal(&card{
Type: "url",
Content: entryURL,
})
if err != nil {
return fmt.Errorf("cubox: unable to encode request body: %w", err)
}

ctx, cancel := context.WithTimeout(context.Background(), defaultClientTimeout)
defer cancel()

request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.apiLink, bytes.NewReader(requestBody))
if err != nil {
return fmt.Errorf("cubox: unable to create request: %w", err)
}

request.Header.Set("Content-Type", "application/json")
request.Header.Set("User-Agent", "Miniflux/"+version.Version)

response, err := http.DefaultClient.Do(request)
if err != nil {
return fmt.Errorf("cubox: unable to send request: %w", err)
}
defer response.Body.Close()

if response.StatusCode != 200 {
return fmt.Errorf("cubox: unable to save link: status=%d", response.StatusCode)
}

return nil
}

type card struct {
Type string `json:"type"`
Content string `json:"content"`
}
20 changes: 20 additions & 0 deletions internal/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"miniflux.app/v2/internal/config"
"miniflux.app/v2/internal/integration/apprise"
"miniflux.app/v2/internal/integration/betula"
"miniflux.app/v2/internal/integration/cubox"
"miniflux.app/v2/internal/integration/espial"
"miniflux.app/v2/internal/integration/instapaper"
"miniflux.app/v2/internal/integration/linkace"
Expand Down Expand Up @@ -322,6 +323,25 @@ func SendEntry(entry *model.Entry, userIntegrations *model.Integration) {
}
}

if userIntegrations.CuboxEnabled {
slog.Debug("Sending entry to Cubox",
slog.Int64("user_id", userIntegrations.UserID),
slog.Int64("entry_id", entry.ID),
slog.String("entry_url", entry.URL),
)

client := cubox.NewClient(userIntegrations.CuboxAPILink)

if err := client.SaveLink(entry.URL); err != nil {
slog.Error("Unable to send entry to Cubox",
slog.Int64("user_id", userIntegrations.UserID),
slog.Int64("entry_id", entry.ID),
slog.String("entry_url", entry.URL),
slog.Any("error", err),
)
}
}

if userIntegrations.ShioriEnabled {
slog.Debug("Sending entry to Shiori",
slog.Int64("user_id", userIntegrations.UserID),
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "Allgemein",
"form.feed.fieldset.rules": "Regeln",
"form.feed.fieldset.network_settings": "Netzwerkeinstellungen",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/el_EL.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.category.label.title": "Τίτλος",
"form.category.hide_globally": "Απόκρυψη καταχωρήσεων σε γενική λίστα μη αναγνωσμένων",
"form.user.label.username": "Χρήστης",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@
"form.integration.ntfy_username": "Ntfy Username (optional)",
"form.integration.ntfy_password": "Ntfy Password (optional)",
"form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.api_key.label.description": "API Key Label",
"form.submit.loading": "Loading…",
"form.submit.saving": "Saving…",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/es_ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Prioridad predeterminada a Ntfy",
"form.feed.label.ntfy_low_priority": "Prioridad baja a Ntfy",
"form.feed.label.ntfy_min_priority": "Prioridad mínima a Ntfy",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Reglas",
"form.feed.fieldset.network_settings": "Ajustes de red",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/fi_FI.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/fr_FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Priorité par défaut de notification",
"form.feed.label.ntfy_low_priority": "Priorité basse de notification",
"form.feed.label.ntfy_min_priority": "Priorité minimale de notification",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "Général",
"form.feed.fieldset.rules": "Règles",
"form.feed.fieldset.network_settings": "Paramètres réseau",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/hi_IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/id_ID.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/it_IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/ja_JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/nl_NL.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy standaard prioriteit",
"form.feed.label.ntfy_low_priority": "Ntfy lage prioriteit",
"form.feed.label.ntfy_min_priority": "Ntfy minimale prioriteit",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "Algemeen",
"form.feed.fieldset.rules": "Regels",
"form.feed.fieldset.network_settings": "Netwerk Instellingen",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/pl_PL.json
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@
"form.feed.label.ntfy_default_priority": "Domyślny priorytet ntfy",
"form.feed.label.ntfy_low_priority": "Niski priorytet ntfy",
"form.feed.label.ntfy_min_priority": "Minimalny priorytet ntfy",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "Ogólne",
"form.feed.fieldset.rules": "Reguły",
"form.feed.fieldset.network_settings": "Ustawienia sieci",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/ru_RU.json
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/tr_TR.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.prefs.fieldset.application_settings": "Uygulama Ayarları",
"form.prefs.fieldset.authentication_settings": "Kimlik Doğrulama Ayarları",
"form.prefs.fieldset.reader_settings": "Okuyucu Ayarları",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/uk_UA.json
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.category.label.title": "Назва",
"form.category.hide_globally": "Приховати записи в глобальному списку непрочитаного",
"form.feed.fieldset.general": "General",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy默认优先级",
"form.feed.label.ntfy_low_priority": "Ntfy低优先级",
"form.feed.label.ntfy_min_priority": "Ntfy最低优先级",
"form.integration.cubox_activate": "保存文章到 Cubox",
"form.integration.cubox_api_link": "Cubox API 链接",
"form.feed.fieldset.general": "通用",
"form.feed.fieldset.rules": "规则",
"form.feed.fieldset.network_settings": "网络设置",
Expand Down
2 changes: 2 additions & 0 deletions internal/locale/translations/zh_TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@
"form.feed.label.ntfy_default_priority": "Ntfy default priority",
"form.feed.label.ntfy_low_priority": "Ntfy low priority",
"form.feed.label.ntfy_min_priority": "Ntfy min priority",
"form.integration.cubox_activate": "Save entries to Cubox",
"form.integration.cubox_api_link": "Cubox API link",
"form.feed.fieldset.general": "通用",
"form.feed.fieldset.rules": "規則",
"form.feed.fieldset.network_settings": "網路設定",
Expand Down
2 changes: 2 additions & 0 deletions internal/model/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,6 @@ type Integration struct {
NtfyUsername string
NtfyPassword string
NtfyIconURL string
CuboxEnabled bool
CuboxAPILink string
}
17 changes: 13 additions & 4 deletions internal/storage/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
ntfy_api_token,
ntfy_username,
ntfy_password,
ntfy_icon_url
ntfy_icon_url,
cubox_enabled,
cubox_api_link
FROM
integrations
WHERE
Expand Down Expand Up @@ -314,6 +316,8 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
&integration.NtfyUsername,
&integration.NtfyPassword,
&integration.NtfyIconURL,
&integration.CuboxEnabled,
&integration.CuboxAPILink,
)
switch {
case err == sql.ErrNoRows:
Expand Down Expand Up @@ -428,9 +432,11 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
ntfy_api_token=$95,
ntfy_username=$96,
ntfy_password=$97,
ntfy_icon_url=$98
ntfy_icon_url=$98,
cubox_enabled=$99,
cubox_api_link=$100
WHERE
user_id=$99
user_id=$101
`
_, err := s.db.Exec(
query,
Expand Down Expand Up @@ -532,6 +538,8 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
integration.NtfyUsername,
integration.NtfyPassword,
integration.NtfyIconURL,
integration.CuboxEnabled,
integration.CuboxAPILink,
integration.UserID,
)

Expand Down Expand Up @@ -571,7 +579,8 @@ func (s *Storage) HasSaveEntry(userID int64) (result bool) {
webhook_enabled='t' OR
omnivore_enabled='t' OR
raindrop_enabled='t' OR
betula_enabled='t'
betula_enabled='t' OR
cubox_enabled='t'
)
`
if err := s.db.QueryRow(query, userID).Scan(&result); err != nil {
Expand Down
16 changes: 16 additions & 0 deletions internal/template/templates/views/integrations.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ <h1 id="page-header-title">{{ t "page.integrations.title" }}</h1>
</div>
</details>

<details {{ if .form.CuboxEnabled }}open{{ end }}>
<summary>Cubox</summary>
<div class="form-section">
<label>
<input type="checkbox" name="cubox_enabled" value="1" {{ if .form.CuboxEnabled }}checked{{ end }}> {{ t "form.integration.cubox_activate" }}
</label>

<label for="form-cubox-api-link">{{ t "form.integration.cubox_api_link" }}</label>
<input type="url" name="cubox_api_link" id="form-cubox-api-link" value="{{ .form.CuboxAPILink }}" placeholder="https://cubox.pro/c/api/save/xxx" spellcheck="false">

<div class="buttons">
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
</div>
</div>
</details>

<details {{ if .form.EspialEnabled }}open{{ end }}>
<summary>Espial</summary>
<div class="form-section">
Expand Down
6 changes: 6 additions & 0 deletions internal/ui/form/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ type IntegrationForm struct {
NtfyUsername string
NtfyPassword string
NtfyIconURL string
CuboxEnabled bool
CuboxAPILink string
}

// Merge copy form values to the model.
Expand Down Expand Up @@ -209,6 +211,8 @@ func (i IntegrationForm) Merge(integration *model.Integration) {
integration.NtfyUsername = i.NtfyUsername
integration.NtfyPassword = i.NtfyPassword
integration.NtfyIconURL = i.NtfyIconURL
integration.CuboxEnabled = i.CuboxEnabled
integration.CuboxAPILink = i.CuboxAPILink
}

// NewIntegrationForm returns a new IntegrationForm.
Expand Down Expand Up @@ -311,6 +315,8 @@ func NewIntegrationForm(r *http.Request) *IntegrationForm {
NtfyUsername: r.FormValue("ntfy_username"),
NtfyPassword: r.FormValue("ntfy_password"),
NtfyIconURL: r.FormValue("ntfy_icon_url"),
CuboxEnabled: r.FormValue("cubox_enabled") == "1",
CuboxAPILink: r.FormValue("cubox_api_link"),
}
}

Expand Down
2 changes: 2 additions & 0 deletions internal/ui/integration_show.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) {
NtfyUsername: integration.NtfyUsername,
NtfyPassword: integration.NtfyPassword,
NtfyIconURL: integration.NtfyIconURL,
CuboxEnabled: integration.CuboxEnabled,
CuboxAPILink: integration.CuboxAPILink,
}

sess := session.New(h.store, request.SessionID(r))
Expand Down
Loading