client.go

 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}