upload file
All checks were successful
docker / build-docker (linux/amd64) (push) Successful in 1m39s
docker / build-docker (linux/386) (push) Successful in 1m48s
docker / build-docker (linux/arm64) (push) Successful in 8m42s
docker / build-docker (linux/arm64/v8) (push) Successful in 8m40s
docker / build-docker (linux/arm/v7) (push) Successful in 9m11s

This commit is contained in:
royalcat 2024-05-15 00:40:38 +03:00
parent 974814c281
commit fa1fdcfc63
5 changed files with 155 additions and 1 deletions

View file

@ -2,6 +2,7 @@ type Mutation {
validateTorrents(filter: TorrentFilter!): Boolean! validateTorrents(filter: TorrentFilter!): Boolean!
cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse! cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse!
downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse
uploadFile(dir: String!, file: Upload!): Boolean!
dedupeStorage: Int! dedupeStorage: Int!
} }

View file

@ -2,6 +2,7 @@ directive @oneOf on INPUT_OBJECT | FIELD_DEFINITION
directive @stream on FIELD_DEFINITION directive @stream on FIELD_DEFINITION
scalar DateTime scalar DateTime
scalar Upload
type Schema { type Schema {
query: Query query: Query

View file

@ -75,6 +75,7 @@ type ComplexityRoot struct {
CleanupTorrents func(childComplexity int, files *bool, dryRun bool) int CleanupTorrents func(childComplexity int, files *bool, dryRun bool) int
DedupeStorage func(childComplexity int) int DedupeStorage func(childComplexity int) int
DownloadTorrent func(childComplexity int, infohash string, file *string) int DownloadTorrent func(childComplexity int, infohash string, file *string) int
UploadFile func(childComplexity int, dir string, file graphql.Upload) int
ValidateTorrents func(childComplexity int, filter model.TorrentFilter) int ValidateTorrents func(childComplexity int, filter model.TorrentFilter) int
} }
@ -164,6 +165,7 @@ type MutationResolver interface {
ValidateTorrents(ctx context.Context, filter model.TorrentFilter) (bool, error) ValidateTorrents(ctx context.Context, filter model.TorrentFilter) (bool, error)
CleanupTorrents(ctx context.Context, files *bool, dryRun bool) (*model.CleanupResponse, error) CleanupTorrents(ctx context.Context, files *bool, dryRun bool) (*model.CleanupResponse, error)
DownloadTorrent(ctx context.Context, infohash string, file *string) (*model.DownloadTorrentResponse, error) DownloadTorrent(ctx context.Context, infohash string, file *string) (*model.DownloadTorrentResponse, error)
UploadFile(ctx context.Context, dir string, file graphql.Upload) (bool, error)
DedupeStorage(ctx context.Context) (int64, error) DedupeStorage(ctx context.Context) (int64, error)
} }
type QueryResolver interface { type QueryResolver interface {
@ -283,6 +285,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.DownloadTorrent(childComplexity, args["infohash"].(string), args["file"].(*string)), true return e.complexity.Mutation.DownloadTorrent(childComplexity, args["infohash"].(string), args["file"].(*string)), true
case "Mutation.uploadFile":
if e.complexity.Mutation.UploadFile == nil {
break
}
args, err := ec.field_Mutation_uploadFile_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.UploadFile(childComplexity, args["dir"].(string), args["file"].(graphql.Upload)), true
case "Mutation.validateTorrents": case "Mutation.validateTorrents":
if e.complexity.Mutation.ValidateTorrents == nil { if e.complexity.Mutation.ValidateTorrents == nil {
break break
@ -716,6 +730,7 @@ var sources = []*ast.Source{
validateTorrents(filter: TorrentFilter!): Boolean! validateTorrents(filter: TorrentFilter!): Boolean!
cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse! cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse!
downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse
uploadFile(dir: String!, file: Upload!): Boolean!
dedupeStorage: Int! dedupeStorage: Int!
} }
@ -789,6 +804,7 @@ input BooleanFilter @oneOf {
directive @stream on FIELD_DEFINITION directive @stream on FIELD_DEFINITION
scalar DateTime scalar DateTime
scalar Upload
type Schema { type Schema {
query: Query query: Query
@ -942,6 +958,30 @@ func (ec *executionContext) field_Mutation_downloadTorrent_args(ctx context.Cont
return args, nil return args, nil
} }
func (ec *executionContext) field_Mutation_uploadFile_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 string
if tmp, ok := rawArgs["dir"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("dir"))
arg0, err = ec.unmarshalNString2string(ctx, tmp)
if err != nil {
return nil, err
}
}
args["dir"] = arg0
var arg1 graphql.Upload
if tmp, ok := rawArgs["file"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("file"))
arg1, err = ec.unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx, tmp)
if err != nil {
return nil, err
}
}
args["file"] = arg1
return args, nil
}
func (ec *executionContext) field_Mutation_validateTorrents_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { func (ec *executionContext) field_Mutation_validateTorrents_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error var err error
args := map[string]interface{}{} args := map[string]interface{}{}
@ -1492,6 +1532,61 @@ func (ec *executionContext) fieldContext_Mutation_downloadTorrent(ctx context.Co
return fc, nil return fc, nil
} }
func (ec *executionContext) _Mutation_uploadFile(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_uploadFile(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().UploadFile(rctx, fc.Args["dir"].(string), fc.Args["file"].(graphql.Upload))
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(bool)
fc.Result = res
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_uploadFile(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Boolean does not have child fields")
},
}
defer func() {
if r := recover(); r != nil {
err = ec.Recover(ctx, r)
ec.Error(ctx, err)
}
}()
ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_Mutation_uploadFile_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _Mutation_dedupeStorage(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { func (ec *executionContext) _Mutation_dedupeStorage(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_dedupeStorage(ctx, field) fc, err := ec.fieldContext_Mutation_dedupeStorage(ctx, field)
if err != nil { if err != nil {
@ -1951,6 +2046,8 @@ func (ec *executionContext) fieldContext_Schema_mutation(ctx context.Context, fi
return ec.fieldContext_Mutation_cleanupTorrents(ctx, field) return ec.fieldContext_Mutation_cleanupTorrents(ctx, field)
case "downloadTorrent": case "downloadTorrent":
return ec.fieldContext_Mutation_downloadTorrent(ctx, field) return ec.fieldContext_Mutation_downloadTorrent(ctx, field)
case "uploadFile":
return ec.fieldContext_Mutation_uploadFile(ctx, field)
case "dedupeStorage": case "dedupeStorage":
return ec.fieldContext_Mutation_dedupeStorage(ctx, field) return ec.fieldContext_Mutation_dedupeStorage(ctx, field)
} }
@ -6226,6 +6323,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_downloadTorrent(ctx, field) return ec._Mutation_downloadTorrent(ctx, field)
}) })
case "uploadFile":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_uploadFile(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "dedupeStorage": case "dedupeStorage":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_dedupeStorage(ctx, field) return ec._Mutation_dedupeStorage(ctx, field)
@ -7797,6 +7901,21 @@ func (ec *executionContext) marshalNTorrentPeer2ᚖgitᚗkmsignᚗruᚋroyalcat
return ec._TorrentPeer(ctx, sel, v) return ec._TorrentPeer(ctx, sel, v)
} }
func (ec *executionContext) unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, v interface{}) (graphql.Upload, error) {
res, err := graphql.UnmarshalUpload(v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, sel ast.SelectionSet, v graphql.Upload) graphql.Marshaler {
res := graphql.MarshalUpload(v)
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {
return ec.___Directive(ctx, sel, &v) return ec.___Directive(ctx, sel, &v)
} }

View file

@ -6,11 +6,16 @@ package resolver
import ( import (
"context" "context"
"fmt"
"io"
"os"
pathlib "path"
"git.kmsign.ru/royalcat/tstor/pkg/uuid" "git.kmsign.ru/royalcat/tstor/pkg/uuid"
graph "git.kmsign.ru/royalcat/tstor/src/delivery/graphql" graph "git.kmsign.ru/royalcat/tstor/src/delivery/graphql"
"git.kmsign.ru/royalcat/tstor/src/delivery/graphql/model" "git.kmsign.ru/royalcat/tstor/src/delivery/graphql/model"
"git.kmsign.ru/royalcat/tstor/src/host/service" "git.kmsign.ru/royalcat/tstor/src/host/service"
"github.com/99designs/gqlgen/graphql"
aih "github.com/anacrolix/torrent/types/infohash" aih "github.com/anacrolix/torrent/types/infohash"
) )
@ -86,6 +91,34 @@ func (r *mutationResolver) DownloadTorrent(ctx context.Context, infohash string,
return &model.DownloadTorrentResponse{}, nil return &model.DownloadTorrentResponse{}, nil
} }
// UploadFile is the resolver for the uploadFile field.
func (r *mutationResolver) UploadFile(ctx context.Context, dir string, file graphql.Upload) (bool, error) {
dir = pathlib.Join(r.Service.SourceDir, dir)
dirInfo, err := os.Stat(dir)
if err != nil {
return false, err
}
if !dirInfo.IsDir() {
return false, fmt.Errorf("path %s is not a directory", dir)
}
filename := pathlib.Join(dir, file.Filename)
target, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, os.ModePerm)
defer target.Close()
if err != nil {
return false, err
}
_, err = io.CopyN(target, file.File, file.Size)
if err != nil {
return false, err
}
return true, nil
}
// DedupeStorage is the resolver for the dedupeStorage field. // DedupeStorage is the resolver for the dedupeStorage field.
func (r *mutationResolver) DedupeStorage(ctx context.Context) (int64, error) { func (r *mutationResolver) DedupeStorage(ctx context.Context) (int64, error) {
deduped, err := r.Service.Storage.Dedupe(ctx) deduped, err := r.Service.Storage.Dedupe(ctx)

View file

@ -46,7 +46,7 @@ type Mutation {
validateTorrents(filter: TorrentFilter!): Boolean! validateTorrents(filter: TorrentFilter!): Boolean!
cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse! cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse!
downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse
uploadFile(file: Upload!): Boolean! uploadFile(dir: String!, file: Upload!): Boolean!
dedupeStorage: Int! dedupeStorage: Int!
} }
input Pagination { input Pagination {