2026-03-16 19:52:29 +00:00
|
|
|
package platform
|
2025-12-16 16:37:53 +00:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
|
2026-01-07 16:07:51 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/config"
|
2026-01-06 22:23:59 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
2025-12-16 16:37:53 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/label-studio"
|
|
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/minio"
|
2026-03-16 19:52:29 +00:00
|
|
|
//"github.com/google/uuid"
|
2025-12-16 16:37:53 +00:00
|
|
|
)
|
|
|
|
|
|
2026-03-16 19:52:29 +00:00
|
|
|
var labelStudioClient *labelstudio.Client
|
|
|
|
|
var labelStudioProject *labelstudio.Project
|
|
|
|
|
var minioClient *minio.Client
|
2025-12-16 16:37:53 +00:00
|
|
|
|
2026-03-16 19:52:29 +00:00
|
|
|
func initializeLabelStudio() error {
|
2025-12-16 16:37:53 +00:00
|
|
|
return nil
|
2026-03-18 15:36:20 +00:00
|
|
|
/*
|
|
|
|
|
// Initialize the minio client
|
|
|
|
|
//minioBucket := os.Getenv("S3_BUCKET")
|
|
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
labelStudioClient, err = createLabelStudioClient()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to create label studio client: %w", err)
|
|
|
|
|
}
|
|
|
|
|
// Get the project we are going to upload to
|
|
|
|
|
labelStudioProject, err = findLabelStudioProject(labelStudioClient, "Nidus Speech-to-Text Transcriptions")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to find the label studio project: %w", err)
|
|
|
|
|
}
|
|
|
|
|
minioClient, err = createMinioClient()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to create minio client: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
*/
|
2025-12-16 16:37:53 +00:00
|
|
|
}
|
|
|
|
|
func createMinioClient() (*minio.Client, error) {
|
|
|
|
|
baseUrl := os.Getenv("S3_BASE_URL")
|
|
|
|
|
accessKeyID := os.Getenv("S3_ACCESS_KEY_ID")
|
|
|
|
|
secretAccessKey := os.Getenv("S3_SECRET_ACCESS_KEY")
|
|
|
|
|
|
|
|
|
|
client, err := minio.NewClient(baseUrl, accessKeyID, secretAccessKey)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
log.Println("Created minio client")
|
|
|
|
|
return client, err
|
|
|
|
|
}
|
|
|
|
|
func createLabelStudioClient() (*labelstudio.Client, error) {
|
|
|
|
|
// Initialize the client with your Label Studio base URL and API key
|
|
|
|
|
labelStudioApiKey := os.Getenv("LABEL_STUDIO_API_KEY")
|
|
|
|
|
labelStudioBaseUrl := os.Getenv("LABEL_STUDIO_BASE_URL")
|
|
|
|
|
labelStudioClient := labelstudio.NewClient(labelStudioBaseUrl, labelStudioApiKey)
|
|
|
|
|
log.Println("Created label studio client")
|
|
|
|
|
|
|
|
|
|
// Get and store the access token
|
|
|
|
|
err := labelStudioClient.GetAccessToken()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.New(fmt.Sprintf("Failed to get access token: %v", err))
|
|
|
|
|
}
|
|
|
|
|
log.Println("Got label studio client access token")
|
|
|
|
|
|
|
|
|
|
return labelStudioClient, nil
|
|
|
|
|
}
|
2026-03-12 23:49:16 +00:00
|
|
|
func noteAudioGetLatest(ctx context.Context, uuid string) (*models.NoteAudio, error) {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
2026-04-17 22:53:23 +00:00
|
|
|
func jobLabelStudioAudioCreate(ctx context.Context, row_id int32) error {
|
2026-03-16 19:52:29 +00:00
|
|
|
return fmt.Errorf("label studio integration has been disabled")
|
|
|
|
|
/*
|
|
|
|
|
customer := os.Getenv("CUSTOMER")
|
|
|
|
|
if customer == "" {
|
|
|
|
|
return errors.New("You must specify a CUSTOMER env var")
|
|
|
|
|
}
|
|
|
|
|
note, err := noteAudioGetLatest(ctx, job.UUID.String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.New(fmt.Sprintf("Failed to get note %s", note.UUID))
|
|
|
|
|
}
|
2025-12-16 16:37:53 +00:00
|
|
|
|
2026-03-16 19:52:29 +00:00
|
|
|
if note.Version != 1 {
|
|
|
|
|
return errors.New(fmt.Sprintf("Got version %d of %s", note.Version, note.UUID))
|
|
|
|
|
}
|
|
|
|
|
task, err := findMatchingTask(labelStudioClient, project, customer, note)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.New(fmt.Sprintf("Failed to search for a task: %v", err))
|
|
|
|
|
}
|
|
|
|
|
// We already have a task, nothing to do.
|
|
|
|
|
if task != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2025-12-16 16:37:53 +00:00
|
|
|
|
2026-03-16 19:52:29 +00:00
|
|
|
err = createTask(labelStudioClient, project, minioClient, minioBucket, customer, note)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.New(fmt.Sprintf("Failed to create a task: %v", err))
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
*/
|
2025-12-16 16:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
2026-01-06 22:23:59 +00:00
|
|
|
func createTask(client *labelstudio.Client, project *labelstudio.Project, minioClient *minio.Client, bucket string, customer string, note *models.NoteAudio) error {
|
2025-12-16 16:37:53 +00:00
|
|
|
audioRef := fmt.Sprintf("s3://%s/%s-normalized.m4a", bucket, note.UUID)
|
2026-02-08 00:58:51 +00:00
|
|
|
audioFile := fmt.Sprintf("%s/user/%s-normalized.m4a", config.FilesDirectory, note.UUID)
|
2025-12-16 16:37:53 +00:00
|
|
|
uploadPath := fmt.Sprintf("%s-normalized.m4a", note.UUID)
|
|
|
|
|
|
|
|
|
|
if !minioClient.ObjectExists(bucket, uploadPath) {
|
|
|
|
|
err := minioClient.UploadFile(bucket, audioFile, uploadPath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to upload audio: %v", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var transcription string = ""
|
|
|
|
|
//if note.Transcription.IsValue() {
|
2026-01-06 22:23:59 +00:00
|
|
|
//transcription = note.Transcription.MustGet()
|
2025-12-16 16:37:53 +00:00
|
|
|
//}
|
2026-01-06 22:23:59 +00:00
|
|
|
transcription = note.Transcription.GetOr("")
|
2025-12-16 16:37:53 +00:00
|
|
|
simpleTasks := []map[string]interface{}{
|
|
|
|
|
{
|
|
|
|
|
"data": map[string]string{
|
|
|
|
|
"audio": audioRef,
|
|
|
|
|
"note_uuid": note.UUID.String(),
|
|
|
|
|
"transcription": transcription,
|
|
|
|
|
},
|
|
|
|
|
"meta": map[string]string{
|
|
|
|
|
"customer": customer,
|
|
|
|
|
"note_uuid": note.UUID.String(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
_, err := client.ImportTasks(project.ID, simpleTasks)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Failed to import tasks: %v", err)
|
|
|
|
|
}
|
|
|
|
|
log.Printf("Created task for note audio %s", note.UUID)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func findLabelStudioProject(client *labelstudio.Client, title string) (*labelstudio.Project, error) {
|
|
|
|
|
// Attempt to get live projects
|
|
|
|
|
projects, err := client.Projects()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("Failed to get projects: %v", err)
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("Found %d projects:\n", projects.Count)
|
|
|
|
|
for i, p := range projects.Results {
|
|
|
|
|
fmt.Printf("%d. %s (ID: %d) - Tasks: %d\n",
|
|
|
|
|
i+1,
|
|
|
|
|
p.Title,
|
|
|
|
|
p.ID,
|
|
|
|
|
p.TaskNumber)
|
|
|
|
|
if p.Title == title {
|
|
|
|
|
return &p, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil, fmt.Errorf("No such project '%s'", title)
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-06 22:23:59 +00:00
|
|
|
func findMatchingTask(client *labelstudio.Client, project *labelstudio.Project, customer string, note *models.NoteAudio) (*labelstudio.Task, error) {
|
2025-12-16 16:37:53 +00:00
|
|
|
/*meta := map[string]string{
|
|
|
|
|
"customer": customer,
|
|
|
|
|
"note_uuid": note.UUID,
|
|
|
|
|
}*/
|
|
|
|
|
items := []map[string]interface{}{
|
|
|
|
|
{"filter": "filter:tasks:data.note_uuid", "operator": "equal", "type": "string", "value": note.UUID},
|
|
|
|
|
}
|
|
|
|
|
filters := map[string]interface{}{
|
|
|
|
|
"conjunction": "and",
|
|
|
|
|
"items": items,
|
|
|
|
|
}
|
|
|
|
|
query := map[string]interface{}{
|
|
|
|
|
"filters": filters,
|
|
|
|
|
}
|
|
|
|
|
queryStr, err := json.Marshal(query)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("Failed to marshal query JSON: %v", err)
|
|
|
|
|
}
|
|
|
|
|
// Get all tasks
|
|
|
|
|
options := &labelstudio.TasksListOptions{
|
|
|
|
|
ProjectID: project.ID,
|
|
|
|
|
Query: string(queryStr),
|
|
|
|
|
}
|
|
|
|
|
tasksResponse, err := client.ListTasks(options)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("Failed to get tasks: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if len(tasksResponse.Tasks) == 0 {
|
|
|
|
|
return nil, nil
|
|
|
|
|
} else if len(tasksResponse.Tasks) == 1 {
|
|
|
|
|
return &tasksResponse.Tasks[0], nil
|
|
|
|
|
} else {
|
|
|
|
|
return nil, fmt.Errorf("Got too many tasks: %d", len(tasksResponse.Tasks))
|
|
|
|
|
}
|
|
|
|
|
// Specify bucket name
|
|
|
|
|
//bucketNamePtr := flag.String("bucket", "label-studio", "The bucket to upload to")
|
|
|
|
|
//filePathPtr := flag.String("file", "example.txt", "The file to upload")
|
|
|
|
|
//flag.Parse()
|
|
|
|
|
}
|