itzngga / Roxy

Command Handler Abstraction for Whatsapp Bot
GNU General Public License v3.0
21 stars 4 forks source link
golang whatsapp whatsapp-bot

GitHub Repo stars GitHub forks GitHub watchers GitHub code size in bytes

Roxy

Command Handler Abstraction for whatsmeow

Installation

go get github.com/itzngga/Roxy

Get Started

package main

import (
    _ "github.com/itzngga/Roxy/examples/cmd"
    "log"

    "github.com/itzngga/Roxy"
    "github.com/itzngga/Roxy/options"

    "os"
    "os/signal"
    "syscall"
)

func main() {
    app, err := roxy.NewRoxyBase(options.NewDefaultOptions())
    if err != nil {
        log.Fatal(err)
    }

    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    <-c
    app.Shutdown()
}

Config

default

app, err := roxy.NewRoxyBase(options.NewDefaultOptions())
if err != nil {
    log.Fatal(err)
}

custom

type Options struct {
    // HostNumber will use the first available device when null
    HostNumber string

    // StoreMode can be "postgres" or "sqlite"
    StoreMode string

    // LogLevel: "INFO", "ERROR", "WARN", "DEBUG"
    LogLevel string

    // This PostgresDsn Must add when StoreMode equal to "postgres"
    PostgresDsn *PostgresDSN

    // This SqliteFile Generate "ROXY.DB" when it null
    SqliteFile string

    // WithSqlDB wrap with sql.DB interface
    WithSqlDB *sql.DB

    WithCommandLog              bool
    CommandResponseCacheTimeout time.Duration
    SendMessageTimeout          time.Duration

    // OSInfo system name in client
    OSInfo string

    // LoginOptions constant of ScanQR or PairCode
    LoginOptions LoginOptions

    // HistorySync is used to synchronize message history
    HistorySync bool
    // AutoRejectCall allow to auto reject incoming calls
    AutoRejectCall bool

    // Bot General Settings

    // AllowFromPrivate allow messages from private
    AllowFromPrivate bool
    // AllowFromGroup allow message from groups
    AllowFromGroup bool
    // OnlyFromSelf allow only from self messages
    OnlyFromSelf bool
    // CommandSuggestion allow command suggestion
    CommandSuggestion bool
    // DebugMessage debug incoming message to console
    DebugMessage bool
}

PostgresSQL

from env

package main

import (
    roxy "github.com/itzngga/Roxy"
    _ "github.com/itzngga/Roxy/examples/cmd"
    "github.com/itzngga/Roxy/options"
    "github.com/joho/godotenv"

    "log"

    "os"
    "os/signal"
    "syscall"
)

func init() {
    err := godotenv.Load()
    if err != nil {
        panic(err)
    }
}

func main() {
    // Required ENV
    // PG_HOST : postgresql host
    // PG_PORT : postgresql port
    // PG_USERNAME : postgresql username
    // PG_PASSWORD : postgresql password
    // PG_DATABASE : postgresql database

    opt := options.NewDefaultOptions()
    opt.StoreMode = "postgres"
    opt.PostgresDsn = options.NewPostgresDSN().FromEnv()

    app, err := roxy.NewRoxyBase(opt)
    if err != nil {
        log.Fatal(err)
    }

    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    <-c
    app.Shutdown()
}

default parser

package main

import (
    roxy "github.com/itzngga/Roxy"
    _ "github.com/itzngga/Roxy/examples/cmd"
    "github.com/itzngga/Roxy/options"

    "log"

    "os"
    "os/signal"
    "syscall"
)

func main() {
    pg := options.NewPostgresDSN()
    pg.SetHost("localhost")
    pg.SetPort("4321")
    pg.SetUsername("postgres")
    pg.SetPassword("root123")
    pg.SetDatabase("roxy")

    opt := options.NewDefaultOptions()
    opt.StoreMode = "postgres"
    opt.PostgresDsn = pg

    app, err := roxy.NewRoxyBase(opt)
    if err != nil {
        log.Fatal(err)
    }

    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    <-c
    app.Shutdown()
}

Sqlite

package main

import (
    roxy "github.com/itzngga/Roxy"
    _ "github.com/itzngga/Roxy/examples/cmd"
    "github.com/itzngga/Roxy/options"

    "log"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    opt := options.NewDefaultOptions()
    app, err := roxy.NewRoxyBase(opt)
    if err != nil {
        log.Fatal(err)
    }

    c := make(chan os.Signal)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    <-c
    app.Shutdown()
}

Add a Command

create a simple command with:

command/hello_world.go

package cmd

import (
    "fmt"
    waProto "github.com/go-whatsapp/whatsmeow/binary/proto"
    "github.com/itzngga/Roxy"
    "github.com/itzngga/Roxy/context"
    "time"
)

func init() {
    roxy.Commands.Add(speed)
}

var speed = &roxy.Command{
    Name:        "speed",
    Description: "Testing speed",
    RunFunc: func(ctx *context.Ctx) *waProto.Message {
        t := time.Now()
        ctx.SendReplyMessage("wait...")
        return ctx.GenerateReplyMessage(fmt.Sprintf("Duration: %f seconds", time.Now().Sub(t).Seconds()))
    },
}

Create Question State

example with media question state

package media

import (
    "github.com/itzngga/Leficious/src/cmd/constant"
    "github.com/itzngga/Roxy"
    "github.com/itzngga/Roxy/context"
    "github.com/itzngga/Roxy/util/cli"
    waProto "github.com/go-whatsapp/whatsmeow/binary/proto"
    "log"
)

func init() {
    roxy.Commands.Add(ocr)
}

var ocr = &roxy.Command{
    Name:        "ocr",
    Category:    "media",
    Description: "Scan text on images",
    context: func(ctx *context.Ctx) *waProto.Message {
        var captured *waProto.Message
        ctx.NewUserQuestion().
            CaptureMediaQuestion("Please send/reply a media message", &captured).
            Exec()

        result, err := ctx.Download(captured, false)
        if err != nil {
            log.Fatal(err)
        }
        res := cli.ExecPipeline("tesseract", result, "stdin", "stdout", "-l", "ind", "--oem", "1", "--psm", "3", "-c", "preserve_interword_spaces=1")

        return ctx.GenerateReplyMessage(string(res))
    },
}

Example

currently available example project in Lara

Documentation

DOC

License

GNU

Contribute

Pull Request are pleased to