mostly working
This commit is contained in:
parent
514688e72b
commit
70b4b9b847
105
glist/glist.go
Normal file
105
glist/glist.go
Normal 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
20
glist/glist_test.go
Normal 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
117
main.go
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user