Skip to content

Commit

Permalink
track start params
Browse files Browse the repository at this point in the history
  • Loading branch information
radiantspace committed Oct 24, 2024
1 parent 358501e commit 92b4f80
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 23 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
.terraform.*
terraform.tfstate*
infra/kustomize/environment-properties.env
data/
data/
.env
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ help: ## show this help
.PHONY: start
start: ## start all services
@echo '$(HEADER) start'
docker-compose up
docker-compose -f docker-compose.cs.yml up

.PHONY: sl
sl: ## start start in local mode
@echo '$(HEADER) start'
docker-compose -f docker-compose.local.yml up


.PHONY: startd
startd: ## start all services as a daemon
Expand Down
26 changes: 26 additions & 0 deletions backend/app/db/mongo/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"regexp"
"strings"
"talk2robots/m/v2/app/config"
"talk2robots/m/v2/app/models"
Expand Down Expand Up @@ -50,6 +51,8 @@ type MongoClient interface {
DeleteUserThread(ctx context.Context) error
GetUserThread(ctx context.Context) (*models.MongoUserThread, error)
UpdateUserThread(ctx context.Context, thread *models.MongoUserThread) error

UpdateUserSourceModeLanguage(ctx context.Context, source string, mode string, language string) error
}

var MongoDBClient MongoClient
Expand Down Expand Up @@ -421,3 +424,26 @@ func (c *Client) AddToUserThread(ctx context.Context, thread *models.MongoUserTh

return c.UpdateUserThread(ctx, thread)
}

func (c *Client) UpdateUserSourceModeLanguage(ctx context.Context, source string, mode string, language string) error {
userId := ctx.Value(models.UserContext{}).(string)
collection := c.Database(config.CONFIG.MongoDBName).Collection(MongoUserCollection)

filter := bson.M{"_id": userId}
update := bson.M{
"$set": bson.M{
"source": sanitize(source),
"mode": sanitize(mode),
"language": sanitize(language),
},
}

options := options.Update().SetUpsert(true)
_, err := collection.UpdateOne(ctx, filter, update, options)
return err
}

func sanitize(s string) string {
// use regex to keep only english letters and digits
return regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAllString(s, "")
}
5 changes: 5 additions & 0 deletions backend/app/models/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ type MongoUser struct {
Usage float64 `bson:"usage"`
LastUsedAt string `bson:"last_used_at"`
LastNotifiedAt string `bson:"last_notified_at"`

// Start params
Source string `bson:"source"`
Mode string `bson:"mode"`
Language string `bson:"language"`
}

