Compare commits
4
Commits
5f16856959
...
43a559bd55
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43a559bd55 | ||
|
|
6a4217960f | ||
|
|
d8b9f815c0 | ||
|
|
ef888b7256 |
+43
-27
@@ -3,6 +3,7 @@ package general
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
hc "neo/context"
|
hc "neo/context"
|
||||||
@@ -13,6 +14,38 @@ func init() {
|
|||||||
core.Default.Register(Help)
|
core.Default.Register(Help)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
cachedMenu string
|
||||||
|
menuOnce sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
// buildMenuCache generates the static portion of the help menu with a {{PREFIX}} placeholder
|
||||||
|
func buildMenuCache() {
|
||||||
|
var sb strings.Builder
|
||||||
|
|
||||||
|
cmdMap := make(map[string][]string)
|
||||||
|
for _, cmd := range core.Default.GetCommands() {
|
||||||
|
cat := cmd.Category
|
||||||
|
if cat == "" {
|
||||||
|
cat = "general"
|
||||||
|
}
|
||||||
|
cmdMap[cat] = append(cmdMap[cat], cmd.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
for cat, cmds := range cmdMap {
|
||||||
|
sb.WriteString(fmt.Sprintf("\n*📃%s*\n", strings.ToUpper(cat)))
|
||||||
|
for i, cmdName := range cmds {
|
||||||
|
branch := "├"
|
||||||
|
if i == len(cmds)-1 {
|
||||||
|
branch = "└"
|
||||||
|
}
|
||||||
|
sb.WriteString(fmt.Sprintf("%s {{PREFIX}}%s\n", branch, cmdName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedMenu = sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
var Help = &core.Command{
|
var Help = &core.Command{
|
||||||
Name: "help",
|
Name: "help",
|
||||||
Aliases: []string{"?", "h", "menu"},
|
Aliases: []string{"?", "h", "menu"},
|
||||||
@@ -42,38 +75,21 @@ var Help = &core.Command{
|
|||||||
pushName = "User"
|
pushName = "User"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header
|
|
||||||
var sb strings.Builder
|
|
||||||
sb.WriteString(fmt.Sprintf("%s *%s*👋\n📬 Need help? Here are all of my commands\n", greeting, pushName))
|
|
||||||
|
|
||||||
// Group commands by category (simulate json object array appending)
|
|
||||||
cmdMap := make(map[string][]string)
|
|
||||||
for _, cmd := range core.Default.GetCommands() {
|
|
||||||
cat := cmd.Category
|
|
||||||
if cat == "" {
|
|
||||||
cat = "general"
|
|
||||||
}
|
|
||||||
cmdMap[cat] = append(cmdMap[cat], cmd.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix := ctx.Prefix()
|
prefix := ctx.Prefix()
|
||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
// fallback if they called it somehow internally without prefix
|
|
||||||
prefix = "."
|
prefix = "."
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print categories
|
// Calculate the static command layout part only once
|
||||||
for cat, cmds := range cmdMap {
|
menuOnce.Do(func() {
|
||||||
sb.WriteString(fmt.Sprintf("\n*📃%s*\n", strings.ToUpper(cat)))
|
buildMenuCache()
|
||||||
for i, cmdName := range cmds {
|
})
|
||||||
branch := "├"
|
|
||||||
if i == len(cmds)-1 {
|
|
||||||
branch = "└"
|
|
||||||
}
|
|
||||||
sb.WriteString(fmt.Sprintf("%s %s%s\n", branch, prefix, cmdName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Reply(sb.String())
|
// Replace placeholder with the dynamically used prefix
|
||||||
|
finalMenu := strings.ReplaceAll(cachedMenu, "{{PREFIX}}", prefix)
|
||||||
|
|
||||||
|
header := fmt.Sprintf("%s *%s*👋\n📬 Need help? Here are all of my commands\n", greeting, pushName)
|
||||||
|
|
||||||
|
ctx.Reply(header + finalMenu)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-20
@@ -9,6 +9,8 @@ import (
|
|||||||
hc "neo/context"
|
hc "neo/context"
|
||||||
"neo/core"
|
"neo/core"
|
||||||
"neo/helper"
|
"neo/helper"
|
||||||
|
|
||||||
|
"go.mau.fi/whatsmeow"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() { core.Default.Register(Sticker) }
|
func init() { core.Default.Register(Sticker) }
|
||||||
@@ -50,29 +52,34 @@ var Sticker = &core.Command{
|
|||||||
var err error
|
var err error
|
||||||
var rawWebp []byte
|
var rawWebp []byte
|
||||||
var mediaData []byte
|
var mediaData []byte
|
||||||
|
var downloadable whatsmeow.DownloadableMessage
|
||||||
|
var mediaType string
|
||||||
|
|
||||||
if img := msg.GetImageMessage(); img != nil {
|
switch {
|
||||||
mediaData, err = ctx.Client().Download(context.Background(), img)
|
case msg.GetImageMessage() != nil:
|
||||||
|
downloadable, mediaType = msg.GetImageMessage(), "image"
|
||||||
|
case quoted != nil && quoted.GetImageMessage() != nil:
|
||||||
|
downloadable, mediaType = quoted.GetImageMessage(), "image"
|
||||||
|
case msg.GetVideoMessage() != nil:
|
||||||
|
downloadable, mediaType = msg.GetVideoMessage(), "video"
|
||||||
|
case quoted != nil && quoted.GetVideoMessage() != nil:
|
||||||
|
downloadable, mediaType = quoted.GetVideoMessage(), "video"
|
||||||
|
case quoted != nil && quoted.GetStickerMessage() != nil:
|
||||||
|
downloadable, mediaType = quoted.GetStickerMessage(), "sticker"
|
||||||
|
}
|
||||||
|
|
||||||
|
if downloadable != nil {
|
||||||
|
mediaData, err = ctx.Client().Download(context.Background(), downloadable)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rawWebp, err = helper.ConvertImageToWebp(mediaData)
|
switch mediaType {
|
||||||
|
case "image":
|
||||||
|
rawWebp, err = helper.ConvertImageToWebp(mediaData)
|
||||||
|
case "video":
|
||||||
|
rawWebp, err = helper.ConvertVideoToWebp(mediaData)
|
||||||
|
case "sticker":
|
||||||
|
rawWebp = mediaData
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if img := quoted.GetImageMessage(); img != nil && quoted != nil {
|
|
||||||
mediaData, err = ctx.Client().Download(context.Background(), img)
|
|
||||||
if err == nil {
|
|
||||||
rawWebp, err = helper.ConvertImageToWebp(mediaData)
|
|
||||||
}
|
|
||||||
} else if vid := msg.GetVideoMessage(); vid != nil {
|
|
||||||
mediaData, err = ctx.Client().Download(context.Background(), vid)
|
|
||||||
if err == nil {
|
|
||||||
rawWebp, err = helper.ConvertVideoToWebp(mediaData)
|
|
||||||
}
|
|
||||||
} else if vid := quoted.GetVideoMessage(); vid != nil && quoted != nil {
|
|
||||||
mediaData, err = ctx.Client().Download(context.Background(), vid)
|
|
||||||
if err == nil {
|
|
||||||
rawWebp, err = helper.ConvertVideoToWebp(mediaData)
|
|
||||||
}
|
|
||||||
} else if smsg := quoted.GetStickerMessage(); smsg != nil && quoted != nil {
|
|
||||||
rawWebp, err = ctx.Client().Download(context.Background(), smsg)
|
|
||||||
} else {
|
} else {
|
||||||
ctx.Reply("error: reply to image/video/sticker or send with caption")
|
ctx.Reply("error: reply to image/video/sticker or send with caption")
|
||||||
return
|
return
|
||||||
|
|||||||
+11
-23
@@ -3,11 +3,7 @@ package helper
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ConvertImageToWebp(imgData []byte) ([]byte, error) {
|
func ConvertImageToWebp(imgData []byte) ([]byte, error) {
|
||||||
@@ -35,35 +31,27 @@ func ConvertImageToWebp(imgData []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ConvertVideoToWebp(vidData []byte) ([]byte, error) {
|
func ConvertVideoToWebp(vidData []byte) ([]byte, error) {
|
||||||
id := uuid.New().String()
|
|
||||||
gifPath := filepath.Join("temp", fmt.Sprintf("%s.gif", id))
|
|
||||||
webpPath := filepath.Join("temp", fmt.Sprintf("%s.webp", id))
|
|
||||||
|
|
||||||
defer os.Remove(gifPath)
|
|
||||||
defer os.Remove(webpPath)
|
|
||||||
|
|
||||||
ffmpegCmd := exec.Command("ffmpeg",
|
ffmpegCmd := exec.Command("ffmpeg",
|
||||||
"-y", "-hide_banner", "-loglevel", "error",
|
"-y", "-hide_banner", "-loglevel", "error",
|
||||||
"-i", "pipe:0",
|
"-i", "pipe:0",
|
||||||
"-ss", "00:00:00", "-t", "00:00:15",
|
"-ss", "00:00:00", "-t", "00:00:15",
|
||||||
|
"-vcodec", "libwebp",
|
||||||
"-vf", "fps=10,scale=720:-1:flags=lanczos:force_original_aspect_ratio=increase,crop=512:512,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1",
|
"-vf", "fps=10,scale=720:-1:flags=lanczos:force_original_aspect_ratio=increase,crop=512:512,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1",
|
||||||
"-loop", "0",
|
"-loop", "0",
|
||||||
|
"-preset", "default",
|
||||||
"-an",
|
"-an",
|
||||||
"-f", "gif", gifPath,
|
"-f", "webp", "pipe:1",
|
||||||
)
|
)
|
||||||
var stderr bytes.Buffer
|
|
||||||
ffmpegCmd.Stderr = &stderr
|
|
||||||
ffmpegCmd.Stdin = bytes.NewReader(vidData)
|
ffmpegCmd.Stdin = bytes.NewReader(vidData)
|
||||||
|
var outBuf bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
ffmpegCmd.Stdout = &outBuf
|
||||||
|
ffmpegCmd.Stderr = &stderr
|
||||||
|
|
||||||
if err := ffmpegCmd.Run(); err != nil {
|
if err := ffmpegCmd.Run(); err != nil {
|
||||||
return nil, fmt.Errorf("ffmpeg failed: %w, stderr: %s", err, stderr.String())
|
return nil, fmt.Errorf("ffmpeg direct convert failed: %w, stderr: %s", err, stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
gif2webpCmd := exec.Command("gif2webp", "-quiet", "-q", "60", "-m", "6", gifPath, "-o", webpPath)
|
return outBuf.Bytes(), nil
|
||||||
var g2wStderr bytes.Buffer
|
|
||||||
gif2webpCmd.Stderr = &g2wStderr
|
|
||||||
if err := gif2webpCmd.Run(); err != nil {
|
|
||||||
return nil, fmt.Errorf("gif2webp failed: %w, stderr: %s", err, g2wStderr.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.ReadFile(webpPath)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user