diff --git a/api/api.go b/api/api.go index e0b0e702..aff1bb40 100644 --- a/api/api.go +++ b/api/api.go @@ -16,6 +16,8 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/queue" "github.com/Gleipnir-Technology/nidus-sync/userfile" + "github.com/aarondl/opt/omit" + "github.com/aarondl/opt/omitnull" "github.com/go-chi/chi/v5" "github.com/go-chi/render" "github.com/google/uuid" @@ -41,7 +43,18 @@ func apiAudioPost(w http.ResponseWriter, r *http.Request, u *models.User) { http.Error(w, "Failed to decode the payload", http.StatusBadRequest) return } - if err := db.NoteAudioCreate(context.Background(), noteUUID, db.NoteAudio{}, u.ID); err != nil { + setter := models.NoteAudioSetter{ + Created: omit.From(payload.Created), + CreatorID: omit.From(u.ID), + Deleted: omitnull.FromPtr(payload.Deleted), + DeletorID: omitnull.FromPtr(payload.DeletorID), + Duration: omit.From(payload.Duration), + Transcription: omitnull.FromPtr(payload.Transcription), + TranscriptionUserEdited: omit.From(payload.TranscriptionUserEdited), + Version: omit.From(payload.Version), + UUID: omit.From(noteUUID), + } + if err := db.NoteAudioCreate(context.Background(), u.R.Organization, u.ID, setter); err != nil { render.Render(w, r, errRender(err)) return } @@ -92,8 +105,15 @@ func handleClientIos(w http.ResponseWriter, r *http.Request, u *models.User) { return } + var since_used time.Time + if since == nil { + since_used = time.Unix(0, 0) + } else { + since_used = *since + } response := ResponseClientIos{ Fieldseeker: toResponseFieldseeker(csync.Fieldseeker), + Since: since_used, } if err := render.Render(w, r, response); err != nil { render.Render(w, r, errRender(err)) @@ -101,31 +121,6 @@ func handleClientIos(w http.ResponseWriter, r *http.Request, u *models.User) { } } -func apiClientIosNotePut(w http.ResponseWriter, r *http.Request, u *models.User) { - id := chi.URLParam(r, "uuid") - noteUUID, err := uuid.Parse(id) - if err != nil { - http.Error(w, "Failed to decode the uuid", http.StatusBadRequest) - return - } - var payload NidusNotePayload - body, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, "Failed to read the payload", http.StatusBadRequest) - return - } - if err := json.Unmarshal(body, &payload); err != nil { - debugSaveRequest(body, err, "Note PUT JSON decode error") - http.Error(w, "Failed to decode the payload", http.StatusBadRequest) - return - } - if err := db.NoteUpdate(context.Background(), noteUUID, db.NidusNotePayload{}); err != nil { - render.Render(w, r, errRender(err)) - return - } - w.WriteHeader(http.StatusAccepted) -} - func apiImagePost(w http.ResponseWriter, r *http.Request, u *models.User) { id := chi.URLParam(r, "uuid") noteUUID, err := uuid.Parse(id) @@ -145,7 +140,15 @@ func apiImagePost(w http.ResponseWriter, r *http.Request, u *models.User) { http.Error(w, "Failed to decode the payload", http.StatusBadRequest) return } - err = db.NoteImageCreate(context.Background(), noteUUID, db.NoteImage{}, u.ID) + setter := models.NoteImageSetter{ + Created: omit.From(payload.Created), + CreatorID: omit.From(u.ID), + Deleted: omitnull.FromPtr(payload.Deleted), + DeletorID: omitnull.FromPtr(payload.DeletorID), + Version: omit.From(payload.Version), + UUID: omit.From(noteUUID), + } + err = db.NoteImageCreate(context.Background(), u.R.Organization, u.ID, setter) if err != nil { render.Render(w, r, errRender(err)) return @@ -187,7 +190,7 @@ func apiMosquitoSource(w http.ResponseWriter, r *http.Request, u *models.User) { } data := []render.Renderer{} - for _, s := range *sources { + for _, s := range sources { data = append(data, NewResponseMosquitoSource(s)) } if err := render.RenderList(w, r, data); err != nil { @@ -212,7 +215,7 @@ func apiTrapData(w http.ResponseWriter, r *http.Request, u *models.User) { } data := []render.Renderer{} - for _, td := range *trap_data { + for _, td := range trap_data { data = append(data, NewResponseTrapDatum(td)) } if err := render.RenderList(w, r, data); err != nil { @@ -236,7 +239,7 @@ func apiServiceRequest(w http.ResponseWriter, r *http.Request, u *models.User) { } data := []render.Renderer{} - for _, sr := range *requests { + for _, sr := range requests { data = append(data, NewResponseServiceRequest(sr)) } if err := render.RenderList(w, r, data); err != nil { diff --git a/api/endpoint.go b/api/endpoint.go index adc4b10b..6a9a3bbe 100644 --- a/api/endpoint.go +++ b/api/endpoint.go @@ -14,7 +14,6 @@ func AddRoutes(r chi.Router) { r.Method("GET", "/service-request", auth.NewEnsureAuth(apiServiceRequest)) r.Method("GET", "/trap-data", auth.NewEnsureAuth(apiTrapData)) r.Method("GET", "/client/ios", auth.NewEnsureAuth(handleClientIos)) - r.Method("PUT", "/client/ios/note/{uuid}", auth.NewEnsureAuth(apiClientIosNotePut)) r.Method("POST", "/audio/{uuid}", auth.NewEnsureAuth(apiAudioPost)) r.Method("POST", "/audio/{uuid}/content", auth.NewEnsureAuth(apiAudioContentPost)) r.Method("POST", "/image/{uuid}", auth.NewEnsureAuth(apiImagePost)) diff --git a/api/types.go b/api/types.go index 56a151bc..9ce61554 100644 --- a/api/types.go +++ b/api/types.go @@ -32,44 +32,34 @@ func NewBounds() Bounds { } } -type LatLong interface { - Latitude() float64 - Longitude() float64 -} - +/* not sure if used type Location struct { Latitude float64 Longitude float64 } +*/ type NoteImagePayload struct { - UUID string `json:"uuid"` - Cell H3Cell `json:"cell"` - Created time.Time `json:"created"` -} - -type NoteAudio struct { - UUID string `db:"uuid"` - Breadcrumbs []NoteAudioBreadcrumbPayload - Created time.Time `db:"created"` - Creator int `db:"creator"` - Deleted *time.Time `db:"deleted"` - Duration int `db:"duration"` - IsAudioNormalized bool `db:"is_audio_normalized"` - IsTranscodedeToOgg bool `db:"is_transcoded_to_ogg"` - Transcription *string `db:"transcription"` - TranscriptionUserEdited bool `db:"transcription_user_edited"` - Version int `db:"version"` + UUID string `json:"uuid"` + Cell H3Cell `json:"cell"` + Created time.Time `json:"created"` + CreatorID int `db:"creator_id"` + Deleted *time.Time `json:"deleted"` + DeletorID *int32 `json:"deletor_id"` + Version int32 `json:"version"` } type NoteAudioPayload struct { UUID string `json:"uuid"` Breadcrumbs []NoteAudioBreadcrumbPayload `json:"breadcrumbs"` Created time.Time `json:"created"` - Duration int `json:"duration"` + CreatorID int `json:"creator_id"` + Deleted *time.Time `json:"deleted"` + DeletorID *int32 `json:"deletor_id"` + Duration float32 `json:"duration"` Transcription *string `json:"transcription"` TranscriptionUserEdited bool `json:"transcriptionUserEdited"` - Version int `json:"version"` + Version int32 `json:"version"` } type ResponseMosquitoSource struct { @@ -97,14 +87,6 @@ type NoteAudioBreadcrumbPayload struct { ManuallySelected bool `json:"manuallySelected"` } -type NidusNotePayload struct { - UUID string `json:"uuid"` - Timestamp time.Time `json:"timestamp"` - H3Cell int64 `json:"h3cell"` - Images []string `json:"images"` - Text string `json:"text"` -} - type ResponseFieldseeker struct { MosquitoSources []ResponseMosquitoSource `json:"sources"` ServiceRequests []ResponseServiceRequest `json:"requests"` @@ -114,6 +96,7 @@ type ResponseFieldseeker struct { // ResponseErr renderer type for handling all sorts of errors. type ResponseClientIos struct { Fieldseeker ResponseFieldseeker `json:"fieldseeker"` + Since time.Time `json:"since"` } func (i ResponseClientIos) Render(w http.ResponseWriter, r *http.Request) error { @@ -163,9 +146,9 @@ func NewResponseMosquitoInspection(i *models.FieldseekerMosquitoinspection) Resp SiteCondition: i.Sitecond.GetOr(""), } } -func NewResponseMosquitoInspections(inspections *models.FieldseekerMosquitoinspectionSlice) []ResponseMosquitoInspection { +func NewResponseMosquitoInspections(inspections models.FieldseekerMosquitoinspectionSlice) []ResponseMosquitoInspection { results := make([]ResponseMosquitoInspection, 0) - for _, i := range *inspections { + for _, i := range inspections { results = append(results, NewResponseMosquitoInspection(i)) } return results @@ -175,7 +158,7 @@ func (rtd ResponseMosquitoSource) Render(w http.ResponseWriter, r *http.Request) return nil } -func NewResponseMosquitoSource(ms *platform.MosquitoSource) ResponseMosquitoSource { +func NewResponseMosquitoSource(ms platform.MosquitoSource) ResponseMosquitoSource { pl := ms.PointLocation return ResponseMosquitoSource{ Active: toBool16(pl.Active), @@ -196,9 +179,9 @@ func NewResponseMosquitoSource(ms *platform.MosquitoSource) ResponseMosquitoSour Zone: pl.Zone.GetOr(""), } } -func NewResponseMosquitoSources(sources *[]*platform.MosquitoSource) []ResponseMosquitoSource { +func NewResponseMosquitoSources(sources []platform.MosquitoSource) []ResponseMosquitoSource { results := make([]ResponseMosquitoSource, 0) - for _, i := range *sources { + for _, i := range sources { results = append(results, NewResponseMosquitoSource(i)) } return results @@ -224,24 +207,22 @@ func (rtd ResponseMosquitoTreatment) Render(w http.ResponseWriter, r *http.Reque } func NewResponseMosquitoTreatment(i *models.FieldseekerTreatment) ResponseMosquitoTreatment { return ResponseMosquitoTreatment{ - /* - Comments: i.Comments(), - Created: i.Created().Format("2006-01-02T15:04:05.000Z"), - FieldTechnician: i.FieldTechnician(), - Habitat: i.Habitat(), - ID: i.ID(), - Product: i.Product(), - Quantity: i.Quantity(), - QuantityUnit: i.QuantityUnit(), - SiteCondition: i.SiteCondition(), - TreatAcres: i.TreatAcres(), - TreatHectares: i.TreatHectares(), - */ + Comments: i.Comments.GetOr(""), + Created: formatTime(i.Creationdate), + FieldTechnician: i.Fieldtech.GetOr(""), + Habitat: i.Habitat.GetOr(""), + ID: i.Globalid.String(), + Product: i.Product.GetOr(""), + Quantity: i.Qty.GetOr(0), + QuantityUnit: i.Qtyunit.GetOr(""), + SiteCondition: i.Sitecond.GetOr(""), + TreatAcres: i.Treatacres.GetOr(0.0), + TreatHectares: i.Treathectares.GetOr(0.0), } } -func NewResponseMosquitoTreatments(treatments *models.FieldseekerTreatmentSlice) []ResponseMosquitoTreatment { +func NewResponseMosquitoTreatments(treatments models.FieldseekerTreatmentSlice) []ResponseMosquitoTreatment { results := make([]ResponseMosquitoTreatment, 0) - for _, i := range *treatments { + for _, i := range treatments { results = append(results, NewResponseMosquitoTreatment(i)) } return results @@ -298,9 +279,9 @@ func NewResponseServiceRequest(sr *models.FieldseekerServicerequest) ResponseSer Zip: sr.Reqzip.GetOr(""), } } -func NewResponseServiceRequests(requests *models.FieldseekerServicerequestSlice) []ResponseServiceRequest { +func NewResponseServiceRequests(requests models.FieldseekerServicerequestSlice) []ResponseServiceRequest { results := make([]ResponseServiceRequest, 0) - for _, i := range *requests { + for _, i := range requests { results = append(results, NewResponseServiceRequest(i)) } return results @@ -326,9 +307,9 @@ func NewResponseTrapDatum(td *models.FieldseekerTraplocation) ResponseTrapData { Name: td.Name.GetOr(""), } } -func NewResponseTrapData(data *models.FieldseekerTraplocationSlice) []ResponseTrapData { +func NewResponseTrapData(data models.FieldseekerTraplocationSlice) []ResponseTrapData { results := make([]ResponseTrapData, 0) - for _, i := range *data { + for _, i := range data { results = append(results, NewResponseTrapDatum(i)) } return results diff --git a/auth/auth.go b/auth/auth.go index 2d6ac25e..24a372fc 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -173,6 +173,7 @@ func findUser(ctx context.Context, user_id int) (*models.User, error) { return nil, err } } + log.Info().Int32("user_id", user.ID).Int32("org_id", user.OrganizationID).Msg("Found user") return user, err } diff --git a/db/query.go b/db/query.go index 828de0de..c3f9a190 100644 --- a/db/query.go +++ b/db/query.go @@ -3,20 +3,25 @@ package db import ( "context" + "github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/google/uuid" + "github.com/rs/zerolog/log" ) -type NidusNotePayload struct {} -type NoteAudio struct { - Transcription string - Version int - UUID uuid.UUID -} -type NoteImage struct {} -func NoteAudioCreate(ctx context.Context, noteUUID uuid.UUID, payload NoteAudio, userID int32) error { - return nil +func NoteAudioCreate(ctx context.Context, org *models.Organization, userID int32, setter models.NoteAudioSetter) error { + err := org.InsertNoteAudios(ctx, PGInstance.BobDB, &setter) + if err == nil { + return nil + } + // Just ignore this failure, it means we already have this content + if err.Error() == "insertOrganizationNoteAudios0: ERROR: duplicate key value violates unique constraint \"note_audio_pkey\" (SQLSTATE 23505)" { + return nil + } + log.Warn().Err(err).Msg("Unrecognized error creating note audio") + return err } -func NoteAudioGetLatest(ctx context.Context, uuid string) (*NoteAudio, error) { + +func NoteAudioGetLatest(ctx context.Context, uuid string) (*models.NoteAudio, error) { return nil, nil } func NoteAudioNormalized(uuid string) error { @@ -25,9 +30,19 @@ func NoteAudioNormalized(uuid string) error { func NoteAudioTranscodedToOgg(uuid string) error { return nil } -func NoteImageCreate(ctx context.Context, noteUUID uuid.UUID, payload NoteImage, userID int32) error { - return nil -} -func NoteUpdate(ctx context.Context, noteUUID uuid.UUID, payload NidusNotePayload) error { +func NoteImageCreate(ctx context.Context, org *models.Organization, userID int32, setter models.NoteImageSetter) error { + err := org.InsertNoteImages(ctx, PGInstance.BobDB, &setter) + if err == nil { + return nil + } + // Just ignore this failure, it means we already have this content + if err.Error() == "insertOrganizationNoteImages0: ERROR: duplicate key value violates unique constraint \"note_image_pkey\" (SQLSTATE 23505)" { + return nil + } + log.Warn().Err(err).Msg("Unrecognized error creating note audio") + return err +} + +func NoteUpdate(ctx context.Context, noteUUID uuid.UUID, setter models.NoteAudioSetter) error { return nil } diff --git a/main.go b/main.go index 52a8c4bd..ca40bf26 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/api" "github.com/Gleipnir-Technology/nidus-sync/auth" "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/queue" "github.com/Gleipnir-Technology/nidus-sync/userfile" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" @@ -162,6 +163,12 @@ func main() { refreshFieldseekerData(ctx, NewOAuthTokenChannel) }() + waitGroup.Add(1) + go func() { + defer waitGroup.Done() + queue.StartAudioWorker(ctx) + }() + server := &http.Server{ Addr: bind, Handler: r, diff --git a/platform/general.go b/platform/general.go index f99c3a38..f89f997a 100644 --- a/platform/general.go +++ b/platform/general.go @@ -4,17 +4,17 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/db/models" ) -func MosquitoSourceQuery() (*[]*MosquitoSource, error) { - results := make([]*MosquitoSource, 0) - return &results, nil +func MosquitoSourceQuery() ([]MosquitoSource, error) { + results := make([]MosquitoSource, 0) + return results, nil } -func ServiceRequestQuery() (*models.FieldseekerServicerequestSlice, error) { +func ServiceRequestQuery() (models.FieldseekerServicerequestSlice, error) { results := make(models.FieldseekerServicerequestSlice, 0) - return &results, nil + return results, nil } -func TrapDataQuery() (*models.FieldseekerTraplocationSlice, error) { +func TrapDataQuery() (models.FieldseekerTraplocationSlice, error) { results := make(models.FieldseekerTraplocationSlice, 0) - return &results, nil + return results, nil } diff --git a/platform/ios.go b/platform/ios.go index 9d787c87..f04974e1 100644 --- a/platform/ios.go +++ b/platform/ios.go @@ -57,7 +57,7 @@ func fieldseeker(ctx context.Context, u *models.User, since *time.Time) (fsync F ts = append(ts, t) treatments_by_location[locid] = ts } - sources := make([]*MosquitoSource, 0) + sources := make([]MosquitoSource, 0) for _, p := range pl { inspections, ok := inspections_by_location[p.Globalid] if !ok { @@ -68,13 +68,13 @@ func fieldseeker(ctx context.Context, u *models.User, since *time.Time) (fsync F treatments = make(models.FieldseekerTreatmentSlice, 0) } ms := MosquitoSource{ - PointLocation: p, - Inspections: &inspections, - Treatments: &treatments, + PointLocation: *p, + Inspections: inspections, + Treatments: treatments, } - sources = append(sources, &ms) + sources = append(sources, ms) } - fsync.MosquitoSources = &sources + fsync.MosquitoSources = sources return fsync, err } diff --git a/platform/type.go b/platform/type.go index 8d0825f9..e7161a88 100644 --- a/platform/type.go +++ b/platform/type.go @@ -12,13 +12,13 @@ type ClientSync struct { } type FieldseekerRecordsSync struct { - MosquitoSources *[]*MosquitoSource - ServiceRequests *models.FieldseekerServicerequestSlice - TrapData *models.FieldseekerTraplocationSlice + MosquitoSources []MosquitoSource + ServiceRequests models.FieldseekerServicerequestSlice + TrapData models.FieldseekerTraplocationSlice } type MosquitoSource struct { - PointLocation *models.FieldseekerPointlocation - Inspections *models.FieldseekerMosquitoinspectionSlice - Treatments *models.FieldseekerTreatmentSlice + PointLocation models.FieldseekerPointlocation + Inspections models.FieldseekerMosquitoinspectionSlice + Treatments models.FieldseekerTreatmentSlice } diff --git a/queue/audio_processing.go b/queue/audio_processing.go index 426441c4..d03ceb6e 100644 --- a/queue/audio_processing.go +++ b/queue/audio_processing.go @@ -4,13 +4,13 @@ import ( "context" "errors" "fmt" - "log" "os" "os/exec" "github.com/Gleipnir-Technology/nidus-sync/db" "github.com/Gleipnir-Technology/nidus-sync/userfile" "github.com/google/uuid" + "github.com/rs/zerolog/log" ) // AudioJob represents a job to process an audio file. @@ -25,18 +25,18 @@ var audioJobChannel chan AudioJob func StartAudioWorker(ctx context.Context) { buffer := 100 audioJobChannel = make(chan AudioJob, buffer) // Buffered channel to prevent blocking - log.Printf("Started audio worker with buffer depth %d", buffer) + log.Info().Int("buffer depth", buffer).Msg("Started audio worker") go func() { for { select { case <-ctx.Done(): - log.Println("Audio worker shutting down.") + log.Info().Msg("Audio worker shutting down.") return case job := <-audioJobChannel: - log.Printf("Processing audio job for UUID: %s", job.AudioUUID) + log.Info().Str("uuid", job.AudioUUID.String()).Msg("Processing audio job") err := processAudioFile(job.AudioUUID) if err != nil { - log.Printf("Error processing audio file %s: %v", job.AudioUUID, err) + log.Error().Err(err).Str("uuid", job.AudioUUID.String()).Msg("Error processing audio file") } } } @@ -47,9 +47,9 @@ func StartAudioWorker(ctx context.Context) { func EnqueueAudioJob(job AudioJob) { select { case audioJobChannel <- job: - log.Printf("Enqueued audio job for UUID: %s", job.AudioUUID) + log.Info().Str("uuid", job.AudioUUID.String()).Msg("Enqueued audio job") default: - log.Printf("Audio job channel is full, dropping job for UUID: %s", job.AudioUUID) + log.Warn().Str("uuid", job.AudioUUID.String()).Msg("Audio job channel is full, dropping job") } } @@ -76,10 +76,10 @@ func normalizeAudio(audioUUID uuid.UUID) error { source := userfile.AudioFileContentPathRaw(audioUUID.String()) _, err := os.Stat(source) if errors.Is(err, os.ErrNotExist) { - log.Printf("%s doesn't exist, skipping normalization", source) + log.Warn().Str("source", source).Msg("file doesn't exist, skipping normalization") return nil } - log.Printf("Normalizing %s", source) + log.Info().Str("sourcce", source).Msg("Normalizing") destination := userfile.AudioFileContentPathNormalized(audioUUID.String()) // Use "ffmpeg" directly, assuming it's in the system PATH cmd := exec.Command("ffmpeg", "-i", source, "-filter:a", "loudnorm", destination) @@ -92,7 +92,7 @@ func normalizeAudio(audioUUID uuid.UUID) error { if err != nil { return fmt.Errorf("failed to update database for normalized audio %s: %v", audioUUID, err) } - log.Printf("Normalized audio to %s", destination) + log.Info().Str("destination", destination).Msg("Normalized audio") return nil } @@ -100,22 +100,22 @@ func transcodeToOgg(audioUUID uuid.UUID) error { source := userfile.AudioFileContentPathNormalized(audioUUID.String()) _, err := os.Stat(source) if errors.Is(err, os.ErrNotExist) { - log.Printf("%s doesn't exist, skipping OGG transcoding", source) + log.Warn().Str("source", source).Msg("file doesn't exist, skipping OGG transcoding") return nil } - log.Printf("Transcoding %s to ogg", source) + log.Info().Str("source", source).Msg("Transcoding to ogg") destination := userfile.AudioFileContentPathOgg(audioUUID.String()) // Use "ffmpeg" directly, assuming it's in the system PATH cmd := exec.Command("ffmpeg", "-i", source, "-vn", "-acodec", "libvorbis", destination) out, err := cmd.CombinedOutput() if err != nil { - log.Printf("FFmpeg output for OGG transcoding: %s", out) + log.Error().Err(err).Bytes("out", out).Msg("FFmpeg output for OGG transcoding") return fmt.Errorf("ffmpeg OGG transcoding failed: %v", err) } err = db.NoteAudioTranscodedToOgg(audioUUID.String()) if err != nil { return fmt.Errorf("failed to update database for OGG transcoded audio %s: %v", audioUUID, err) } - log.Printf("Transcoded audio to %s", destination) + log.Info().Str("destination", destination).Msg("Transcoded audio") return nil } diff --git a/queue/label_studio.go b/queue/label_studio.go index 2a6c90dc..35321de6 100644 --- a/queue/label_studio.go +++ b/queue/label_studio.go @@ -9,6 +9,7 @@ import ( "os" "github.com/Gleipnir-Technology/nidus-sync/db" + "github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/label-studio" "github.com/Gleipnir-Technology/nidus-sync/minio" "github.com/Gleipnir-Technology/nidus-sync/userfile" @@ -127,7 +128,7 @@ func processLabelTask(ctx context.Context, minioClient *minio.Client, minioBucke return nil } -func createTask(client *labelstudio.Client, project *labelstudio.Project, minioClient *minio.Client, bucket string, customer string, note *db.NoteAudio) error { +func createTask(client *labelstudio.Client, project *labelstudio.Project, minioClient *minio.Client, bucket string, customer string, note *models.NoteAudio) error { audioRef := fmt.Sprintf("s3://%s/%s-normalized.m4a", bucket, note.UUID) audioFile := fmt.Sprintf("%s/%s-normalized.m4a", userfile.UserFilesDirectory, note.UUID) uploadPath := fmt.Sprintf("%s-normalized.m4a", note.UUID) @@ -140,9 +141,9 @@ func createTask(client *labelstudio.Client, project *labelstudio.Project, minioC } var transcription string = "" //if note.Transcription.IsValue() { - //transcription = note.Transcription.MustGet() + //transcription = note.Transcription.MustGet() //} - transcription = note.Transcription + transcription = note.Transcription.GetOr("") simpleTasks := []map[string]interface{}{ { "data": map[string]string{ @@ -184,7 +185,7 @@ func findLabelStudioProject(client *labelstudio.Client, title string) (*labelstu return nil, fmt.Errorf("No such project '%s'", title) } -func findMatchingTask(client *labelstudio.Client, project *labelstudio.Project, customer string, note *db.NoteAudio) (*labelstudio.Task, error) { +func findMatchingTask(client *labelstudio.Client, project *labelstudio.Project, customer string, note *models.NoteAudio) (*labelstudio.Task, error) { /*meta := map[string]string{ "customer": customer, "note_uuid": note.UUID,