mostly working

This commit is contained in:
Balakrishnan Balasubramanian 2022-12-26 13:41:45 -05:00
parent 514688e72b
commit 70b4b9b847
3 changed files with 190 additions and 58 deletions

105
glist/glist.go Normal file
View File

@ -0,0 +1,105 @@
package glist
import (
"encoding/json"
"fmt"
"sync"
)
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
}
func (g *GList) Add(text string) error {
for _, item := range g.Items {
if item.Text == text {
return fmt.Errorf("dupe:%s", text)
}
}
g.Items = append(g.Items, Entry{text, false})
return nil
}
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
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
}
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: "ok"}
itemButtons := makeButtons(g.Items)
controlButtons := []button{{"clear checked", "clear"}}
req.ReplyMarkup.InlineKeyboard = append(itemButtons, controlButtons)
data, err := json.Marshal(req)
return data, err
}

20
glist/glist_test.go Normal file
View File

@ -0,0 +1,20 @@
package glist
import (
"sync"
"testing"
)
func TestGList(t *testing.T) {
var ti int
var m sync.Mutex
g := GList{ti, m, 4342, nil, []Entry{{"foo", true}}}
data, err := g.GenSendListReq()
if err != nil {
t.Fatal(err)
}
expected := `{"chat_id":4342,"text":"ok","reply_markup":{"inline_keyboard":[[{"text":"✓ foo","callback_data":"foo"}]]}}`
if expected != string(data) {
t.Fatalf("expected: %s\n got:%s\n", expected, string(data))
}
}

117
main.go
View File

@ -1,21 +1,23 @@
package main package main
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"log" "log"
"net/http" "net/http"
"strings" "sync"
"time"
"gitea.balki.me/telegram-msgchkbox/glist"
) )
var apiToken = "421791796:AAE4wPbcqfLP1GNeGR3RTBiyX16fCj3HPAM" var apiToken = "421791796:AAE4wPbcqfLP1GNeGR3RTBiyX16fCj3HPAM"
func main() { func main() {
var chats sync.Map
fmt.Println("vim-go") fmt.Println("vim-go")
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
})
http.HandleFunc("/zeexkfcsdjpmncirkyelwzotjmmefcqtcogrfwnafidionxiacwnslwuhbwfuppjgwzbmazd", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/zeexkfcsdjpmncirkyelwzotjmmefcqtcogrfwnafidionxiacwnslwuhbwfuppjgwzbmazd", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok")) w.Write([]byte("ok"))
body, err := io.ReadAll(r.Body) body, err := io.ReadAll(r.Body)
@ -50,39 +52,70 @@ func main() {
} }
if update.Message != nil { if update.Message != nil {
go sendButton(update.Message.Chat.ID, update.Message.ID, update.Message.Text)
go DeleteMessage(update.Message.Chat.ID, update.Message.ID) chatID := update.Message.Chat.ID
g, _ := chats.LoadOrStore(chatID, glist.NewGList(chatID))
gl := g.(*glist.GList)
go handleTextAdded(gl, update.Message.Text)
} else if update.CallbackQuery != nil { } else if update.CallbackQuery != nil {
go markButtonChecked(update.CallbackQuery.Message.Chat.ID, update.CallbackQuery.Message.ID, update.CallbackQuery.Data) defer func() { go answerCallbackQuery(update.CallbackQuery.ID) }()
go answerCallbackQuery(update.CallbackQuery.ID)
chatID := update.CallbackQuery.Message.Chat.ID
g, ok := chats.Load(chatID)
if !ok {
log.Println("Chat not found: %s", chatID)
return
}
gl := g.(*glist.GList)
go handleButtonClick(gl, update.CallbackQuery.Message.ID, update.CallbackQuery.Data)
} }
}) })
port := 28923 port := 28923
log.Panic(http.ListenAndServe(fmt.Sprintf(":%v", port), nil)) log.Panic(http.ListenAndServe(fmt.Sprintf(":%v", port), nil))
} }
func markButtonChecked(chatID int, messageID int, text string) { func handleTextAdded(gl *glist.GList, text string) {
url := fmt.Sprintf("https://api.telegram.org/bot%s/editMessageText", apiToken) gl.Mutex.Lock()
text = fmt.Sprintf("✓ %s", text) defer gl.Mutex.Unlock()
sendMsgFmt := ` gl.Add(text)
{ count := gl.AllMsgCounter + 1
"chat_id": "%d", gl.AllMsgCounter = count
"message_id": "%d", time.AfterFunc(30*time.Second, func() {
"text": "ok", gl.Mutex.Lock()
"reply_markup": { defer gl.Mutex.Unlock()
"inline_keyboard": [ if count == gl.AllMsgCounter {
[ sendList(gl, "sendMessage")
{
"text": "%s",
"callback_data": "%s"
} }
] })
] }
func handleButtonClick(gl *glist.GList, messageID int, text string) {
gl.Mutex.Lock()
defer gl.Mutex.Unlock()
if gl.MessageID != nil {
if messageID != *gl.MessageID {
go deleteMessage(gl.ChatID, *gl.MessageID)
} }
} }
` gl.MessageID = &messageID
sendMsgReq := fmt.Sprintf(sendMsgFmt, chatID, messageID, text, text) if text == "clear" {
resp, err := http.Post(url, "application/json", strings.NewReader(sendMsgReq)) gl.ClearChecked()
} else {
gl.Toggle(text)
}
sendList(gl, "editMessageText")
}
func sendList(gl *glist.GList, method string) {
url := fmt.Sprintf("https://api.telegram.org/bot%s/%s", apiToken, method)
sendMsgReq, err := gl.GenSendListReq()
if err != nil {
log.Println(err)
return
}
resp, err := http.Post(url, "application/json", bytes.NewReader(sendMsgReq))
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return return
@ -100,33 +133,7 @@ func answerCallbackQuery(callbackQueryID string) {
logBody(resp.Body) logBody(resp.Body)
} }
func sendButton(chatID int, messageID int, text string) { func deleteMessage(chatID int, messageID int) {
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", apiToken)
sendMsgFmt := `
{
"chat_id": "%d",
"text": "ok",
"reply_markup": {
"inline_keyboard": [
[
{
"text": "%s",
"callback_data": "%s"
}
]
]
}
}
`
sendMsgReq := fmt.Sprintf(sendMsgFmt, chatID, text, text)
resp, err := http.Post(url, "application/json", strings.NewReader(sendMsgReq))
if err != nil {
log.Println(err)
return
}
logBody(resp.Body)
}
func DeleteMessage(chatID int, messageID int) {
deleteUrl := fmt.Sprintf("https://api.telegram.org/bot%s/deleteMessage?chat_id=%d&message_id=%d", apiToken, chatID, messageID) deleteUrl := fmt.Sprintf("https://api.telegram.org/bot%s/deleteMessage?chat_id=%d&message_id=%d", apiToken, chatID, messageID)
resp, err := http.Get(deleteUrl) resp, err := http.Get(deleteUrl)
if err != nil { if err != nil {
@ -151,7 +158,7 @@ func logBody(respBody io.ReadCloser) {
log.Println(string(body)) log.Println(string(body))
} }
/* /* Example data
update_id: 547400623 update_id: 547400623
message: message:
message_id: 869 message_id: 869