Skip to content
This repository has been archived by the owner on Dec 25, 2024. It is now read-only.

Commit

Permalink
feat(server): added audio services (getting info, upload and download…
Browse files Browse the repository at this point in the history
… audio)
  • Loading branch information
Wittano committed Jun 24, 2024
1 parent c76ee77 commit 6557e7b
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 20 deletions.
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
}
28 changes: 28 additions & 0 deletions bot/audio/file.go → audio/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,34 @@ func Paths() (paths []string, err error) {
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 RandomPath() (string, error) {
paths, err := Paths()
if err != nil {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func createJokeGetServices(globalCtx context.Context, database *db.MongodbDataba
return []dbJoke.SearchService{
jokeDevServiceID: joke.NewJokeDevService(globalCtx),
humorAPIServiceID: joke.NewHumorAPIService(globalCtx),
databaseServiceID: joke.NewDatabaseJokeService(database),
databaseServiceID: joke.NewJokeDatabase(database),
}
}

Expand Down
6 changes: 3 additions & 3 deletions bot/command/joke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestSelectGetService(t *testing.T) {
testServices := []dbJoke.SearchService{
joke.NewJokeDevService(ctx),
joke.NewHumorAPIService(ctx),
joke.NewDatabaseJokeService(dumpMongoService{}),
joke.NewJokeDatabase(dumpMongoService{}),
}

service, err := findService(ctx, testServices)
Expand All @@ -47,7 +47,7 @@ func TestFindJokeService_ContextCancelled(t *testing.T) {
testServices := []dbJoke.SearchService{
joke.NewJokeDevService(ctx),
joke.NewHumorAPIService(ctx),
joke.NewDatabaseJokeService(dumpMongoService{}),
joke.NewJokeDatabase(dumpMongoService{}),
}

if _, err := findService(ctx, testServices); err == nil {
Expand All @@ -58,7 +58,7 @@ func TestFindJokeService_ContextCancelled(t *testing.T) {
func TestFindJokeService_ServicesIsDeactivated(t *testing.T) {
ctx := context.Background()
services := []dbJoke.SearchService{
joke.NewDatabaseJokeService(dumpMongoService{}),
joke.NewJokeDatabase(dumpMongoService{}),
}

if _, err := findService(ctx, services); err == nil {
Expand Down
2 changes: 1 addition & 1 deletion bot/command/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"errors"
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/wittano/komputer/bot/audio"
"github.com/wittano/komputer/audio"
"os"
"regexp"
"strings"
Expand Down
4 changes: 2 additions & 2 deletions bot/command/spock.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"github.com/bwmarrin/dgvoice"
"github.com/bwmarrin/discordgo"
"github.com/wittano/komputer/bot/audio"
"github.com/wittano/komputer/audio"
"github.com/wittano/komputer/bot/log"
"github.com/wittano/komputer/bot/voice"
"log/slog"
Expand Down Expand Up @@ -133,7 +133,7 @@ func audioPath(data discordgo.ApplicationCommandInteractionData) (path string, e
}
}

if name == "" && err == nil {
if name == "" {
path, err = audio.RandomPath()
} else {
path = audio.Path(path)
Expand Down
13 changes: 9 additions & 4 deletions proto/audio.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ message AudioInfo {

message Audio {
AudioInfo info = 1;
bytes file = 2;
bytes chunk = 2;
}

message File {
message FileBuffer {
bytes content = 1;
uint64 size = 2;
}
Expand All @@ -30,12 +30,17 @@ message UploadAudioResponse {
uint32 size = 2;
}

message DownloadRequest {
optional UUID uuid = 1;
optional string name = 2;
}

service AudioService {
rpc List(komputer.Pagination) returns (stream AudioInfo);
rpc Add(stream Audio) returns (UploadAudioResponse);
rpc Remove(NameOrIdRequest) returns (google.protobuf.Empty);
rpc Remove(NameOrIdAudioRequest) returns (google.protobuf.Empty);
}

service AudioFileService {
rpc Download(FindById) returns (stream File);
rpc Download(DownloadRequest) returns (stream FileBuffer);
}
9 changes: 6 additions & 3 deletions proto/request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ message ObjectID {
string object_id = 1;
}

message NameOrIdRequest {
message FileQuery {
oneof query {
uint64 id = 1;
bytes uuid = 2;
UUID uuid = 2;
string name = 3;
}
optional Pagination page = 4;
}

message NameOrIdAudioRequest {
repeated FileQuery query = 1;
}
102 changes: 102 additions & 0 deletions server/audio.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package server

import (
"context"
"errors"
"fmt"
"github.com/google/uuid"
komputer "github.com/wittano/komputer/api/proto"
"github.com/wittano/komputer/audio"
"google.golang.org/protobuf/types/known/emptypb"
"os"
"sync"
)

type audioServer struct {
komputer.UnimplementedAudioServiceServer
}

func (a audioServer) List(pagination *komputer.Pagination, server komputer.AudioService_ListServer) (err error) {
page := paginationOrDefault(pagination)

paths, err := audio.PathsWithPagination(page.Page, page.Size)
if err != nil {
return
}

for _, path := range paths {
err = errors.Join(err, server.Send(&komputer.AudioInfo{Name: path, Type: komputer.FileFormat_MP3}))
}

return
}

func (a audioServer) Add(server komputer.AudioService_AddServer) error {
for {
au, err := server.Recv()
if err != nil {
return err
}

path := audio.Path(fmt.Sprintf("%s-%s.%s", au.Info.Name, uuid.NewString(), au.Info.Type.String()))

f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
f.Close()

m := sync.Mutex{}

m.Lock()
if _, err := f.Write(au.Chunk); err != nil {
m.Unlock()
return err
}
m.Unlock()
}
}

func (a audioServer) Remove(ctx context.Context, request *komputer.NameOrIdAudioRequest) (e *emptypb.Empty, err error) {
e = &emptypb.Empty{}
if request == nil || len(request.Query) == 0 {
return e, nil
}

var wg sync.WaitGroup
for _, query := range request.Query {
if query == nil {
continue
}

wg.Add(1)
go func(q *komputer.FileQuery) {
err = remove(ctx, &wg, q)
}(query)
}
wg.Wait()

return
}

func remove(ctx context.Context, wg *sync.WaitGroup, query *komputer.FileQuery) error {
defer wg.Done()
select {
case <-ctx.Done():
return context.Canceled
default:
}

uid, name := query.GetUuid(), query.GetName()

var path string
if uid != nil && name != "" {
path = audio.Path(fmt.Sprintf("%s-%s", name, uid.Uuid))
}

if path == "" {
return os.ErrNotExist
}

return os.Remove(path)
}
69 changes: 69 additions & 0 deletions server/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package server

import (
"context"
"errors"
"fmt"
komputer "github.com/wittano/komputer/api/proto"
"github.com/wittano/komputer/audio"
"io"
"log/slog"
"os"
)

type fileServer struct {
komputer.UnimplementedAudioFileServiceServer
}

func (fs fileServer) Download(request *komputer.DownloadRequest, server komputer.AudioFileService_DownloadServer) error {
if request == nil {
return errors.New("download: missing request data")
}

path := audio.Path(filename(request))
f, err := os.Open(path)
if err != nil {
slog.Error("failed find f "+path, err)
return err
}
defer f.Close()

ctx := server.Context()

buf := make([]byte, 1024)
for {
select {
case <-ctx.Done():
return context.Canceled
default:
}

n, err := f.Read(buf)
if errors.Is(err, io.EOF) {
break
} else if err != nil {
return err
}

if err = server.Send(&komputer.FileBuffer{Content: buf, Size: uint64(n)}); err != nil {
return err
}
}

return nil
}

func filename(request *komputer.DownloadRequest) (name string) {
if request == nil {
return
}

var uuid *komputer.UUID
uuid, name = request.GetUuid(), request.GetName()

if uuid == nil {
return
}

return fmt.Sprintf("%s-%s", name, uuid)
}
8 changes: 2 additions & 6 deletions server/joke.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,8 @@ func (j jokeServer) FindAll(identity *komputer.JokeParamsPagination, server komp
return err
}

page := identity.Page
if page == nil {
page = &komputer.Pagination{Size: 10}
}

jokes, err := j.Db.Jokes(server.Context(), p, identity.Page)
page := paginationOrDefault(identity.Page)
jokes, err := j.Db.Jokes(server.Context(), p, page)
if err != nil {
return err
}
Expand Down
13 changes: 13 additions & 0 deletions server/pagination.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package server

import komputer "github.com/wittano/komputer/api/proto"

func paginationOrDefault(p *komputer.Pagination) *komputer.Pagination {
if p == nil {
return &komputer.Pagination{
Size: 10,
}
}

return p
}
2 changes: 2 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ func newGRPGServer() *grpc.Server {
mongodb := db.Mongodb(ctx)

komputer.RegisterJokeServiceServer(s, &jokeServer{Db: joke.Database{Mongodb: mongodb}})
komputer.RegisterAudioServiceServer(s, &audioServer{})
komputer.RegisterAudioFileServiceServer(s, &fileServer{})

return s
}

0 comments on commit 6557e7b

Please sign in to comment.