Skip to content

Commit

Permalink
internal/plugin,internal/telegram,internal/tts: add tts command
Browse files Browse the repository at this point in the history
  • Loading branch information
scbizu committed Nov 27, 2023
1 parent 421b394 commit 596075c
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 37 deletions.
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ require (

replace github.com/bwmarrin/discordgo v0.23.2 => github.com/bwmarrin/discordgo v0.23.3-0.20211010150959-f0b7e81468f7

require github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
require (
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
github.com/rakyll/openai-go v1.0.9
)

require (
github.com/gorilla/websocket v1.4.2 // indirect
github.com/rakyll/openai-go v1.0.9 // indirect
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions internal/plugin/ai/ai.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ func (ai *AICommands) Enable() bool {
return true
}

func (ai *AICommands) Process(msg *tgbotapi.Message) tgbotapi.MessageConfig {
func (ai *AICommands) Process(msg *tgbotapi.Message) tgbotapi.Chattable {
cmd := command.NewCommand(
command.CommandAIChat,
"chat with openAI",
func(msg *tgbotapi.Message) tgbotapi.MessageConfig {
func(msg *tgbotapi.Message) tgbotapi.Chattable {
resp, err := openai.GetOpenAIClient().CreateCompletion(context.TODO(), &chat.CreateCompletionParams{
Messages: []*chat.Message{
{Role: "user", Content: msg.Text},
Expand Down
11 changes: 7 additions & 4 deletions internal/plugin/hub/hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,15 @@ func (ph *TGPluginHub) AddTGPlugin(
}

// Do iters telegram plugin
func (ph *TGPluginHub) Do(rawmsg *tgbotapi.Message) (msg tgbotapi.MessageConfig) {
func (ph *TGPluginHub) Do(rawmsg *tgbotapi.Message) (msg tgbotapi.Chattable) {
for _, p := range ph.GetEnabledTelegramPlugins() {
msg, _ = p.Run(rawmsg)
logrus.Infof("[chatID:%d,msg:%s]", msg.ChatID, msg.Text)
if p.Validate(msg) {
return
if _, ok := msg.(tgbotapi.MessageConfig); ok {
msgConf := msg.(tgbotapi.MessageConfig)
logrus.Infof("[chatID:%d,msg:%s]", msgConf.ChatID, msgConf.Text)
if p.Validate(msgConf) {
return
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions internal/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ type Handler func(msg *tgbotapi.Message) tgbotapi.MessageConfig
// TGPlugin defines the common telegram plugin
type TGPlugin struct {
enable bool
configure tgbotapi.MessageConfig
configure tgbotapi.Chattable
name string
}

type IPlugin interface {
Name() command.CommanderName
Enable() bool
Process(*tgbotapi.Message) tgbotapi.MessageConfig
Process(*tgbotapi.Message) tgbotapi.Chattable
}

// NewTGPlugin init the tg plugin
func NewTGPlugin(name command.CommanderName,
conf tgbotapi.MessageConfig,
conf tgbotapi.Chattable,
) *TGPlugin {
return &TGPlugin{
enable: true,
Expand All @@ -40,7 +40,7 @@ func (p *TGPlugin) IsPluginEnable() bool {
}

// Run runs the enabled plugins
func (p *TGPlugin) Run(msg *tgbotapi.Message) (tgbotapi.MessageConfig, error) {
func (p *TGPlugin) Run(msg *tgbotapi.Message) (tgbotapi.Chattable, error) {
if p.enable {
return p.configure, nil
}
Expand Down
4 changes: 2 additions & 2 deletions internal/plugin/py/py.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ var _ plugin.IPlugin = (*Handler)(nil)
type Handler struct{}

// Register regists py plugin
func (h *Handler) Process(msg *tgbotapi.Message) tgbotapi.MessageConfig {
pyHandler := func(msg *tgbotapi.Message) tgbotapi.MessageConfig {
func (h *Handler) Process(msg *tgbotapi.Message) tgbotapi.Chattable {
pyHandler := func(msg *tgbotapi.Message) tgbotapi.Chattable {
pyStr := format(command.GetAllCommands())
return tgbotapi.NewMessage(msg.Chat.ID, pyStr)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/plugin/sayhi/sayhi.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func (h *Handler) Enable() bool {
}

// Register regists sayhi plugin
func (h *Handler) Process(msg *tgbotapi.Message) tgbotapi.MessageConfig {
sayHandler := func(msg *tgbotapi.Message) tgbotapi.MessageConfig {
func (h *Handler) Process(msg *tgbotapi.Message) tgbotapi.Chattable {
sayHandler := func(msg *tgbotapi.Message) tgbotapi.Chattable {
user := msg.From.UserName
if user == masterName {
user = "master"
Expand Down
4 changes: 2 additions & 2 deletions internal/plugin/today-anime/anime.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ var _ plugin.IPlugin = (*Handler)(nil)
type Handler struct{}

// Register register anime plugin
func (h *Handler) Process(msg *tgbotapi.Message) tgbotapi.MessageConfig {
handler := func(msg *tgbotapi.Message) tgbotapi.MessageConfig {
func (h *Handler) Process(msg *tgbotapi.Message) tgbotapi.Chattable {
handler := func(msg *tgbotapi.Message) tgbotapi.Chattable {
return tgbotapi.MessageConfig{
BaseChat: tgbotapi.BaseChat{
ChatID: msg.Chat.ID,
Expand Down
42 changes: 42 additions & 0 deletions internal/plugin/tts/tts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package tts

import (
"context"
"fmt"

tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/scbizu/Astral/internal/plugin"
"github.com/scbizu/Astral/internal/telegram/command"
itts "github.com/scbizu/Astral/internal/tts"
)

var _ plugin.IPlugin = (*TTSCommand)(nil)

type TTSCommand struct{}

func (t *TTSCommand) Name() command.CommanderName {
return command.CommandTTS
}

func (t *TTSCommand) Enable() bool {
return true
}

func (t *TTSCommand) Process(msg *tgbotapi.Message) tgbotapi.Chattable {
cmd := command.NewCommand(
command.CommandTTS,
"tts",
func(msg *tgbotapi.Message) tgbotapi.Chattable {
c := itts.NewElevenLabClient()
bs, err := c.ToSpeech(context.Background(), msg.Text)
if err != nil {
return tgbotapi.NewMessage(msg.Chat.ID, err.Error())
}
return tgbotapi.NewVoice(msg.Chat.ID, tgbotapi.FileBytes{
Name: fmt.Sprintf("%s.mp3", msg.Text),
Bytes: bs,
})
},
)
return cmd.Do(msg)
}
8 changes: 5 additions & 3 deletions internal/telegram/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

// Handler defines handle func
type Handler func(msg *tgbotapi.Message) tgbotapi.MessageConfig
type Handler func(msg *tgbotapi.Message) tgbotapi.Chattable

// CommanderName defines command's literal name
type CommanderName string
Expand All @@ -30,12 +30,14 @@ const (
CommandShowAllCommand CommanderName = "show_commands"
// CommandAIChat makes bot chat with you
CommandAIChat CommanderName = "chat"
// CommandTTS makes bot say something
CommandTTS CommanderName = "tts"
)

var allCommandsMapping *sync.Map

// DefaultBehavior defines the default behavior of commander
var DefaultBehavior = func(msg *tgbotapi.Message) tgbotapi.MessageConfig {
var DefaultBehavior = func(msg *tgbotapi.Message) tgbotapi.Chattable {
defaultText := fmt.Sprintf("%s 命中了,但是作者什么都没有实现哦😞", msg.Command())
return tgbotapi.NewMessage(msg.Chat.ID, defaultText)
}
Expand Down Expand Up @@ -65,7 +67,7 @@ func (c CommanderName) String() string {
}

// Do will run the command behavior
func (c *Commander) Do(msg *tgbotapi.Message) tgbotapi.MessageConfig {
func (c *Commander) Do(msg *tgbotapi.Message) tgbotapi.Chattable {
if msg.Command() != string(c.Name) {
logrus.Infof("%s skiped command %s", msg.Command(), string(c.Name))
return tgbotapi.MessageConfig{}
Expand Down
33 changes: 17 additions & 16 deletions internal/telegram/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,24 @@ func (b *Bot) ServeBotUpdateMessage() error {
}
pluginHub := hub.NewTGPluginHub(update.Message)
msg := pluginHub.Do(update.Message)
if isMsgBadRequest(msg) {
continue
}

mbNames, ok := isMsgNewMember(update)
if ok {
msg = tgbotapi.NewMessage(update.Message.Chat.ID, fmt.Sprintf("撒花欢迎新基佬(%v)入群", mbNames))
if msgConf, ok := msg.(tgbotapi.MessageConfig); ok {
if isMsgBadRequest(msgConf) {
continue
}
mbNames, ok := isMsgNewMember(update)
if ok {
msgConf = tgbotapi.NewMessage(update.Message.Chat.ID, fmt.Sprintf("撒花欢迎新基佬(%v)入群", mbNames))
}
_, ok = isMsgLeftMember(update)
if ok {
// drop the member left message
continue
}
msgConf.ReplyToMessageID = update.Message.MessageID
b.bot.Send(msgConf)
} else {
b.bot.Send(msg)
}

_, ok = isMsgLeftMember(update)
if ok {
// drop the member left message
continue
}

msg.ReplyToMessageID = update.Message.MessageID
b.bot.Send(msg)
}
return nil
}
Expand Down
61 changes: 61 additions & 0 deletions internal/tts/eleven_lab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package tts

import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"os"
)

type Client struct {
domain string
voiceID string
apiKey string
model string
}

func NewElevenLabClient() *Client {
return &Client{
domain: "https://api.elevenlabs.io/v1/text-to-speech/",
voiceID: "21m00Tcm4TlvDq8ikWAM",
apiKey: os.Getenv("ELEVEN_LAB_API_KEY"),
model: "eleven_monolingual_v2",
}
}

func (c *Client) ToSpeech(ctx context.Context, text string) ([]byte, error) {
u, err := url.JoinPath(c.domain, c.voiceID)
if err != nil {
return nil, err
}
body := make(map[string]any)
body["text"] = text
body["model_id"] = c.model
body["voice_setting"] = map[string]any{
"stability": 0.5,
"similarity_boost": 0.5,
}
bodyBytes := bytes.NewBuffer(nil)
if err := json.NewEncoder(bodyBytes).Encode(body); err != nil {
return nil, err
}
req, err := http.NewRequest(http.MethodPost, u, bodyBytes)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req.WithContext(ctx))
if err != nil {
return nil, err
}
defer resp.Body.Close()

respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

return respBody, nil
}

0 comments on commit 596075c

Please sign in to comment.