Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .codegraph/.gitignore

This file was deleted.

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ docker/traefik/acme.json
docker/traefik/.env

# my personal compose
docker/docker-compose-local.yaml
docker/docker-compose-local.yaml

# codegraph
.codegraph
53 changes: 47 additions & 6 deletions cmd/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import (
"noirbot/internal/domain/repository"
"noirbot/internal/domain/service"
"noirbot/internal/gateways/deepseek"
"noirbot/internal/gateways/groq"
httpgw "noirbot/internal/gateways/http"
"noirbot/internal/gateways/memory"
redisstore "noirbot/internal/gateways/redis"
"noirbot/internal/gateways/telegram/files"
"noirbot/internal/gateways/telegram/inbound"
"noirbot/internal/gateways/telegram/outbound"
"noirbot/internal/usecase/handle_business_connection"
"noirbot/internal/usecase/handle_business_message"
"noirbot/internal/usecase/businessconn"
"noirbot/internal/usecase/businessmsg"
"noirbot/internal/usecase/longvoice"
"noirbot/pkg/config"
"os"

Expand All @@ -32,6 +35,7 @@ func main() {
newGreetingDetector,
newFloodDetector,
newShortVoiceDetector,
newLongVoiceDetector,
newVoiceReplyWindowStore,

newOwnerWhitelist,
Expand All @@ -44,11 +48,17 @@ func main() {
newDeepseekConfig,
newLLMClient,

newGroqConfig,
newTranscriber,
newVoiceDownloader,
newHandleLongVoiceConfig,
longvoice.New,

newRedisClient,

newHandleBusinessMessageConfig,
handle_business_connection.New,
handle_business_message.New,
businessconn.New,
businessmsg.New,

inbound.NewLazyHandler,
inbound.NewUpdateMapper,
Expand Down Expand Up @@ -168,8 +178,8 @@ func newLLMClient(c deepseek.Config) repository.LLMClient {
return deepseek.NewClient(c)
}

func newHandleBusinessMessageConfig(cfg *config.Config) handle_business_message.Config {
return handle_business_message.Config{
func newHandleBusinessMessageConfig(cfg *config.Config) businessmsg.Config {
return businessmsg.Config{
SystemPrompt: cfg.Bot.SystemPrompt,
ShortVoicePrompt: cfg.Bot.ShortVoicePrompt,
ShortVoiceResponseWindow: cfg.ShortVoice.ResponseWindow,
Expand All @@ -189,3 +199,34 @@ func newRedisClient(cfg *config.Config) *redis.Client {

return rdb
}

func newLongVoiceDetector(cfg *config.Config) *service.LongVoiceDetector {
return service.NewLongVoiceDetector(
service.LongVoiceDetectorConfig{
MaxDuration: cfg.LongVoice.MaxDuration,
},
)
}

func newGroqConfig(cfg *config.Config) groq.Config {
return groq.Config{
BaseURL: cfg.Groq.BaseURL,
APIKey: cfg.Groq.APIKey,
Model: cfg.Groq.Model,
Timeout: cfg.Groq.Timeout,
}
}

func newTranscriber(cfg groq.Config) repository.Transcriber {
return groq.NewClient(cfg)
}

func newVoiceDownloader(b *bot.Bot, cfg *config.Config) repository.VoiceDownloader {
return files.NewDownloader(b, cfg.Telegram.FileDownloadTimeout)
}

func newHandleLongVoiceConfig(cfg *config.Config) longvoice.Config {
return longvoice.Config{
LongVoicePrompt: cfg.Bot.LongVoicePrompt,
}
}
1 change: 1 addition & 0 deletions internal/domain/model/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type IncomingMessage struct {
Text string
VoiceDuration time.Duration
ReceivedAt time.Time
VoiceFileID string
}

type ReplyDraft struct {
Expand Down
1 change: 1 addition & 0 deletions internal/domain/model/trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const (
TriggerKindGreeting TriggerKind = "greeting"
TriggerKindFlood TriggerKind = "flood"
TriggerKindShortVoice TriggerKind = "short_voice"
TriggerKindLongVoice TriggerKind = "long_voice"
)

type TriggerDecision struct {
Expand Down
57 changes: 57 additions & 0 deletions internal/domain/repository/mock/transcriber.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions internal/domain/repository/mock/voice_downloader.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions internal/domain/repository/transcriber.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package repository

import (
"context"
"io"
)

//go:generate go tool mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock

type Transcriber interface {
Transcribe(ctx context.Context, reader io.ReadCloser) (string, error)
}
12 changes: 12 additions & 0 deletions internal/domain/repository/voice_downloader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package repository

import (
"context"
"io"
)

//go:generate go tool mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock

type VoiceDownloader interface {
Download(ctx context.Context, fileID string) (io.ReadCloser, error)
}
38 changes: 38 additions & 0 deletions internal/domain/service/long_voice_detector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package service

import (
"fmt"
"noirbot/internal/domain/model"
"time"
)

type LongVoiceDetectorConfig struct {
MinDuration time.Duration
MaxDuration time.Duration
}

type LongVoiceDetector struct {
cfg LongVoiceDetectorConfig
}

func NewLongVoiceDetector(cfg LongVoiceDetectorConfig) *LongVoiceDetector {
return &LongVoiceDetector{
cfg: cfg,
}
}

func (d *LongVoiceDetector) Detect(msg model.IncomingMessage) model.TriggerDecision {
switch {
case msg.Kind != model.MessageKindVoice:
return model.TriggerDecision{Kind: model.TriggerKindNone}
case msg.VoiceDuration <= d.cfg.MinDuration:
return model.TriggerDecision{Kind: model.TriggerKindNone}
case msg.VoiceDuration > d.cfg.MaxDuration:
return model.TriggerDecision{Kind: model.TriggerKindNone}
default:
return model.TriggerDecision{
Kind: model.TriggerKindLongVoice,
Reason: fmt.Sprintf("voice %s > %s <= %s", msg.VoiceDuration.String(), d.cfg.MinDuration.String(), d.cfg.MaxDuration.String()),
}
}
}
Loading