This commit is contained in:
royalcat 2024-03-28 16:09:42 +03:00
parent 7b1863109c
commit ef751771d2
107 changed files with 9435 additions and 850 deletions

View file

@ -57,6 +57,11 @@ type ComplexityRoot struct {
Size func(childComplexity int) int
}
CleanupResponse struct {
Count func(childComplexity int) int
List func(childComplexity int) int
}
Dir struct {
Name func(childComplexity int) int
}
@ -70,8 +75,14 @@ type ComplexityRoot struct {
Size func(childComplexity int) int
}
ListDirResponse struct {
Entries func(childComplexity int) int
Root func(childComplexity int) int
}
Mutation struct {
CleanupTorrents func(childComplexity int, files *bool, dryRun bool) int
DedupeStorage func(childComplexity int) int
DownloadTorrent func(childComplexity int, infohash string, file *string) int
ValidateTorrents func(childComplexity int, filter model.TorrentFilter) int
}
@ -138,12 +149,13 @@ type ComplexityRoot struct {
type MutationResolver interface {
ValidateTorrents(ctx context.Context, filter model.TorrentFilter) (bool, error)
CleanupTorrents(ctx context.Context, files *bool, dryRun bool) (int64, error)
CleanupTorrents(ctx context.Context, files *bool, dryRun bool) (*model.CleanupResponse, error)
DownloadTorrent(ctx context.Context, infohash string, file *string) (*model.DownloadTorrentResponse, error)
DedupeStorage(ctx context.Context) (int64, error)
}
type QueryResolver interface {
Torrents(ctx context.Context, filter *model.TorrentsFilter, pagination *model.Pagination) ([]*model.Torrent, error)
FsListDir(ctx context.Context, path string) ([]model.DirEntry, error)
FsListDir(ctx context.Context, path string) (*model.ListDirResponse, error)
}
type SubscriptionResolver interface {
TaskProgress(ctx context.Context, taskID string) (<-chan model.Progress, error)
@ -190,6 +202,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.ArchiveFS.Size(childComplexity), true
case "CleanupResponse.count":
if e.complexity.CleanupResponse.Count == nil {
break
}
return e.complexity.CleanupResponse.Count(childComplexity), true
case "CleanupResponse.list":
if e.complexity.CleanupResponse.List == nil {
break
}
return e.complexity.CleanupResponse.List(childComplexity), true
case "Dir.name":
if e.complexity.Dir.Name == nil {
break
@ -218,6 +244,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.File.Size(childComplexity), true
case "ListDirResponse.entries":
if e.complexity.ListDirResponse.Entries == nil {
break
}
return e.complexity.ListDirResponse.Entries(childComplexity), true
case "ListDirResponse.root":
if e.complexity.ListDirResponse.Root == nil {
break
}
return e.complexity.ListDirResponse.Root(childComplexity), true
case "Mutation.cleanupTorrents":
if e.complexity.Mutation.CleanupTorrents == nil {
break
@ -230,6 +270,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.CleanupTorrents(childComplexity, args["files"].(*bool), args["dryRun"].(bool)), true
case "Mutation.dedupeStorage":
if e.complexity.Mutation.DedupeStorage == nil {
break
}
return e.complexity.Mutation.DedupeStorage(childComplexity), true
case "Mutation.downloadTorrent":
if e.complexity.Mutation.DownloadTorrent == nil {
break
@ -602,28 +649,34 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
var sources = []*ast.Source{
{Name: "../../../graphql/mutation.graphql", Input: `type Mutation {
validateTorrents(filter: TorrentFilter!): Boolean!
cleanupTorrents(files: Boolean, dryRun: Boolean!): Int!
downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse
validateTorrents(filter: TorrentFilter!): Boolean!
cleanupTorrents(files: Boolean, dryRun: Boolean!): CleanupResponse!
downloadTorrent(infohash: String!, file: String): DownloadTorrentResponse
dedupeStorage: Int!
}
input TorrentFilter @oneOf {
everything: Boolean
infohash: String
# pathGlob: String!
everything: Boolean
infohash: String
# pathGlob: String!
}
type DownloadTorrentResponse {
task: Task
task: Task
}
type CleanupResponse {
count: Int!
list: [String!]!
}
type Task {
id: ID!
}`, BuiltIn: false},
id: ID!
}
`, BuiltIn: false},
{Name: "../../../graphql/query.graphql", Input: `type Query {
torrents(filter: TorrentsFilter, pagination: Pagination): [Torrent!]!
fsListDir(path: String!): [DirEntry!]!
fsListDir(path: String!): ListDirResponse!
}
input TorrentsFilter {
@ -634,6 +687,11 @@ input TorrentsFilter {
peersCount: IntFilter
}
type ListDirResponse {
root: DirEntry!
entries: [DirEntry!]!
}
input Pagination {
offset: Int!
limit: Int!
@ -1008,6 +1066,94 @@ func (ec *executionContext) fieldContext_ArchiveFS_size(ctx context.Context, fie
return fc, nil
}
func (ec *executionContext) _CleanupResponse_count(ctx context.Context, field graphql.CollectedField, obj *model.CleanupResponse) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_CleanupResponse_count(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 obj.Count, nil
})
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.(int64)
fc.Result = res
return ec.marshalNInt2int64(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_CleanupResponse_count(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "CleanupResponse",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _CleanupResponse_list(ctx context.Context, field graphql.CollectedField, obj *model.CleanupResponse) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_CleanupResponse_list(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 obj.List, nil
})
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.([]string)
fc.Result = res
return ec.marshalNString2ᚕstringᚄ(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_CleanupResponse_list(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "CleanupResponse",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Dir_name(ctx context.Context, field graphql.CollectedField, obj *model.Dir) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Dir_name(ctx, field)
if err != nil {
@ -1185,6 +1331,94 @@ func (ec *executionContext) fieldContext_File_size(ctx context.Context, field gr
return fc, nil
}
func (ec *executionContext) _ListDirResponse_root(ctx context.Context, field graphql.CollectedField, obj *model.ListDirResponse) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ListDirResponse_root(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 obj.Root, nil
})
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.(model.DirEntry)
fc.Result = res
return ec.marshalNDirEntry2gitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐDirEntry(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_ListDirResponse_root(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ListDirResponse",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("FieldContext.Child cannot be called on type INTERFACE")
},
}
return fc, nil
}
func (ec *executionContext) _ListDirResponse_entries(ctx context.Context, field graphql.CollectedField, obj *model.ListDirResponse) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ListDirResponse_entries(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 obj.Entries, nil
})
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.([]model.DirEntry)
fc.Result = res
return ec.marshalNDirEntry2ᚕgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐDirEntryᚄ(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_ListDirResponse_entries(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ListDirResponse",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("FieldContext.Child cannot be called on type INTERFACE")
},
}
return fc, nil
}
func (ec *executionContext) _Mutation_validateTorrents(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_validateTorrents(ctx, field)
if err != nil {
@ -1266,9 +1500,9 @@ func (ec *executionContext) _Mutation_cleanupTorrents(ctx context.Context, field
}
return graphql.Null
}
res := resTmp.(int64)
res := resTmp.(*model.CleanupResponse)
fc.Result = res
return ec.marshalNInt2int64(ctx, field.Selections, res)
return ec.marshalNCleanupResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐCleanupResponse(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_cleanupTorrents(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@ -1278,7 +1512,13 @@ func (ec *executionContext) fieldContext_Mutation_cleanupTorrents(ctx context.Co
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Int does not have child fields")
switch field.Name {
case "count":
return ec.fieldContext_CleanupResponse_count(ctx, field)
case "list":
return ec.fieldContext_CleanupResponse_list(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type CleanupResponse", field.Name)
},
}
defer func() {
@ -1351,6 +1591,50 @@ func (ec *executionContext) fieldContext_Mutation_downloadTorrent(ctx context.Co
return fc, nil
}
func (ec *executionContext) _Mutation_dedupeStorage(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_dedupeStorage(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().DedupeStorage(rctx)
})
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.(int64)
fc.Result = res
return ec.marshalNInt2int64(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_dedupeStorage(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 Int does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Query_torrents(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Query_torrents(ctx, field)
if err != nil {
@ -1450,9 +1734,9 @@ func (ec *executionContext) _Query_fsListDir(ctx context.Context, field graphql.
}
return graphql.Null
}
res := resTmp.([]model.DirEntry)
res := resTmp.(*model.ListDirResponse)
fc.Result = res
return ec.marshalNDirEntry2ᚕgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐDirEntryᚄ(ctx, field.Selections, res)
return ec.marshalNListDirResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐListDirResponse(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Query_fsListDir(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
@ -1462,7 +1746,13 @@ func (ec *executionContext) fieldContext_Query_fsListDir(ctx context.Context, fi
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("FieldContext.Child cannot be called on type INTERFACE")
switch field.Name {
case "root":
return ec.fieldContext_ListDirResponse_root(ctx, field)
case "entries":
return ec.fieldContext_ListDirResponse_entries(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ListDirResponse", field.Name)
},
}
defer func() {
@ -1723,6 +2013,8 @@ func (ec *executionContext) fieldContext_Schema_mutation(ctx context.Context, fi
return ec.fieldContext_Mutation_cleanupTorrents(ctx, field)
case "downloadTorrent":
return ec.fieldContext_Mutation_downloadTorrent(ctx, field)
case "dedupeStorage":
return ec.fieldContext_Mutation_dedupeStorage(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Mutation", field.Name)
},
@ -5400,6 +5692,50 @@ func (ec *executionContext) _ArchiveFS(ctx context.Context, sel ast.SelectionSet
return out
}
var cleanupResponseImplementors = []string{"CleanupResponse"}
func (ec *executionContext) _CleanupResponse(ctx context.Context, sel ast.SelectionSet, obj *model.CleanupResponse) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, cleanupResponseImplementors)
out := graphql.NewFieldSet(fields)
deferred := make(map[string]*graphql.FieldSet)
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("CleanupResponse")
case "count":
out.Values[i] = ec._CleanupResponse_count(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "list":
out.Values[i] = ec._CleanupResponse_list(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var dirImplementors = []string{"Dir", "DirEntry"}
func (ec *executionContext) _Dir(ctx context.Context, sel ast.SelectionSet, obj *model.Dir) graphql.Marshaler {
@ -5519,6 +5855,50 @@ func (ec *executionContext) _File(ctx context.Context, sel ast.SelectionSet, obj
return out
}
var listDirResponseImplementors = []string{"ListDirResponse"}
func (ec *executionContext) _ListDirResponse(ctx context.Context, sel ast.SelectionSet, obj *model.ListDirResponse) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, listDirResponseImplementors)
out := graphql.NewFieldSet(fields)
deferred := make(map[string]*graphql.FieldSet)
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("ListDirResponse")
case "root":
out.Values[i] = ec._ListDirResponse_root(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "entries":
out.Values[i] = ec._ListDirResponse_entries(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var mutationImplementors = []string{"Mutation"}
func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {
@ -5556,6 +5936,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) {
return ec._Mutation_downloadTorrent(ctx, field)
})
case "dedupeStorage":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_dedupeStorage(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@ -6551,6 +6938,20 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
return res
}
func (ec *executionContext) marshalNCleanupResponse2gitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐCleanupResponse(ctx context.Context, sel ast.SelectionSet, v model.CleanupResponse) graphql.Marshaler {
return ec._CleanupResponse(ctx, sel, &v)
}
func (ec *executionContext) marshalNCleanupResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐCleanupResponse(ctx context.Context, sel ast.SelectionSet, v *model.CleanupResponse) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
return ec._CleanupResponse(ctx, sel, v)
}
func (ec *executionContext) marshalNDirEntry2gitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐDirEntry(ctx context.Context, sel ast.SelectionSet, v model.DirEntry) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
@ -6650,6 +7051,20 @@ func (ec *executionContext) marshalNInt2int64(ctx context.Context, sel ast.Selec
return res
}
func (ec *executionContext) marshalNListDirResponse2gitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐListDirResponse(ctx context.Context, sel ast.SelectionSet, v model.ListDirResponse) graphql.Marshaler {
return ec._ListDirResponse(ctx, sel, &v)
}
func (ec *executionContext) marshalNListDirResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐListDirResponse(ctx context.Context, sel ast.SelectionSet, v *model.ListDirResponse) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
return ec._ListDirResponse(ctx, sel, v)
}
func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) {
res, err := graphql.UnmarshalString(v)
return res, graphql.ErrorOnPath(ctx, err)
@ -6665,6 +7080,38 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
return res
}
func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) {
var vSlice []interface{}
if v != nil {
vSlice = graphql.CoerceList(v)
}
var err error
res := make([]string, len(vSlice))
for i := range vSlice {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
res[i], err = ec.unmarshalNString2string(ctx, vSlice[i])
if err != nil {
return nil, err
}
}
return res, nil
}
func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {
ret := make(graphql.Array, len(v))
for i := range v {
ret[i] = ec.marshalNString2string(ctx, sel, v[i])
}
for _, e := range ret {
if e == graphql.Null {
return graphql.Null
}
}
return ret
}
func (ec *executionContext) marshalNTorrent2ᚕᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐTorrentᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Torrent) graphql.Marshaler {
ret := make(graphql.Array, len(v))
var wg sync.WaitGroup

View file

@ -32,6 +32,11 @@ type BooleanFilter struct {
Eq *bool `json:"eq,omitempty"`
}
type CleanupResponse struct {
Count int64 `json:"count"`
List []string `json:"list"`
}
type DateTimeFilter struct {
Eq *time.Time `json:"eq,omitempty"`
Gt *time.Time `json:"gt,omitempty"`
@ -68,6 +73,11 @@ type IntFilter struct {
In []int64 `json:"in,omitempty"`
}
type ListDirResponse struct {
Root DirEntry `json:"root"`
Entries []DirEntry `json:"entries"`
}
type Mutation struct {
}

View file

@ -46,18 +46,24 @@ func (r *mutationResolver) ValidateTorrents(ctx context.Context, filter model.To
}
// CleanupTorrents is the resolver for the cleanupTorrents field.
func (r *mutationResolver) CleanupTorrents(ctx context.Context, files *bool, dryRun bool) (int64, error) {
func (r *mutationResolver) CleanupTorrents(ctx context.Context, files *bool, dryRun bool) (*model.CleanupResponse, error) {
torrents, err := r.Service.ListTorrents(ctx)
if err != nil {
return 0, err
return nil, err
}
if files != nil && *files {
r, err := r.Service.Storage.CleanupFiles(ctx, torrents, dryRun)
return int64(r), err
return &model.CleanupResponse{
Count: int64(len(r)),
List: r,
}, err
} else {
r, err := r.Service.Storage.CleanupDirs(ctx, torrents, dryRun)
return int64(r), err
return &model.CleanupResponse{
Count: int64(len(r)),
List: r,
}, err
}
}
@ -80,6 +86,15 @@ func (r *mutationResolver) DownloadTorrent(ctx context.Context, infohash string,
return &model.DownloadTorrentResponse{}, nil
}
// DedupeStorage is the resolver for the dedupeStorage field.
func (r *mutationResolver) DedupeStorage(ctx context.Context) (int64, error) {
deduped, err := r.Service.Storage.Dedupe(ctx)
if err != nil {
return 0, err
}
return int64(deduped), nil
}
// Mutation returns graph.MutationResolver implementation.
func (r *Resolver) Mutation() graph.MutationResolver { return &mutationResolver{r} }

View file

@ -6,6 +6,7 @@ package resolver
import (
"context"
"io/fs"
graph "git.kmsign.ru/royalcat/tstor/src/delivery/graphql"
"git.kmsign.ru/royalcat/tstor/src/delivery/graphql/model"
@ -64,51 +65,75 @@ func (r *queryResolver) Torrents(ctx context.Context, filter *model.TorrentsFilt
return tr, nil
}
type dirEntry interface {
Name() string
IsDir() bool
}
func fillDirEntry(e dirEntry) model.DirEntry {
switch e.(type) {
case *vfs.ArchiveFS:
e := e.(*vfs.ArchiveFS)
return model.ArchiveFs{
Name: e.Name(),
Size: e.Size(),
}
case *vfs.ResolverFS:
e := e.(*vfs.ResolverFS)
return model.ResolverFs{
Name: e.Name(),
}
case *vfs.TorrentFs:
e := e.(*vfs.TorrentFs)
return model.TorrentFs{
Name: e.Name(),
Torrent: model.MapTorrent(e.Torrent),
}
default:
if e.IsDir() {
return model.Dir{
Name: e.Name(),
}
}
if de, ok := e.(fs.DirEntry); ok {
info, _ := de.Info()
return model.File{
Name: e.Name(),
Size: info.Size(),
}
}
if fe, ok := e.(fs.FileInfo); ok {
return model.File{
Name: fe.Name(),
Size: fe.Size(),
}
}
}
panic("this dir entry is strange af")
}
// FsListDir is the resolver for the fsListDir field.
func (r *queryResolver) FsListDir(ctx context.Context, path string) ([]model.DirEntry, error) {
func (r *queryResolver) FsListDir(ctx context.Context, path string) (*model.ListDirResponse, error) {
root, err := r.VFS.Stat(ctx, path)
if err != nil {
return nil, err
}
entries, err := r.VFS.ReadDir(ctx, path)
if err != nil {
return nil, err
}
out := []model.DirEntry{}
for _, e := range entries {
switch e.(type) {
case *vfs.ArchiveFS:
e := e.(*vfs.ArchiveFS)
out = append(out, model.ArchiveFs{
Name: e.Name(),
Size: e.Size,
})
case *vfs.ResolverFS:
e := e.(*vfs.ResolverFS)
out = append(out, model.ResolverFs{
Name: e.Name(),
})
case *vfs.TorrentFs:
e := e.(*vfs.TorrentFs)
out = append(out, model.TorrentFs{
Name: e.Name(),
Torrent: model.MapTorrent(e.Torrent),
})
default:
if e.IsDir() {
out = append(out, model.Dir{Name: e.Name()})
} else {
info, err := e.Info()
if err != nil {
return nil, err
}
out = append(out, model.File{
Name: e.Name(),
Size: info.Size(),
})
}
}
out = append(out, fillDirEntry(e))
}
return out, nil
return &model.ListDirResponse{
Root: fillDirEntry(root),
Entries: out,
}, nil
}
// Query returns graph.QueryResolver implementation.

View file

@ -15,7 +15,7 @@ import (
"github.com/shurcooL/httpfs/html/vfstemplate"
)
func New(fc *filecache.Cache, ss *service.Stats, s *service.Service, vfs vfs.Filesystem, logPath string, cfg *config.Config) error {
func New(fc *filecache.Cache, ss *service.Stats, s *service.Service, vfs vfs.Filesystem, logPath string, cfg *config.Settings) error {
log := slog.With()
gin.SetMode(gin.ReleaseMode)

View file

@ -7,6 +7,7 @@ import (
"git.kmsign.ru/royalcat/tstor/src/delivery/graphql/resolver"
"git.kmsign.ru/royalcat/tstor/src/host/service"
"git.kmsign.ru/royalcat/tstor/src/host/vfs"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/lru"
@ -33,7 +34,11 @@ func GraphQLHandler(service *service.Service, vfs vfs.Filesystem) http.Handler {
graphqlHandler.SetQueryCache(lru.New(1000))
graphqlHandler.Use(extension.Introspection{})
graphqlHandler.Use(extension.AutomaticPersistedQuery{Cache: lru.New(100)})
graphqlHandler.Use(otelgqlgen.Middleware())
graphqlHandler.Use(otelgqlgen.Middleware(
otelgqlgen.WithCreateSpanFromFields(func(ctx *graphql.FieldContext) bool {
return ctx.Field.Directives.ForName("link") != nil
}),
))
return graphqlHandler
}