<repo><f p="audio.go"><![CDATA[package main
import (
 "fmt"
 "os/exec"
)
func ConvertAudio(inputPath, outputPath string) error {
 cmd := exec.Command("ffmpeg", "-i", inputPath, outputPath)
 output, err := cmd.CombinedOutput()
 if err != nil {
 return fmt.Errorf("FFmpeg conversion error: %v\nOutput: %s", err, string(output))
 }
 return nil
}]]></f><f p="main.go"><![CDATA[package main
import (
 "context"
 "fmt"
 "io"
 "log"
 "net/http"
 "os"
 "os/signal"
 "strings"
 "github.com/go-telegram/bot"
 "github.com/go-telegram/bot/models"
 "github.com/joho/godotenv"
 "github.com/tmc/langchaingo/llms"
 "github.com/tmc/langchaingo/llms/googleai"
)
var updatesChan = make(chan *models.Update, 100)
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
 if update.Message.Voice != nil {
 file, err := b.GetFile(ctx, &bot.GetFileParams{
 FileID: update.Message.Voice.FileID,
 })
 if err != nil {
 log.Printf("Error getting file: %v", err)
 return
 }
 downloadURL := b.FileDownloadLink(file)
 fmt.Println(downloadURL)
 resp, err := http.Get(downloadURL)
 if err != nil {
 log.Printf("Error downloading file: %v", err)
 return
 }
 defer resp.Body.Close()
 fileData, err := io.ReadAll(resp.Body)
 if err != nil {
 log.Printf("Error reading file: %v", err)
 return
 }
 fileName := file.FileUniqueID + ".oga"
 err = os.WriteFile(fileName, fileData, 0644)
 if err != nil {
 log.Fatal(err)
 }
 fileNameWithoutExtension := strings.Split(fileName, ".")
 fileNameWithWavExtension := fileNameWithoutExtension[0] + ".wav"
 ConvertAudio(fileName, fileNameWithWavExtension)
 finalFile, _ := os.ReadFile(fileNameWithWavExtension)
 ctx := context.Background()
 apiKey := os.Getenv("GOOGLE_API_KEY")
 llm, err := googleai.New(ctx, googleai.WithAPIKey(apiKey))
 if err != nil {
 log.Fatal(err)
 }
 systemPrompt := `
You will be sent audio files and they may be in variety of languages.
Try to classify what the user means, you have 3 options:
[NEW_REMINDER]
User wants to create a new reminder. Extract info what they need to be reminded of and when.
[NEW_TODO]
User wants to create some sort of TODO LIST. Extract all todos into array of strings [todo1,todo2]. dont translate it to english, keep language of the user.
[UNKNOWN]
Can't classify. Respond with what you understood from the user"`
 answer, err := llm.GenerateContent(
 ctx,
 []llms.MessageContent{
 {
 Role: llms.ChatMessageTypeHuman,
 Parts: []llms.ContentPart{
 llms.TextPart(systemPrompt),
 llms.BinaryPart("audio/wav", finalFile),
 },
 },
 },
 llms.WithMaxTokens(4000),
 llms.WithTemperature(0.1),
 llms.WithModel("gemini-1.5-pro"),
 )
 if err != nil {
 log.Fatal(err)
 }
 fmt.Println(answer)
 b.SendMessage(ctx, &bot.SendMessageParams{
 ChatID: update.Message.Chat.ID,
 Text: answer.Choices[0].Content,
 })
 }
}
func main() {
 if err := godotenv.Load(); err != nil {
 log.Fatalf("Error loading .env file: %v", err)
 }
 ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
 defer cancel()
 botToken := os.Getenv("TELEGRAM_API_KEY")
 if botToken == "" {
 log.Fatal("TELEGRAM_API_KEY is not set in the environment")
 }
 opts := []bot.Option{
 bot.WithDefaultHandler(handler),
 }
 b, err := bot.New(botToken, opts...)
 if err != nil {
 log.Fatalf("Failed to create bot: %v", err)
 }
 user, _ := b.GetMe(context.Background())
 fmt.Printf("User: %#v\n", user)
 go func() {
 for update := range updatesChan {
 if update.Message != nil {
 log.Printf("Received message from [%s]: %s", update.Message.From.Username, update.Message.Text)
 }
 }
 }()
 b.Start(ctx)
 close(updatesChan)
}]]></f></repo>
--------------

This is start of project. Restructure and organize it so that we can start building more modularily. 
This will be telegram bot for productivity. It will feature regular and voice commands. Todo's, notes and such. 
Implement best go practices, write idiomatic go, use interfaces, implement logging.