Skip to content

Commit

Permalink
feat: finished project
Browse files Browse the repository at this point in the history
  • Loading branch information
Wittano committed Jul 29, 2024
1 parent 9191677 commit 12d54e4
Show file tree
Hide file tree
Showing 34 changed files with 301 additions and 1,330 deletions.
43 changes: 6 additions & 37 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
DEST_DIR = /opt/komputer
ARCH = $(shell uname -m)
OUTPUT_DIR=./build
PROTOBUF_API_DEST=./api
Expand All @@ -11,50 +10,20 @@ endif

.PHONY: test clean

bot-dev: proto gen-sql
bot-dev:
CGO_ENABLED=1 GOOS=linux GOARCH=$(GOARCH) go build -tags dev -o $(OUTPUT_DIR)/komputer ./cmd/komputer/main.go


bot-prod: protobuf gen-sql
bot-prod:
CGO_ENABLED=1 GOOS=linux GOARCH=$(GOARCH) go build -o $(OUTPUT_DIR)/komputer ./cmd/komputer/main.go

sever: protobuf gen-sql
go build -o $(OUTPUT_DIR)/server ./cmd/server/main.go
test: test-bot

tui: protobuf
go build -o $(OUTPUT_DIR)/tui ./cmd/tui/main.go

protobuf:
mkdir -p $(PROTOBUF_API_DEST)
protoc --go_out=./api --go_opt=paths=source_relative --go-grpc_out=./api --go-grpc_opt=paths=source_relative proto/*

test: test-bot test-server

test-bot: protobuf gen-sql
test-bot:
CGO_CFLAGS="-w" go test ./bot/...;

test-server: protobuf
CGO_CFLAGS="-w" go test ./server/...;

all: bot-prod sever tui test

DB_PATH=db.sqlite

update-database:
ifeq (,$(wildcard $(DB_PATH)))
touch $(DB_PATH)
endif
migrate -database sqlite3://$(DB_PATH) -path db/migrations up

gen-sql:
sqlc -f sqlc.yaml generate

clean: cleanProto
all: bot-prod test
clean:
ifneq ("$(wildcard $(OUTPUT_DIR))", "")
rm -r $(OUTPUT_DIR)
endif

cleanProto:
ifneq ("$(wildcard $(PROTOBUF_API_DEST))", "")
rm -r $(PROTOBUF_API_DEST)
endif
17 changes: 17 additions & 0 deletions audio/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package audio

import (
"context"
"io"
)

func Upload(ctx context.Context, r io.ReadCloser) (int, error) {
defer r.Close()
select {
case <-ctx.Done():
return 0, context.Canceled
default:
}

return 0, nil
}
147 changes: 147 additions & 0 deletions audio/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package audio

import (
"errors"
"fmt"
"io"
"math/rand"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"time"
)

const (
defaultCacheDirAudio = "assets"
assetsDirKey = "ASSETS_DIR"
)

func Path(name string) (path string, err error) {
assertDir := AssertDir()
path = filepath.Join(assertDir, name)
_, err = os.Stat(path)
if err != nil {
path, err = searchPathByNameOrUUID(name)
}

return
}

func searchPathByNameOrUUID(prefix string) (p string, err error) {
var paths []string
paths, err = Paths()
if err != nil {
return
}

for _, p = range paths {
base := filepath.Base(p)
if strings.HasPrefix(base, prefix) {
return
} else {
split := strings.Split(base, "-")
if len(split) < 2 {
continue
}

if strings.HasPrefix(strings.Join(split[1:], "-"), prefix) {
return
}
}
}

return "", fmt.Errorf("path with prefix %s wasn't found", prefix)
}

func AssertDir() (path string) {
path = defaultCacheDirAudio
if cacheDir, ok := os.LookupEnv(assetsDirKey); ok && cacheDir != "" {
path = cacheDir
}

return
}

func Paths() (paths []string, err error) {
assertDir := AssertDir()
dirs, err := os.ReadDir(assertDir)
if err != nil {
return nil, err
}

if len(dirs) <= 0 {
return nil, errors.New("assert directory is empty")
}

paths = make([]string, 0, len(dirs))
for _, dir := range dirs {
if dir.Type() != os.ModeDir {
paths = append(paths, filepath.Join(assertDir, dir.Name()))
}
}

return
}

// PathsWithPagination get fixed-sized list of audio paths from assert dictionary
func PathsWithPagination(page uint32, size uint32) (paths []string, err error) {
dirs, err := os.ReadDir(AssertDir())
if err != nil {
return nil, err
}

skipFiles := int(page * size)
if len(dirs) < skipFiles {
return []string{}, nil
} else if len(dirs) <= 0 {
return nil, errors.New("assert directory is empty")
}

paths = make([]string, 0, size)
for _, dir := range dirs[skipFiles:] {
if dir.Type() != os.ModeDir {
paths = append(paths, dir.Name())
}

if len(paths) >= int(size) {
break
}
}

return
}

func RandomAudioName() (string, error) {
paths, err := Paths()
if err != nil {
return "", err
}

return paths[rand.Int()%len(paths)], nil
}

func Duration(path string) (duration time.Duration, err error) {
cmd := exec.Command("ffprobe", "-i", path, "-show_entries", "format=duration", "-v", "quiet", "-of", "csv='p=0'")
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}

if err = cmd.Start(); err != nil {
return
}

out, err := cmd.StdoutPipe()
if err != nil {
return
}
defer out.Close()

rawTime, err := io.ReadAll(out)
if err != nil {
return
}

return time.ParseDuration(string(rawTime) + "s")
}
117 changes: 117 additions & 0 deletions audio/path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package audio

import (
"errors"
"github.com/wittano/komputer/internal/test"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
)

func TestAudioIDs_AssetDirHasEmptyDirs(t *testing.T) {
dir := t.TempDir()

for i := 0; i < 5; i++ {
os.Mkdir(filepath.Join(dir, strconv.Itoa(i)), 0700)
}

if err := os.Setenv(assetsDirKey, dir); err != nil {
t.Fatal(err)
}

paths, err := Paths()
if err != nil {
t.Fatal(err)
}

if len(paths) != 0 {
t.Fatal("something was found in empty directory")
}
}

func TestAudioIDs(t *testing.T) {
const expectedFilesNumber = 5
if err := test.CreateAssertDir(t, expectedFilesNumber); err != nil {
t.Fatal(err)
}

paths, err := Paths()
if err != nil {
t.Fatal(err)
}

if len(paths) != expectedFilesNumber {
t.Fatalf("missing audios IDs. Expected '%d', Result: '%d'", expectedFilesNumber, len(paths))
}

for i, id := range paths {
fileID := filepath.Base(strings.Split(id, ".")[0])

if fileID != "test-"+strconv.Itoa(i) {
t.Fatalf("invalid ID. Expected: '%d', Result: '%s'", i, fileID)
}
}
}

func TestPathsWithPagination_ButEmptyDictionary(t *testing.T) {
if err := os.Setenv(assetsDirKey, t.TempDir()); err != nil {
t.Fatal(err)
}

res, err := PathsWithPagination(0, 10)
if err == nil {
t.Fatalf("Assert dictionary was found: %s", os.Getenv(assetsDirKey))
}

if len(res) != 0 {
t.Fatalf("Something was found in assert dictionary, but it doesn't expect. %v", res)
}
}

func TestPathsWithPagination_PageIsOverANumberOfFiles(t *testing.T) {
const expectedFilesNumber = 5
if err := test.CreateAssertDir(t, expectedFilesNumber); err != nil {
t.Fatal(err)
}

res, err := PathsWithPagination(10, 10)
if err != nil {
t.Fatal(err)
}

if len(res) != 0 {
t.Fatalf("Something was added to list, but page and size are over number of files. %v", res)
}
}

func TestPathsWithPagination(t *testing.T) {
const expectedFilesNumber = 50
if err := test.CreateAssertDir(t, expectedFilesNumber); err != nil {
t.Fatal(err)
}

res, err := PathsWithPagination(2, 10)
if err != nil {
t.Fatal(err)
}

if len(res) != 10 {
t.Fatalf("Files wasn't found but shoule be")
}

const startFileSuffix = 20
for i := startFileSuffix; i < 30; i++ {
f := res[i-startFileSuffix]
if _, err = os.Stat(f); !errors.Is(err, os.ErrNotExist) {
t.Fatal(err)
}
}
}

func TestPathsWithPagination_AssertDirNotFound(t *testing.T) {
if _, err := PathsWithPagination(0, 10); err == nil {
t.Fatalf("Assert dictionary was found")
}
}
21 changes: 0 additions & 21 deletions cmd/server/main.go

This file was deleted.

9 changes: 0 additions & 9 deletions cmd/tui/main.go

This file was deleted.

8 changes: 0 additions & 8 deletions db/migrations/000001_init.down.sql

This file was deleted.

Loading

0 comments on commit 12d54e4

Please sign in to comment.