Balakrishnan Balasubramanian
0354436ab6
This prevents the process from waking up every five seconds even when there are no requests
157 lines
3.2 KiB
Go
157 lines
3.2 KiB
Go
package glist
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var DataPath string
|
|
|
|
type Entry struct {
|
|
Text string `json:"text"`
|
|
Checked bool `json:"checked"`
|
|
}
|
|
|
|
type GList struct {
|
|
AllMsgCounter int `json:"-"`
|
|
Mutex sync.Mutex `json:"-"`
|
|
ChatID int `json:"chat_id"`
|
|
MessageID *int `json:"message_id"`
|
|
Items []Entry `json:"items"`
|
|
}
|
|
|
|
func NewGList(chatID int, items ...string) *GList {
|
|
g := GList{ChatID: chatID}
|
|
for _, text := range items {
|
|
g.Items = append(g.Items, Entry{text, false})
|
|
}
|
|
return &g
|
|
}
|
|
|
|
var PersistReqC chan<- *GList
|
|
|
|
func startPersistenceGoR() {
|
|
reqs := make(chan *GList, 50)
|
|
PersistReqC = reqs
|
|
go func() {
|
|
lists := map[*GList]struct{}{}
|
|
for g := range reqs {
|
|
lists[g] = struct{}{}
|
|
time.Sleep(5 * time.Second)
|
|
for len(reqs) > 0 {
|
|
g := <-reqs
|
|
lists[g] = struct{}{}
|
|
}
|
|
for g := range lists {
|
|
g.persist()
|
|
}
|
|
lists = make(map[*GList]struct{}, len(lists))
|
|
}
|
|
}()
|
|
}
|
|
|
|
func init() {
|
|
startPersistenceGoR()
|
|
}
|
|
|
|
func (g *GList) persist() {
|
|
g.Mutex.Lock()
|
|
defer g.Mutex.Unlock()
|
|
data, err := json.Marshal(g)
|
|
if err != nil {
|
|
log.Panicln("failed to marshal")
|
|
}
|
|
filename := path.Join(DataPath, fmt.Sprintf("chkchat%d", g.ChatID))
|
|
if err := os.WriteFile(filename, data, 0644); err != nil {
|
|
log.Panicln("failed to write to file")
|
|
}
|
|
}
|
|
|
|
func (g *GList) Add(t string) {
|
|
outer:
|
|
for _, text := range strings.Split(t, "\n") {
|
|
for _, item := range g.Items {
|
|
if item.Text == text {
|
|
continue outer
|
|
}
|
|
}
|
|
g.Items = append(g.Items, Entry{text, false})
|
|
}
|
|
PersistReqC <- g
|
|
}
|
|
|
|
func (g *GList) Toggle(text string) error {
|
|
for i, item := range g.Items {
|
|
if item.Text == text {
|
|
g.Items[i].Checked = !g.Items[i].Checked
|
|
PersistReqC <- g
|
|
return nil
|
|
}
|
|
}
|
|
return fmt.Errorf("not found:%s", text)
|
|
}
|
|
|
|
func (g *GList) ClearChecked() {
|
|
var remaining []Entry
|
|
for _, item := range g.Items {
|
|
if !item.Checked {
|
|
remaining = append(remaining, item)
|
|
}
|
|
}
|
|
g.Items = remaining
|
|
PersistReqC <- g
|
|
}
|
|
|
|
type button struct {
|
|
Text string `json:"text"`
|
|
CallbackData string `json:"callback_data"`
|
|
}
|
|
|
|
type newListReq struct {
|
|
ChatID int `json:"chat_id"`
|
|
MessageID *int `json:"message_id,omitempty"`
|
|
Text string `json:"text"`
|
|
ReplyMarkup struct {
|
|
InlineKeyboard [][]button `json:"inline_keyboard"`
|
|
} `json:"reply_markup"`
|
|
}
|
|
|
|
func makeButton(e Entry) button {
|
|
b := button{Text: e.Text, CallbackData: e.Text}
|
|
if e.Checked {
|
|
b.Text = fmt.Sprintf("✓ %s", e.Text)
|
|
}
|
|
return b
|
|
}
|
|
|
|
func makeButtons(items []Entry) [][]button {
|
|
var buttons [][]button
|
|
var current []button
|
|
for _, item := range items {
|
|
current = append(current, makeButton(item))
|
|
if len(current) == 2 {
|
|
buttons = append(buttons, current)
|
|
current = []button{}
|
|
}
|
|
}
|
|
if len(current) != 0 {
|
|
buttons = append(buttons, current)
|
|
}
|
|
return buttons
|
|
}
|
|
|
|
func (g *GList) GenSendListReq() ([]byte, error) {
|
|
req := newListReq{ChatID: g.ChatID, MessageID: g.MessageID, Text: "List:"}
|
|
itemButtons := makeButtons(g.Items)
|
|
controlButtons := []button{{"clear checked", "clear"}}
|
|
req.ReplyMarkup.InlineKeyboard = append(itemButtons, controlButtons)
|
|
data, err := json.Marshal(req)
|
|
return data, err
|
|
}
|