type MongoSubscription struct {
Expand Down
97 changes: 76 additions & 21 deletions backend/app/telegram/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,27 +94,7 @@ type CommandHandlers []*CommandHandler
func setupCommandHandlers() {
AllCommandHandlers = []*CommandHandler{
newCommandHandler(EmptyCommand, emptyCommandHandler),
newCommandHandler(StartCommand, func(ctx context.Context, bot *Bot, message *telego.Message) {
notification := lib.AddBotSuffixToGroupCommands(ctx, ONBOARDING_TEXT)
_, err := bot.SendMessage(tu.Message(util.GetChatID(message), notification).WithMessageThreadID(message.MessageThreadID).WithReplyMarkup(GetStatusKeyboard(ctx)))
if err != nil {
log.Errorf("Failed to send StartCommand message: %v", err)
}
// try getting onboarding video from redis and sending it to the user
videoFileId := redis.RedisClient.Get(ctx, "onboarding-video").Val()
if videoFileId == "" || videoFileId == "get onboarding-video: redis: nil" {
log.Errorf("Failed to get onboarding video from redis: %v", err)
return
}
log.Infof("Sending onboarding video %s to userID: %s", videoFileId, util.GetChatIDString(message))
_, err = bot.SendVideo(&telego.SendVideoParams{
ChatID: util.GetChatID(message),
Video: telego.InputFile{FileID: videoFileId},
})
if err != nil {
log.Errorf("Failed to send onboarding video: %v", err)
}
}),
newCommandHandler(StartCommand, startCommandHandler),
newCommandHandler(EmiliCommand, getModeHandlerFunction(lib.Emili, "היי, אעזור עם הטקסטים והודעות בעברית."+"\n\n"+fmt.Sprintf("אגב, אני בת %.f שעות, כלומר %.f ימים, %.f שבועות, %.1f חודשים או %.1f שנים", time.Since(EMILY_BIRTHDAY).Hours(), time.Since(EMILY_BIRTHDAY).Hours()/24, time.Since(EMILY_BIRTHDAY).Hours()/24/7, 12*(time.Since(EMILY_BIRTHDAY).Hours()/24/365), time.Since(EMILY_BIRTHDAY).Hours()/24/365))),
newCommandHandler(VasilisaCommand, getModeHandlerFunction(lib.Vasilisa, "Привет, я помогу тебе с текстами и сообщениями на русском языке 😊\n\n"+fmt.Sprintf("Кстати, мне %.f часов, то есть %.f дней или %.1f лет", time.Since(VASILISA_BIRTHDAY).Hours(), time.Since(VASILISA_BIRTHDAY).Hours()/24, time.Since(VASILISA_BIRTHDAY).Hours()/24/365))),
newCommandHandler(ChatGPTCommand, getModeHandlerFunction(lib.ChatGPT, "🚀 ChatGPT is now fully unleashed! Just tell me or ask me anything you want. I can now remember the context of our conversation. You can use /clear command anytime to wipe my memory and start a new thread.")),
Expand Down Expand Up @@ -882,3 +862,78 @@ func contains(arr []string, word string) bool {
}
return false
}

func startCommandHandler(ctx context.Context, bot *Bot, message *telego.Message) {
params := ""
startCommandParams := strings.Split(message.Text, " ")
if len(startCommandParams) > 1 {
params = startCommandParams[1]
if len(startCommandParams) > 64 {
params = ""
// ignore params longer than 64 characters
// https://core.telegram.org/api/links#bot-links
} else {
// base64 decode params
decoded := util.Base64Decode(params)
if decoded != "" {
params = decoded
}
}
}
ddParams := params
if ddParams == "" {
ddParams = "empty"
}
log.Infof("Start command params: %s", params)
if params != "" {
// parse format: s=web&m=transcribe&l=es
// s - source, m - mode, l - language
source := ""
mode := ""
language := ""
paramsArray := strings.Split(params, "&")
for _, param := range paramsArray {
paramArray := strings.Split(param, "=")
if len(paramArray) == 2 {
switch strings.ToLower(paramArray[0]) {
case "s":
// source
source = paramArray[1]
case "m":
// mode
mode = paramArray[1]
case "l":
// language
language = paramArray[1]
default:
log.Warnf("Unknown start command param: %s", param)
}
}
}

config.CONFIG.DataDogClient.Incr("start_command", []string{"source:" + source, "mode:" + mode, "language:" + language}, 1)
go mongo.MongoDBClient.UpdateUserSourceModeLanguage(ctx, source, mode, language)
} else {
config.CONFIG.DataDogClient.Incr("start_command", []string{"source:empty", "mode:empty", "language:empty"}, 1)
}

notification := lib.AddBotSuffixToGroupCommands(ctx, ONBOARDING_TEXT)
_, err := bot.SendMessage(tu.Message(util.GetChatID(message), notification).WithMessageThreadID(message.MessageThreadID).WithReplyMarkup(GetStatusKeyboard(ctx)))
if err != nil {
log.Errorf("Failed to send StartCommand message: %v", err)
}
// try getting onboarding video from redis and sending it to the user
videoFileId := redis.RedisClient.Get(ctx, "onboarding-video").Val()
if videoFileId == "" || videoFileId == "get onboarding-video: redis: nil" {
log.Errorf("Failed to get onboarding video from redis: %v", err)
return
}
log.Infof("Sending onboarding video %s to userID: %s", videoFileId, util.GetChatIDString(message))
_, err = bot.SendVideo(&telego.SendVideoParams{
ChatID: util.GetChatID(message),
Video: telego.InputFile{FileID: videoFileId},
})
if err != nil {
log.Errorf("Failed to send onboarding video: %v", err)
}
}
10 changes: 10 additions & 0 deletions backend/app/util/util.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package util

import (
"encoding/base64"
"fmt"
"os"
"strings"
Expand Down Expand Up @@ -148,3 +149,12 @@ func SafeOsDelete(filename string) {
log.Errorf("Error deleting file %s: %v", filename, err)
}
}

func Base64Decode(s string) string {
decoded, err := base64.StdEncoding.DecodeString(s)
if err != nil {
log.Errorf("Error decoding base64 string: %v", err)
return ""
}
return string(decoded)
}
File renamed without changes.
70 changes: 70 additions & 0 deletions docker-compose.local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
version: '3.7'

services:
backend:
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
depends_on:
- mongo
- redis
restart: always
environment:
REDIS_HOST: redis
REDIS_PASSWORD: ""
BACKEND_BASE_URL: ${NGROK_HOST}
BACKEND_LISTEN_ADDRESS: 0.0.0.0:8080
BACKEND_LISTEN_URL: http://0.0.0.0:8080
CLAUDE_API_KEY:
OPENAI_API_KEY:
FIREWORKS_API_KEY:
STRIPE_TOKEN: setup-for-testing
TELEGRAM_BOT_TOKEN:
MONGO_DB_CONNECTION_STRING: mongodb://root:example@mongo:27017/?tls=false
MONGO_DB_NAME: test
SLACK_BOT_TOKEN: dev
SLACK_SIGNING_SECRET: dev
STRIPE_ENDPOINT_SECRET: dev
STRIPE_ENDPOINT_SUFFIX: dev

# setup to enable telegram system notifications
TELEGRAM_SYSTEM_TOKEN: ""
TELEGRAM_SYSTEM_TO: ""
networks:
- my_network
volumes:
- ./data:/data

nginx:
image: nginx:1.19-alpine
restart: always
depends_on:
- backend
volumes:
- ./infra/nginx-dev/nginx.conf:/etc/nginx/nginx.conf
networks:
- my_network

mongo:
image: mongo:6.0.4
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
networks:
- my_network

redis:
image: redis:7.0.9-alpine
restart: always
environment:
REDIS_PASSWORD: example
networks:
- my_network


networks:
my_network:
driver: bridge

0 comments on commit 92b4f80

Please sign in to comment.