diff --git a/.goreleaser.yaml b/.goreleaser.yaml index a6211959..3998ba64 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -17,6 +17,14 @@ builds: goarch: 386 - goos: windows goarch: arm64 + ldflags: + - -s -w -X cmd.version={{.Version}} -X cmd.commit={{.Commit}} -X cmd.date={{.Date}} -X cmd.builtBy=goreleaser + +# binary_signs: +# - {} + +# signs: +# - artifacts: checksum universal_binaries: - replace: true @@ -66,7 +74,7 @@ brews: chocolateys: - title: prattl authors: Ben Marshall, Ezra Klitsie - project_url: https://github.com/prattlOrg/prattl + project_url: https://prattl.co/ url_template: "https://github.com/prattlOrg/prattl/releases/download/{{ .Tag }}/{{ .ArtifactName }}" copyright: 2024 Prattl Org package_source_url: https://github.com/prattlOrg/prattl @@ -88,8 +96,42 @@ chocolateys: source_repo: "https://push.chocolatey.org/" skip_publish: false +nfpms: + - package_name: prattl + file_name_template: >- + {{ .ProjectName }}_{{ .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}{{ .Arm }}{{ end }} + vendor: Prattl Org. + homepage: https://prattl.co/ + maintainer: Benjamin Marshall + description: |- + Prattl installer package. + CLI tool for transcribing audio to text. + license: MIT + formats: + - apk + - deb + - rpm + - termux.deb + - archlinux + dependencies: + - ffmpeg + # Changelog YAML file, see: https://github.com/goreleaser/chglog + # + # You can use goreleaser/chglog to create the changelog for your project, + # pass that changelog yaml file to GoReleaser, + # and it should in turn setup it accordingly for the given available + # formats (deb and rpm at the moment). + # + # Experimental. + # changelog: changelog.yaml + changelog: sort: asc + use: github filters: exclude: - "^docs:" diff --git a/Makefile b/Makefile index 8610b957..853e4aed 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,6 @@ local: - goreleaser release --snapshot --clean \ No newline at end of file + goreleaser release --snapshot --clean +test-stdin: + go test ./cmd -run TestStdin -count=1 -v +test-fp: + go test ./cmd -run TestFp -count=1 -v \ No newline at end of file diff --git a/cmd/clean.go b/cmd/clean.go index cb4e1aa0..42a4f98c 100644 --- a/cmd/clean.go +++ b/cmd/clean.go @@ -14,7 +14,7 @@ var Confirm bool func init() { cleanCmd.Flags().BoolVarP(&Confirm, "confirm", "y", false, "skips confirmation prompt") - rootCmd.AddCommand(cleanCmd) + RootCmd.AddCommand(cleanCmd) } var cleanCmd = &cobra.Command{ diff --git a/cmd/compress.go b/cmd/compress.go index bc233d86..4a7e196c 100644 --- a/cmd/compress.go +++ b/cmd/compress.go @@ -8,8 +8,8 @@ import ( ) func init() { - rootCmd.AddCommand(compressCommand) - rootCmd.AddCommand(decompressCommand) + RootCmd.AddCommand(compressCommand) + RootCmd.AddCommand(decompressCommand) } var compressCommand = &cobra.Command{ diff --git a/cmd/prepare.go b/cmd/prepare.go index 4b820086..47fe62c3 100644 --- a/cmd/prepare.go +++ b/cmd/prepare.go @@ -8,7 +8,7 @@ import ( ) func init() { - rootCmd.AddCommand(prepareCmd) + RootCmd.AddCommand(prepareCmd) } var prepareCmd = &cobra.Command{ diff --git a/cmd/report.go b/cmd/report.go index f930cccd..2df542b5 100644 --- a/cmd/report.go +++ b/cmd/report.go @@ -12,7 +12,7 @@ import ( ) func init() { - rootCmd.AddCommand(reportCommand) + RootCmd.AddCommand(reportCommand) } // ripped straight from stack overflow: https://stackoverflow.com/questions/32482673/how-to-get-directory-total-size diff --git a/cmd/root.go b/cmd/root.go index 4a2ed179..3753926f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,15 +6,21 @@ import ( "github.com/spf13/cobra" ) -var rootCmd = &cobra.Command{ +var ( + version = "dev" + // commit = "none" + // date = "unknown" +) + +var RootCmd = &cobra.Command{ Use: "prattl", Short: "Prattl is a transcription tool", Long: "A transcription tool built with Go and Python.\nComplete documentation is available at https://github.com/prattlOrg/prattl", - Version: "v0.2.2", + Version: version, } func Execute() { - if err := rootCmd.Execute(); err != nil { + if err := RootCmd.Execute(); err != nil { os.Exit(1) } } diff --git a/cmd/transcribe.go b/cmd/transcribe.go index 9f36524f..510ec0ac 100644 --- a/cmd/transcribe.go +++ b/cmd/transcribe.go @@ -1,8 +1,10 @@ package cmd import ( + "bufio" "bytes" "encoding/json" + "errors" "fmt" "io" "os" @@ -15,61 +17,88 @@ import ( ) func init() { - rootCmd.AddCommand(transcribeCmd) + RootCmd.AddCommand(transcribeCmd) } var transcribeCmd = &cobra.Command{ Use: "transcribe ", Short: "Transcribe the provided audio file (file path)", Long: "This command transcribes the provided audiofile and prints the resulting string", - Args: cobra.MinimumNArgs(1), + // Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - - if len(args) == 0 { - return fmt.Errorf("%s", "no file path provided\n") - } - fmt.Fprintln(os.Stderr, "Transcribing..") - - - transcriptionMap := make(map[string]string) - transcriptions, err := transcribe(args) + isStdin, err := checkStdin() if err != nil { return err } + if isStdin { + fileBytes, err := readStdin() + if err != nil { + return err + } + err = transcribeStdin(fileBytes) + if err != nil { + return err + } + } else { + if len(args) == 0 { + return fmt.Errorf("requires at least 1 arg(s), only received 0") + } + err = transcribeFp(args...) + if err != nil { + return err + } + } + return nil + }, +} - for i, trans := range transcriptions { - transcriptionMap[args[i]] = trans +func checkStdin() (bool, error) { + fileStat, err := os.Stdin.Stat() + if err != nil { + return false, fmt.Errorf("getting stdin stat failed: %v", err) + } + if fileStat.Size() == 0 { + return false, nil + } + return true, nil - } + // // check if stdin is pipe + // return fileStat.Mode()&os.ModeNamedPipe != 0, nil +} - jsonOutput, err := json.Marshal(transcriptionMap) - if err != nil { - return fmt.Errorf("error marshaling to JSON: %v", err) +func readStdin() ([]byte, error) { + reader := bufio.NewReader(os.Stdin) + var fileBytes []byte + for { + b, err := reader.ReadByte() + if err != nil && !errors.Is(err, io.EOF) { + return nil, fmt.Errorf("failed to read file byte: %v", err) } - - clearLine() - _, err = io.WriteString(os.Stdout, string(jsonOutput)+"\n") + // process the one byte b if err != nil { - return fmt.Errorf("error writing to stdout: %v", err) + // end of file + break } - - return nil - }, + fileBytes = append(fileBytes, b) + } + return fileBytes, nil } -func isPipeInput() bool { - fileInfo, _ := os.Stdin.Stat() - return fileInfo.Mode()&os.ModeCharDevice == 0 +func transcribeStdin(fileBytes []byte) error { + transcription, err := transcribe(fileBytes) + if err != nil { + return err + } + fmt.Println(transcription[0]) + return nil } -func transcribe(fps []string) ([]string, error) { - returnStrings := []string{} - +func transcribeFp(fps ...string) error { var allBytes []byte for i, fp := range fps { fileBytes, err := os.ReadFile(fp) if err != nil { - return returnStrings, fmt.Errorf("error reading file: %v", err) + return fmt.Errorf("error reading file: %v", err) } allBytes = append(allBytes, fileBytes...) @@ -78,49 +107,72 @@ func transcribe(fps []string) ([]string, error) { } } + transcriptionMap := make(map[string]string) + transcriptions, err := transcribe(allBytes) + if err != nil { + return err + } + for i, trans := range transcriptions { + transcriptionMap[fps[i]] = trans + } + jsonOutput, err := json.Marshal(transcriptionMap) + if err != nil { + return fmt.Errorf("marshaling to JSON failed: %v", err) + } + _, err = io.WriteString(os.Stdout, string(jsonOutput)+"\n") + if err != nil { + return fmt.Errorf("writing to stdout failed: %v", err) + } + return nil +} +func transcribe(file []byte) ([]string, error) { + fmt.Fprintln(os.Stderr, "Transcribing..") program, err := pysrc.ReturnFile("transcribe.py") if err != nil { - return returnStrings, err + return nil, err } env, err := pysrc.GetPrattlEnv() if err != nil { - return returnStrings, err + return nil, err } + cmd, err := env.ExecutePython("-c", program) if err != nil { - return returnStrings, err + return nil, err } + var out bytes.Buffer var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr stdin, err := cmd.StdinPipe() if err != nil { - return returnStrings, fmt.Errorf("error instantiating pipe: %v", err) + return nil, fmt.Errorf("error instantiating pipe: %v", stderr.String()) } - cmd.Stdout = &out - cmd.Stderr = &stderr if err = cmd.Start(); err != nil { - return returnStrings, fmt.Errorf("error starting command: %v", err) + return nil, fmt.Errorf("error starting command: %v", stderr.String()) } - _, err = stdin.Write(allBytes) + _, err = stdin.Write(file) if err != nil { - return returnStrings, fmt.Errorf("error writing to stdin: %v", err) + return nil, fmt.Errorf("error writing to stdin: %v", stderr.String()) } stdin.Close() if err = cmd.Wait(); err != nil { - return returnStrings, fmt.Errorf("error waiting for command: %v", err) + return nil, fmt.Errorf("error waiting for command: %v", stderr.String()) } output := out.String() - // fmt.Println(output) - - returnStrings = strings.Split(strings.ToLower(output), embed.SeparatorExpectedString) + returnStrings := strings.Split(strings.ToLower(output), embed.SeparatorExpectedString) for _, str := range returnStrings { str = fmt.Sprintf("---%s---\n", str) } + // not working frfr + clearLine() + return returnStrings, nil } diff --git a/cmd/transcribe_test.go b/cmd/transcribe_test.go new file mode 100644 index 00000000..c2cb8f37 --- /dev/null +++ b/cmd/transcribe_test.go @@ -0,0 +1,55 @@ +package cmd_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/prattlOrg/prattl/cmd" +) + +var audio00 = filepath.Clean("../test_audio/test.mp3") +var audio01 = filepath.Clean("../test_audio/transcribing_1.mp3") + +func TestStdin(t *testing.T) { + dat, err := os.ReadFile(audio00) + if err != nil { + t.Fatal(err) + } + + tmpfile, err := os.CreateTemp("../test_audio", "*.mp3") + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpfile.Name()) // clean up + if _, err := tmpfile.Write(dat); err != nil { + t.Fatal(err) + } + if _, err := tmpfile.Seek(0, 0); err != nil { + t.Fatal(err) + } + oldStdin := os.Stdin + defer func() { os.Stdin = oldStdin }() // Restore original Stdin + os.Stdin = tmpfile + + root := cmd.RootCmd + root.SetIn(nil) + root.SetArgs([]string{"transcribe"}) + err = root.Execute() + if err != nil { + t.FailNow() + } + + if err := tmpfile.Close(); err != nil { + t.Fatal(err) + } +} + +func TestFp(t *testing.T) { + root := cmd.RootCmd + root.SetArgs([]string{"transcribe", audio00, audio01}) + err := root.Execute() + if err != nil { + t.FailNow() + } +}