diff --git a/cmds/minigame/2048.go b/cmds/minigame/2048.go
new file mode 100644
index 0000000..11f77d0
--- /dev/null
+++ b/cmds/minigame/2048.go
@@ -0,0 +1,29 @@
+package minigame
+
+import (
+ "fmt"
+ "os"
+
+ hc "neo/context"
+ "neo/core"
+)
+
+func init() { core.Default.Register(Game2048) }
+
+var Game2048 = &core.Command{
+ Name: "2048",
+ Aliases: []string{"2048"},
+ Category: "minigame",
+ Description: "Play 2048 in WhatsApp",
+ Run: func(ctx *hc.Ctx) {
+ htmlBytes, err := os.ReadFile("cmds/minigame/2048.html")
+ if err != nil {
+ ctx.Reply(fmt.Sprintf("Failed to read HTML file: %v", err))
+ return
+ }
+ _, err = ctx.SendInteractiveHTML(string(htmlBytes))
+ if err != nil {
+ ctx.Reply(fmt.Sprintf("Failed to send game: %v", err))
+ }
+ },
+}
diff --git a/cmds/minigame/2048.html b/cmds/minigame/2048.html
new file mode 100644
index 0000000..6a9b4d5
--- /dev/null
+++ b/cmds/minigame/2048.html
@@ -0,0 +1,394 @@
+
+
+
+
+2048
+
+
+
+
+
+
+
+
+
+
+
Game Over!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cmds/register.go b/cmds/register.go
index d1c7b0d..e7b5784 100644
--- a/cmds/register.go
+++ b/cmds/register.go
@@ -5,5 +5,6 @@ import (
_ "neo/cmds/general"
_ "neo/cmds/group"
_ "neo/cmds/media"
+ _ "neo/cmds/minigame"
_ "neo/cmds/misc"
)
diff --git a/context/send.go b/context/send.go
index 58b6e7b..cfdc8d8 100644
--- a/context/send.go
+++ b/context/send.go
@@ -2,7 +2,12 @@ package context
import (
stdctx "context"
+ "encoding/json"
+ "github.com/google/uuid"
+ "go.mau.fi/whatsmeow"
+ "go.mau.fi/whatsmeow/proto/waAICommon"
+ "go.mau.fi/whatsmeow/proto/waAICommonDeprecated"
waCommon "go.mau.fi/whatsmeow/proto/waCommon"
waE2E "go.mau.fi/whatsmeow/proto/waE2E"
waTypes "go.mau.fi/whatsmeow/types"
@@ -32,8 +37,8 @@ func (c *Ctx) Send(text string) {
c.client.SendMessage(stdctx.Background(), c.event.Info.Chat, msg)
}
-func (c *Ctx) SendMessage(msg *waE2E.Message) {
- c.client.SendMessage(stdctx.Background(), c.event.Info.Chat, msg)
+func (c *Ctx) SendMessage(msg *waE2E.Message, extra ...whatsmeow.SendRequestExtra) {
+ c.client.SendMessage(stdctx.Background(), c.event.Info.Chat, msg, extra...)
}
func (c *Ctx) React(emoji string) {
@@ -104,3 +109,58 @@ func (c *Ctx) SendPresence(composing bool) {
_ = c.client.SubscribePresence(stdctx.Background(), c.event.Info.Chat)
_ = c.client.SendChatPresence(stdctx.Background(), c.event.Info.Chat, state, waTypes.ChatPresenceMediaText)
}
+
+func (c *Ctx) SendInteractiveHTML(htmlContent string) (whatsmeow.SendResponse, error) {
+ responseID := uuid.New().String()
+
+ payload := map[string]interface{}{
+ "response_id": responseID,
+ "sections": []map[string]interface{}{
+ {
+ "view_model": map[string]interface{}{
+ "primitive": map[string]interface{}{
+ "__typename": "GenAIaeacdsnwHtmlPrimitive",
+ "payload": htmlContent,
+ "trusted_sources": []string{},
+ },
+ "__typename": "GenAISingleLayoutViewModel",
+ },
+ },
+ },
+ }
+
+ data, err := json.Marshal(payload)
+ if err != nil {
+ return whatsmeow.SendResponse{}, err
+ }
+
+ msg := &waE2E.Message{
+ BotForwardedMessage: &waE2E.FutureProofMessage{
+ Message: &waE2E.Message{
+ RichResponseMessage: &waE2E.AIRichResponseMessage{
+ MessageType: waAICommonDeprecated.AIRichResponseMessageType(1).Enum(),
+ Submessages: []*waAICommonDeprecated.AIRichResponseSubMessage{
+ {
+ MessageType: waAICommonDeprecated.AIRichResponseSubMessageType(2).Enum(),
+ MessageText: proto.String("Game Center"),
+ },
+ },
+ UnifiedResponse: &waAICommon.AIRichResponseUnifiedResponse{
+ Data: data,
+ },
+ ContextInfo: &waE2E.ContextInfo{
+ ForwardingScore: proto.Uint32(1),
+ IsForwarded: proto.Bool(true),
+ ForwardedAiBotMessageInfo: &waAICommon.ForwardedAIBotMessageInfo{
+ BotJID: proto.String("867051314767696@bot"),
+ },
+ },
+ },
+ },
+ },
+ }
+
+ return c.client.SendMessage(stdctx.Background(), c.event.Info.Chat, msg, whatsmeow.SendRequestExtra{
+ ID: responseID,
+ })
+}
diff --git a/go.mod b/go.mod
index 856e525..af86f28 100644
--- a/go.mod
+++ b/go.mod
@@ -1,15 +1,15 @@
module neo
-go 1.25.5
+go 1.26.0
require (
github.com/davidbyttow/govips/v2 v2.18.0
github.com/gabriel-vasile/mimetype v1.4.13
github.com/joho/godotenv v1.5.1
- github.com/mattn/go-sqlite3 v1.14.48
+ github.com/mattn/go-sqlite3 v1.14.49
github.com/mdp/qrterminal/v3 v3.2.1
- go.mau.fi/whatsmeow v0.0.0-20260630180629-b572e5bcb92b
- google.golang.org/protobuf v1.36.11
+ go.mau.fi/whatsmeow v0.0.0-20260828224850-0fadda796019
+ google.golang.org/protobuf v1.36.12
gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.2
)
@@ -18,24 +18,25 @@ require (
filippo.io/edwards25519 v1.2.0 // indirect
github.com/beeper/argo-go v1.1.2 // indirect
github.com/coder/websocket v1.8.15 // indirect
- github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
+ github.com/elliotchance/orderedmap/v3 v3.1.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
- github.com/mattn/go-colorable v0.1.14 // indirect
- github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect
+ github.com/mattn/go-colorable v0.1.15 // indirect
+ github.com/mattn/go-isatty v0.0.24 // indirect
+ github.com/petermattis/goid v0.0.0-20260816044145-ed329add6b1b // indirect
github.com/rs/zerolog v1.35.1 // indirect
- github.com/vektah/gqlparser/v2 v2.5.27 // indirect
+ github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
+ github.com/vektah/gqlparser/v2 v2.5.37 // indirect
go.mau.fi/libsignal v0.2.2 // indirect
- go.mau.fi/util v0.9.10 // indirect
- golang.org/x/crypto v0.54.0 // indirect
- golang.org/x/exp v0.0.0-20260611194520-c48552f49976 // indirect
+ go.mau.fi/util v0.10.1-0.20260820140024-eb612d936fde // indirect
+ golang.org/x/crypto v0.56.0 // indirect
+ golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297 // indirect
golang.org/x/image v0.44.0 // indirect
- golang.org/x/net v0.57.0 // indirect
+ golang.org/x/net v0.58.0 // indirect
golang.org/x/sync v0.22.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/term v0.45.0 // indirect
- golang.org/x/text v0.40.0 // indirect
+ golang.org/x/text v0.41.0 // indirect
rsc.io/qr v0.2.0 // indirect
)
diff --git a/go.sum b/go.sum
index 7b83f1e..1eb525c 100644
--- a/go.sum
+++ b/go.sum
@@ -16,6 +16,8 @@ github.com/davidbyttow/govips/v2 v2.18.0 h1:pZRshWVYvewP/TZx3yZ7YeC42WyLXg53tHy5
github.com/davidbyttow/govips/v2 v2.18.0/go.mod h1:8+nst5zfMoats12PgmmAPh6p5OfjDaXK0BXMFl/vOcM=
github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg=
github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo=
+github.com/elliotchance/orderedmap/v3 v3.1.1 h1:eV7lfZ5fVL8d36b8Wogqi/eqm7R/kZcftA9Yiyj+63M=
+github.com/elliotchance/orderedmap/v3 v3.1.1/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -30,38 +32,61 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
+github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
+github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
+github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs=
github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
+github.com/mattn/go-sqlite3 v1.14.49 h1:B8jBHC3xhxZgxztrgruTuLucebnULQnx4W7cF7SAE9w=
+github.com/mattn/go-sqlite3 v1.14.49/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4=
github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU=
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM=
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
+github.com/petermattis/goid v0.0.0-20260816044145-ed329add6b1b h1:sS7HLzwS+dO+gxATgQfeZDEdUZe2pKAB3nGoUwP5zU0=
+github.com/petermattis/goid v0.0.0-20260816044145-ed329add6b1b/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI=
github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
+github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
+github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
+github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s=
github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
+github.com/vektah/gqlparser/v2 v2.5.37 h1:jbb1Ilv+xBklV6653tKb4oVUupPNTLb5LmrnBKVI12Y=
+github.com/vektah/gqlparser/v2 v2.5.37/go.mod h1:9O4Ox6Ngd3Y12bMD3w6i3CRQXh8W1oC1q0m6olCymDM=
go.mau.fi/libsignal v0.2.2 h1:QV+XdzQkm3x3aSG7FcqfGSZuFXz83pRZPBFaPygHbOU=
go.mau.fi/libsignal v0.2.2/go.mod h1:CRlIQg2J8uYTfDFvNoO8/KcZjs5cey0vbc6oj/bssY0=
go.mau.fi/util v0.9.10 h1:wzvz5iDHyqDXB8vgisD4d3SzucLXNM3iNY+1O1RoHtg=
go.mau.fi/util v0.9.10/go.mod h1:YQOxySn+ZE3qSYqNxvyX7Yi3suA8YK17PS6QqBREW7A=
+go.mau.fi/util v0.10.1-0.20260820140024-eb612d936fde h1:eMHY9dMDkNuDMWhfTbMZHbbsxj7G6mfujjKei1HaFQM=
+go.mau.fi/util v0.10.1-0.20260820140024-eb612d936fde/go.mod h1:z0ZZNt4hq3FZbUKnunexE/QscCx7VkLvQSvtggc/aE8=
go.mau.fi/whatsmeow v0.0.0-20260630180629-b572e5bcb92b h1:ZUk1ErarDNpnbosXR/MeOz2gkqA4S1bh8zjaSRj7N+Y=
go.mau.fi/whatsmeow v0.0.0-20260630180629-b572e5bcb92b/go.mod h1:9dmNTYZ/1pHjPw/bz+azBsGjAkcrZbqzMrKcvG5bJ8U=
+go.mau.fi/whatsmeow v0.0.0-20260828224850-0fadda796019 h1:vUX4rgZhobwtMYH6tkYOSyfd2ufTysNEDWVpTSVPjmc=
+go.mau.fi/whatsmeow v0.0.0-20260828224850-0fadda796019/go.mod h1:aMd13H2xFFGH9cskcvxo4Aae+TmyFN38yw+HvsrpwVg=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
+golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=
+golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=
golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M=
golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY=
+golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297 h1:YXnL44eJ77R+ji4/ooy8UsXIhz+lbi2Qgdlc8iRN0gY=
+golang.org/x/exp v0.0.0-20260813180055-c1d0aacb2297/go.mod h1:Mkmymgv+uMpSQ/XxJ/7GpdrdYoqm3u72jEbpCLiJmNk=
golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I=
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
+golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
+golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -71,8 +96,12 @@ golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
+golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
+golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
+google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=