feat: add basic linkding connection

This commit is contained in:
Alexander Navarro 2024-12-18 16:54:33 -03:00
parent 43cd24e4d0
commit 43f6340a4a
8 changed files with 163 additions and 16 deletions

View file

@ -9,10 +9,11 @@ import (
"git.alecodes.page/alecodes/miniflux-archiver/internal/app" "git.alecodes.page/alecodes/miniflux-archiver/internal/app"
"git.alecodes.page/alecodes/miniflux-archiver/internal/miniflux" "git.alecodes.page/alecodes/miniflux-archiver/internal/miniflux"
"git.alecodes.page/alecodes/miniflux-archiver/internal/service"
) )
var Services = []string{ var Services = []string{
"linkding", string(service.ServiceLinkding),
} }
var ( var (
@ -29,13 +30,13 @@ var archiveCmd = &cobra.Command{
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
ValidArgs: Services, ValidArgs: Services,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
service := args[0] serviceOption := service.ServiceOption(args[0])
serviceConfig := app.ServiceConfig{ serviceConfig := service.ServiceConfig{
Service: service, Service: serviceOption,
Host: service_host, Host: viper.GetString("service_host"),
User: service_user, User: viper.GetString("service_user"),
Token: service_token, Token: viper.GetString("service_token"),
} }
minifluxConfig := miniflux.MinifluxConfig{ minifluxConfig := miniflux.MinifluxConfig{

1
go.mod
View file

@ -16,6 +16,7 @@ require (
github.com/magiconair/properties v1.8.7 // indirect github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/piero-vic/go-linkding v0.2.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect

2
go.sum
View file

@ -25,6 +25,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/piero-vic/go-linkding v0.2.0 h1:1LNIeWvYe8Kd+kaG4hsWzYH/vvQ9OaJOMoV+XvXaH+Q=
github.com/piero-vic/go-linkding v0.2.0/go.mod h1:PuwOySAQYmbq4cIDAG1bXDMQwBUuorRkbjM43RdUhao=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

View file

@ -5,14 +5,20 @@ import (
"git.alecodes.page/alecodes/miniflux-archiver/internal/logger" "git.alecodes.page/alecodes/miniflux-archiver/internal/logger"
"git.alecodes.page/alecodes/miniflux-archiver/internal/miniflux" "git.alecodes.page/alecodes/miniflux-archiver/internal/miniflux"
"git.alecodes.page/alecodes/miniflux-archiver/internal/service"
) )
func Archive(minifluxConfig miniflux.MinifluxConfig, serviceConfig ServiceConfig) { func Archive(minifluxConfig miniflux.MinifluxConfig, serviceConfig service.ServiceConfig) {
mf, err := miniflux.NewMiniflux(minifluxConfig) mf, err := miniflux.NewMiniflux(minifluxConfig)
if err != nil { if err != nil {
logger.Fatal("Could not connect to the miniflux server: %v", err) logger.Fatal("Could not connect to the miniflux server: %v", err)
} }
externalService, err := service.ResolveService(serviceConfig)
if err != nil {
logger.Fatal(err.Error())
}
result, err := mf.GetEntries() result, err := mf.GetEntries()
if err != nil { if err != nil {
logger.Fatal("Could not retrieve entries from the miniflux feed: %v", err) logger.Fatal("Could not retrieve entries from the miniflux feed: %v", err)
@ -20,4 +26,9 @@ func Archive(minifluxConfig miniflux.MinifluxConfig, serviceConfig ServiceConfig
entry := result.Entries[0] entry := result.Entries[0]
fmt.Println(entry.Title, entry.Status, entry.Tags) fmt.Println(entry.Title, entry.Status, entry.Tags)
err = externalService.Archive(entry.URL)
if err != nil {
logger.Fatal("Could not archive entry from the service: %v", err)
}
} }

View file

@ -1,8 +0,0 @@
package app
type ServiceConfig struct {
Service string
Host string
User string
Token string
}

17
internal/config/config.go Normal file
View file

@ -0,0 +1,17 @@
package config
import "git.alecodes.page/alecodes/miniflux-archiver/internal/service"
type MinifluxConfig struct {
Host string
User string
Token string
FeedId int64
}
type ServiceConfig struct {
Service service.ServiceOption
Host string
User string
Token string
}

View file

@ -0,0 +1,81 @@
package service
import (
"encoding/json"
"fmt"
"net/http"
ldApi "github.com/piero-vic/go-linkding"
)
type Linkding struct {
ServiceConfig
client *ldApi.Client
}
func (ld *Linkding) CheckBookmark(url string) (*ldApi.Bookmark, error) {
bookmark := &ldApi.Bookmark{}
req, err := http.NewRequest(
http.MethodGet,
fmt.Sprintf("%v/api/bookmarks/check/?url=%d", ld.Host, url),
nil,
)
if err != nil {
return bookmark, err
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
req.Header.Add("Authorization", fmt.Sprintf("Token %s", ld.Token))
res, err := http.DefaultClient.Do(req)
if err != nil {
return bookmark, err
}
defer res.Body.Close()
if err := json.NewDecoder(res.Body).Decode(bookmark); err != nil {
return bookmark, err
}
return bookmark, nil
}
func (ld *Linkding) Archive(url string) error {
bookmark, err := ld.CheckBookmark(url)
payload := ldApi.CreateBookmarkRequest{
URL: url,
Unread: false,
TagNames: bookmark.TagNames,
}
if payload.TagNames == nil {
payload.TagNames = []string{}
}
if err != nil {
_, err = ld.client.UpdateBookmark(bookmark.ID, payload)
} else {
_, err = ld.client.CreateBookmark(payload)
}
return err
}
func (ld *Linkding) IsAvailable() (bool, error) {
_, err := ld.client.ListTags(ldApi.ListTagsParams{})
return err == nil, err
}
func NewLinkding(config ServiceConfig) (*Linkding, error) {
mf := &Linkding{
ServiceConfig: config,
client: ldApi.NewClient(config.Host, config.Token),
}
return mf, nil
}

View file

@ -0,0 +1,42 @@
package service
import "fmt"
type ServiceOption string
const (
ServiceLinkding ServiceOption = "linkding"
)
type ServiceConfig struct {
Service ServiceOption
Host string
User string
Token string
}
type Service interface {
IsAvailable() (bool, error)
Archive(string) error
}
func ResolveService(serviceConfig ServiceConfig) (Service, error) {
var service Service
switch serviceConfig.Service {
case ServiceLinkding:
service, _ = NewLinkding(serviceConfig)
default:
return nil, fmt.Errorf("Could not determine service to connect to")
}
if isAvailable, err := service.IsAvailable(); !isAvailable {
return nil, fmt.Errorf(
"Could not connect to the service %v in %v: %v",
serviceConfig.Service,
serviceConfig.Host,
err,
)
}
return service, nil
}