85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package service
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type PendingAction string
|
|
|
|
const (
|
|
PendingCreateList PendingAction = "create_list"
|
|
PendingRenameList PendingAction = "rename_list"
|
|
|
|
PendingCreateItem PendingAction = "create_item"
|
|
PendingRenameItem PendingAction = "rename_item"
|
|
PendingEditItemNote PendingAction = "edit_item_note"
|
|
PendingEditItemQuantity PendingAction = "edit_item_quantity"
|
|
|
|
PendingShareTarget PendingAction = "share_target"
|
|
PendingShareRole PendingAction = "share_role"
|
|
)
|
|
|
|
type Pending struct {
|
|
Action PendingAction
|
|
ListID int64
|
|
ItemID int64
|
|
Target string
|
|
expiresAt time.Time
|
|
}
|
|
|
|
type PendingStore struct {
|
|
mu sync.Mutex
|
|
ttl time.Duration
|
|
items map[int64]Pending
|
|
}
|
|
|
|
func NewPendingStore(ttl time.Duration) *PendingStore {
|
|
// shortcut: expired entries stay in memory until the user writes again; add a janitor if user count grows.
|
|
return &PendingStore{
|
|
ttl: ttl,
|
|
items: make(map[int64]Pending),
|
|
}
|
|
}
|
|
|
|
func (s *PendingStore) Set(telegramID int64, pending Pending) {
|
|
pending.expiresAt = time.Now().Add(s.ttl)
|
|
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.items[telegramID] = pending
|
|
}
|
|
|
|
func (s *PendingStore) Take(telegramID int64) (Pending, bool) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
pending, ok := s.items[telegramID]
|
|
delete(s.items, telegramID)
|
|
if !ok || time.Now().After(pending.expiresAt) {
|
|
return Pending{}, false
|
|
}
|
|
return pending, true
|
|
}
|
|
|
|
func (s *PendingStore) Get(telegramID int64) (Pending, bool) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
pending, ok := s.items[telegramID]
|
|
if !ok {
|
|
return Pending{}, false
|
|
}
|
|
if time.Now().After(pending.expiresAt) {
|
|
delete(s.items, telegramID)
|
|
return Pending{}, false
|
|
}
|
|
return pending, true
|
|
}
|
|
|
|
func (s *PendingStore) Clear(telegramID int64) bool {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
pending, ok := s.items[telegramID]
|
|
delete(s.items, telegramID)
|
|
return ok && !time.Now().After(pending.expiresAt)
|
|
}
|