1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5// Package client provides a configured Lunatask API client.
6package client
7
8import (
9 "errors"
10 "fmt"
11 "runtime/debug"
12
13 "git.secluded.site/go-lunatask"
14 "github.com/zalando/go-keyring"
15)
16
17const (
18 keyringService = "lune"
19 keyringUser = "api-key"
20)
21
22// ErrNoToken indicates no access token is available in the system keyring.
23var ErrNoToken = errors.New("no access token found in system keyring; run 'lune init' to configure")
24
25// New creates a Lunatask client using the access token from system keyring.
26func New() (*lunatask.Client, error) {
27 token, err := keyring.Get(keyringService, keyringUser)
28 if err != nil {
29 if errors.Is(err, keyring.ErrNotFound) {
30 return nil, ErrNoToken
31 }
32
33 return nil, fmt.Errorf("accessing system keyring: %w", err)
34 }
35
36 return lunatask.NewClient(token, lunatask.UserAgent("lune/"+version())), nil
37}
38
39// GetToken returns the access token from keyring. Returns empty string and nil error
40// if not found; returns error for keyring access problems.
41func GetToken() (string, error) {
42 token, err := keyring.Get(keyringService, keyringUser)
43 if err != nil {
44 if errors.Is(err, keyring.ErrNotFound) {
45 return "", nil
46 }
47
48 return "", fmt.Errorf("accessing system keyring: %w", err)
49 }
50
51 return token, nil
52}
53
54// SetToken stores the access token in the system keyring.
55func SetToken(token string) error {
56 if err := keyring.Set(keyringService, keyringUser, token); err != nil {
57 return fmt.Errorf("keyring set: %w", err)
58 }
59
60 return nil
61}
62
63// DeleteToken removes the access token from the system keyring.
64func DeleteToken() error {
65 if err := keyring.Delete(keyringService, keyringUser); err != nil {
66 return fmt.Errorf("keyring delete: %w", err)
67 }
68
69 return nil
70}
71
72// HasKeyringToken checks if an access token is stored in the keyring.
73// Returns (true, nil) if found, (false, nil) if not found,
74// or (false, error) if there was a keyring access problem.
75func HasKeyringToken() (bool, error) {
76 _, err := keyring.Get(keyringService, keyringUser)
77 if err != nil {
78 if errors.Is(err, keyring.ErrNotFound) {
79 return false, nil
80 }
81
82 return false, fmt.Errorf("accessing system keyring: %w", err)
83 }
84
85 return true, nil
86}
87
88// version returns the module version from build info, or "dev" if unavailable.
89func version() string {
90 info, ok := debug.ReadBuildInfo()
91 if !ok || info.Main.Version == "" || info.Main.Version == "(devel)" {
92 return "dev"
93 }
94
95 return info.Main.Version
96}