From 52999672f82d5b67962a98914d03975eb2e26ffb Mon Sep 17 00:00:00 2001
From: royalcat <k.adamovich20@gmail.com>
Date: Fri, 4 Apr 2025 02:15:26 +0400
Subject: [PATCH] separate filters

---
 server/.gqlgen.yml                            |    3 +
 server/go.sum                                 |   17 +
 .../{graphql/model => filter}/filter.go       |   30 +-
 server/src/delivery/graphql/generated.go      | 1437 +----------------
 server/src/delivery/graphql/model/entry.go    |   48 +
 .../src/delivery/graphql/model/models_gen.go  |   58 -
 .../delivery/graphql/resolver/fs.resolvers.go |   30 +-
 .../graphql/resolver/mutation.resolvers.go    |    8 +-
 .../qbittorrent_mutation.resolvers.go         |   45 -
 .../resolver/qbittorrent_query.resolvers.go   |   54 -
 .../resolver/qbittorrent_types.resolvers.go   |   23 -
 .../graphql/resolver/query.resolvers.go       |    2 +-
 .../resolver/subscription.resolvers.go        |    2 +-
 13 files changed, 121 insertions(+), 1636 deletions(-)
 rename server/src/delivery/{graphql/model => filter}/filter.go (65%)
 delete mode 100644 server/src/delivery/graphql/resolver/qbittorrent_mutation.resolvers.go
 delete mode 100644 server/src/delivery/graphql/resolver/qbittorrent_query.resolvers.go
 delete mode 100644 server/src/delivery/graphql/resolver/qbittorrent_types.resolvers.go

diff --git a/server/.gqlgen.yml b/server/.gqlgen.yml
index c50c698..349a706 100644
--- a/server/.gqlgen.yml
+++ b/server/.gqlgen.yml
@@ -42,3 +42,6 @@ models:
     extraFields:
       InfoHash:
         type: "string"
+
+autobind:
+  - "git.kmsign.ru/royalcat/tstor/server/src/delivery/filter"
diff --git a/server/go.sum b/server/go.sum
index 79182eb..567a79e 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -405,6 +405,7 @@ github.com/cncf/xds/go v0.0.0-20240822171458-6449f94b4d59/go.mod h1:W+zGtBO5Y1Ig
 github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
 github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
 github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -468,6 +469,7 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
 github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
@@ -501,6 +503,7 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
 github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
 github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
 github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
+github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
 github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/goccy/go-yaml v1.9.8/go.mod h1:JubOolP3gh0HpiBc4BLRD4YmjEjHAmIIB2aaXKkTfoE=
 github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng=
@@ -661,7 +664,9 @@ github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
+github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
 github.com/goware/singleflight v0.2.0 h1:e/hZsvNmbLoiZLx3XbihH01oXYA2MwLFo4e+N017U4c=
 github.com/goware/singleflight v0.2.0/go.mod h1:SsAslCMS7HizXdbYcBQRBLC7HcNmFrHutRt3Hz6wovY=
 github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
@@ -783,10 +788,13 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/polydawn/go-timeless-api v0.0.0-20201121022836-7399661094a6/go.mod h1:z2fMUifgtqrZiNLgzF4ZR8pX+YFLCmAp1jJTSTvyDMM=
 github.com/polydawn/go-timeless-api v0.0.0-20220821201550-b93919e12c56 h1:LQ103HjiN76aqIxnQNgdZ+7NveuKd45+Q+TYGJVVsyw=
+github.com/polydawn/go-timeless-api v0.0.0-20220821201550-b93919e12c56/go.mod h1:OAK6p/pJUakz6jQ+HlSw16gVMnuohxqJFGoypUYyr4w=
 github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
 github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
+github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
 github.com/polydawn/rio v0.0.0-20201122020833-6192319df581/go.mod h1:mwZtAu36D3fSNzVLN1we6PFdRU4VeE+RXLTZiOiQlJ0=
 github.com/polydawn/rio v0.0.0-20220823181337-7c31ad9831a4 h1:SNhgcsCNGEqz7Tp46YHEvcjF1s5x+ZGWcVzFoghkuMA=
+github.com/polydawn/rio v0.0.0-20220823181337-7c31ad9831a4/go.mod h1:fZ8OGW5CVjZHyQeNs8QH3X3tUxrPcx1jxHSl2z6Xv00=
 github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
 github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -829,11 +837,13 @@ github.com/royalcat/kv/testsuite v0.0.0-20240723124828-253d2ecf5312/go.mod h1:mn
 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
 github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
 github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
 github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
+github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
 github.com/samber/slog-multi v1.0.2 h1:6BVH9uHGAsiGkbbtQgAOQJMpKgV8unMrHhhJaw+X1EQ=
 github.com/samber/slog-multi v1.0.2/go.mod h1:uLAvHpGqbYgX4FSL0p1ZwoLuveIAJvBECtE07XmYvFo=
 github.com/samber/slog-zerolog v1.0.0 h1:YpRy0xux1uJr0Ng3wrEjv9nyvb4RAoNqkS611UjzeG8=
@@ -842,10 +852,13 @@ github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
 github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
 github.com/shoenig/test v1.8.0 h1:8f4lrmjkoSykT+EfiTtJuWbV4eaNEBWsYXcl1n6C6BY=
 github.com/shoenig/test v1.8.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
 github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4=
 github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
 github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
@@ -880,6 +893,7 @@ github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vl
 github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
 github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
 github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
+github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
 github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@@ -892,6 +906,7 @@ github.com/warpfork/go-errcat v0.0.0-20180917083543-335044ffc86e h1:FIB2fi7XJGHI
 github.com/warpfork/go-errcat v0.0.0-20180917083543-335044ffc86e/go.mod h1:/qe02xr3jvTUz8u/PV0FHGpP8t96OQNP7U9BJMwMLEw=
 github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
 github.com/willscott/go-nfs-client v0.0.0-20240104095149-b44639837b00 h1:U0DnHRZFzoIV1oFEZczg5XyPut9yxk9jjtax/9Bxr/o=
 github.com/willscott/go-nfs-client v0.0.0-20240104095149-b44639837b00/go.mod h1:Tq++Lr/FgiS3X48q5FETemXiSLGuYMQT2sPjYNPJSwA=
 github.com/willscott/memphis v0.0.0-20210922141505-529d4987ab7e h1:1eHCP4w7tMmpfFBdrd5ff+vYU9THtrtA1yM9f0TLlJw=
@@ -921,6 +936,7 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
 go.opentelemetry.io/contrib v1.26.0 h1:8/CmxLl5uDm37V9rdqbZcVLvYigAE2vMostBq3nGDrI=
+go.opentelemetry.io/contrib v1.26.0/go.mod h1:Tmhw9grdWtmXy6DxZNpIAudzYJqLeEM2P6QTZQSRwU8=
 go.opentelemetry.io/contrib/bridges/otelslog v0.10.0 h1:lRKWBp9nWoBe1HKXzc3ovkro7YZSb72X2+3zYNxfXiU=
 go.opentelemetry.io/contrib/bridges/otelslog v0.10.0/go.mod h1:D+iyUv/Wxbw5LUDO5oh7x744ypftIryiWjoj42I6EKs=
 go.opentelemetry.io/contrib/detectors/gcp v1.28.0/go.mod h1:9BIqH22qyHWAiZxQh0whuJygro59z+nbMVuc7ciiGug=
@@ -1028,6 +1044,7 @@ go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
diff --git a/server/src/delivery/graphql/model/filter.go b/server/src/delivery/filter/filter.go
similarity index 65%
rename from server/src/delivery/graphql/model/filter.go
rename to server/src/delivery/filter/filter.go
index f98bf12..0989f93 100644
--- a/server/src/delivery/graphql/model/filter.go
+++ b/server/src/delivery/filter/filter.go
@@ -1,14 +1,24 @@
-package model
+package filter
 
 import (
 	"slices"
 	"strings"
+	"time"
 )
 
 type Filter[T any] interface {
 	Include(v T) bool
 }
 
+type IntFilter struct {
+	Eq  *int64  `json:"eq,omitempty"`
+	Gt  *int64  `json:"gt,omitempty"`
+	Lt  *int64  `json:"lt,omitempty"`
+	Gte *int64  `json:"gte,omitempty"`
+	Lte *int64  `json:"lte,omitempty"`
+	In  []int64 `json:"in,omitempty"`
+}
+
 func (f *IntFilter) Include(v int64) bool {
 	if f == nil {
 		return true
@@ -29,6 +39,12 @@ func (f *IntFilter) Include(v int64) bool {
 	return true
 }
 
+type StringFilter struct {
+	Eq     *string  `json:"eq,omitempty"`
+	Substr *string  `json:"substr,omitempty"`
+	In     []string `json:"in,omitempty"`
+}
+
 func (f *StringFilter) Include(v string) bool {
 	if f == nil {
 		return true
@@ -43,6 +59,10 @@ func (f *StringFilter) Include(v string) bool {
 	return true
 }
 
+type BooleanFilter struct {
+	Eq *bool `json:"eq,omitempty"`
+}
+
 func (f *BooleanFilter) Include(v bool) bool {
 	if f == nil {
 		return true
@@ -53,6 +73,14 @@ func (f *BooleanFilter) Include(v bool) bool {
 	return true
 }
 
+type DateTimeFilter struct {
+	Eq  *time.Time `json:"eq,omitempty"`
+	Gt  *time.Time `json:"gt,omitempty"`
+	Lt  *time.Time `json:"lt,omitempty"`
+	Gte *time.Time `json:"gte,omitempty"`
+	Lte *time.Time `json:"lte,omitempty"`
+}
+
 // func (f *TorrentPriorityFilter) Include(v types.PiecePriority) bool {
 // 	if f == nil {
 // 		return true
diff --git a/server/src/delivery/graphql/generated.go b/server/src/delivery/graphql/generated.go
index 0fde0fa..c90add6 100644
--- a/server/src/delivery/graphql/generated.go
+++ b/server/src/delivery/graphql/generated.go
@@ -13,6 +13,7 @@ import (
 	"sync/atomic"
 	"time"
 
+	"git.kmsign.ru/royalcat/tstor/server/src/delivery/filter"
 	"git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model"
 	"github.com/99designs/gqlgen/graphql"
 	"github.com/99designs/gqlgen/graphql/introspection"
@@ -41,9 +42,6 @@ type Config struct {
 
 type ResolverRoot interface {
 	Mutation() MutationResolver
-	QBitTorrentDaemonMutation() QBitTorrentDaemonMutationResolver
-	QBitTorrentDaemonQuery() QBitTorrentDaemonQueryResolver
-	QTorrent() QTorrentResolver
 	Query() QueryResolver
 	ResolverFS() ResolverFSResolver
 	SimpleDir() SimpleDirResolver
@@ -57,9 +55,8 @@ type DirectiveRoot struct {
 
 type ComplexityRoot struct {
 	Mutation struct {
-		DedupeStorage     func(childComplexity int) int
-		QbitTorrentDaemon func(childComplexity int) int
-		UploadFile        func(childComplexity int, dir string, file graphql.Upload) int
+		DedupeStorage func(childComplexity int) int
+		UploadFile    func(childComplexity int, dir string, file graphql.Upload) int
 	}
 
 	Plugin struct {
@@ -67,31 +64,6 @@ type ComplexityRoot struct {
 		Name            func(childComplexity int) int
 	}
 
-	QBitCleanupResponse struct {
-		Count  func(childComplexity int) int
-		Hashes func(childComplexity int) int
-	}
-
-	QBitCleanupUnregistredResponse struct {
-		Count  func(childComplexity int) int
-		Hashes func(childComplexity int) int
-	}
-
-	QBitTorrentDaemonMutation struct {
-		Cleanup            func(childComplexity int, run bool) int
-		CleanupUnregistred func(childComplexity int, run bool) int
-	}
-
-	QBitTorrentDaemonQuery struct {
-		Torrents func(childComplexity int, filter *model.QBitTorrentDaemonFilter) int
-	}
-
-	QTorrent struct {
-		Hash        func(childComplexity int) int
-		Name        func(childComplexity int) int
-		SourceFiles func(childComplexity int) int
-	}
-
 	Query struct {
 		FsEntry func(childComplexity int, path string) int
 		Plugins func(childComplexity int) int
@@ -127,20 +99,9 @@ type ComplexityRoot struct {
 }
 
 type MutationResolver interface {
-	QbitTorrentDaemon(ctx context.Context) (*model.QBitTorrentDaemonMutation, error)
 	UploadFile(ctx context.Context, dir string, file graphql.Upload) (bool, error)
 	DedupeStorage(ctx context.Context) (int64, error)
 }
-type QBitTorrentDaemonMutationResolver interface {
-	Cleanup(ctx context.Context, obj *model.QBitTorrentDaemonMutation, run bool) (*model.QBitCleanupResponse, error)
-	CleanupUnregistred(ctx context.Context, obj *model.QBitTorrentDaemonMutation, run bool) (*model.QBitCleanupUnregistredResponse, error)
-}
-type QBitTorrentDaemonQueryResolver interface {
-	Torrents(ctx context.Context, obj *model.QBitTorrentDaemonQuery, filter *model.QBitTorrentDaemonFilter) ([]*model.QTorrent, error)
-}
-type QTorrentResolver interface {
-	SourceFiles(ctx context.Context, obj *model.QTorrent) ([]string, error)
-}
 type QueryResolver interface {
 	Plugins(ctx context.Context) ([]*model.Plugin, error)
 	FsEntry(ctx context.Context, path string) (model.FsEntry, error)
@@ -181,13 +142,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
 
 		return e.complexity.Mutation.DedupeStorage(childComplexity), true
 
-	case "Mutation.qbitTorrentDaemon":
-		if e.complexity.Mutation.QbitTorrentDaemon == nil {
-			break
-		}
-
-		return e.complexity.Mutation.QbitTorrentDaemon(childComplexity), true
-
 	case "Mutation.uploadFile":
 		if e.complexity.Mutation.UploadFile == nil {
 			break
@@ -214,91 +168,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
 
 		return e.complexity.Plugin.Name(childComplexity), true
 
-	case "QBitCleanupResponse.count":
-		if e.complexity.QBitCleanupResponse.Count == nil {
-			break
-		}
-
-		return e.complexity.QBitCleanupResponse.Count(childComplexity), true
-
-	case "QBitCleanupResponse.hashes":
-		if e.complexity.QBitCleanupResponse.Hashes == nil {
-			break
-		}
-
-		return e.complexity.QBitCleanupResponse.Hashes(childComplexity), true
-
-	case "QBitCleanupUnregistredResponse.count":
-		if e.complexity.QBitCleanupUnregistredResponse.Count == nil {
-			break
-		}
-
-		return e.complexity.QBitCleanupUnregistredResponse.Count(childComplexity), true
-
-	case "QBitCleanupUnregistredResponse.hashes":
-		if e.complexity.QBitCleanupUnregistredResponse.Hashes == nil {
-			break
-		}
-
-		return e.complexity.QBitCleanupUnregistredResponse.Hashes(childComplexity), true
-
-	case "QBitTorrentDaemonMutation.cleanup":
-		if e.complexity.QBitTorrentDaemonMutation.Cleanup == nil {
-			break
-		}
-
-		args, err := ec.field_QBitTorrentDaemonMutation_cleanup_args(context.TODO(), rawArgs)
-		if err != nil {
-			return 0, false
-		}
-
-		return e.complexity.QBitTorrentDaemonMutation.Cleanup(childComplexity, args["run"].(bool)), true
-
-	case "QBitTorrentDaemonMutation.cleanupUnregistred":
-		if e.complexity.QBitTorrentDaemonMutation.CleanupUnregistred == nil {
-			break
-		}
-
-		args, err := ec.field_QBitTorrentDaemonMutation_cleanupUnregistred_args(context.TODO(), rawArgs)
-		if err != nil {
-			return 0, false
-		}
-
-		return e.complexity.QBitTorrentDaemonMutation.CleanupUnregistred(childComplexity, args["run"].(bool)), true
-
-	case "QBitTorrentDaemonQuery.torrents":
-		if e.complexity.QBitTorrentDaemonQuery.Torrents == nil {
-			break
-		}
-
-		args, err := ec.field_QBitTorrentDaemonQuery_torrents_args(context.TODO(), rawArgs)
-		if err != nil {
-			return 0, false
-		}
-
-		return e.complexity.QBitTorrentDaemonQuery.Torrents(childComplexity, args["filter"].(*model.QBitTorrentDaemonFilter)), true
-
-	case "QTorrent.hash":
-		if e.complexity.QTorrent.Hash == nil {
-			break
-		}
-
-		return e.complexity.QTorrent.Hash(childComplexity), true
-
-	case "QTorrent.name":
-		if e.complexity.QTorrent.Name == nil {
-			break
-		}
-
-		return e.complexity.QTorrent.Name(childComplexity), true
-
-	case "QTorrent.sourceFiles":
-		if e.complexity.QTorrent.SourceFiles == nil {
-			break
-		}
-
-		return e.complexity.QTorrent.SourceFiles(childComplexity), true
-
 	case "Query.fsEntry":
 		if e.complexity.Query.FsEntry == nil {
 			break
@@ -405,7 +274,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
 		ec.unmarshalInputDateTimeFilter,
 		ec.unmarshalInputIntFilter,
 		ec.unmarshalInputPagination,
-		ec.unmarshalInputQBitTorrentDaemonFilter,
 		ec.unmarshalInputStringFilter,
 	)
 	first := true
@@ -521,9 +389,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
 }
 
 var sources = []*ast.Source{
-	{Name: "../../../../graphql/mutation.graphql", Input: `type Mutation {
-  qbitTorrentDaemon: QBitTorrentDaemonMutation @resolver
-
+	{Name: "../../../graphql/mutation.graphql", Input: `type Mutation {
   uploadFile(dir: String!, file: Upload!): Boolean!
   dedupeStorage: Int!
 }
@@ -532,7 +398,7 @@ type Task {
   id: ID!
 }
 `, BuiltIn: false},
-	{Name: "../../../../graphql/query.graphql", Input: `type Query {
+	{Name: "../../../graphql/query.graphql", Input: `type Query {
   plugins: [Plugin!]!
   fsEntry(path: String!): FsEntry
 }
@@ -542,7 +408,7 @@ type Plugin {
   endpountSubPath: String
 }
 `, BuiltIn: false},
-	{Name: "../../../../graphql/schema.graphql", Input: `# directive @oneOf on INPUT_OBJECT | FIELD_DEFINITION
+	{Name: "../../../graphql/schema.graphql", Input: `# directive @oneOf on INPUT_OBJECT | FIELD_DEFINITION
 directive @resolver on INPUT_FIELD_DEFINITION | FIELD_DEFINITION
 
 directive @stream on FIELD_DEFINITION
@@ -556,40 +422,11 @@ type Schema {
   mutation: Mutation
 }
 `, BuiltIn: false},
-	{Name: "../../../../graphql/subscription.graphql", Input: `type Subscription {
+	{Name: "../../../graphql/subscription.graphql", Input: `type Subscription {
   taskProgress(taskID: ID!): Progress
 }
 `, BuiltIn: false},
-	{Name: "../../../../graphql/sources/qbittorrent_mutation.graphql", Input: `type QBitTorrentDaemonMutation {
-  cleanup(run: Boolean!): QBitCleanupResponse! @resolver
-  cleanupUnregistred(run: Boolean!): QBitCleanupUnregistredResponse! @resolver
-}
-
-type QBitCleanupResponse {
-  count: Int!
-  hashes: [String!]!
-}
-
-type QBitCleanupUnregistredResponse {
-  count: Int!
-  hashes: [String!]!
-}
-`, BuiltIn: false},
-	{Name: "../../../../graphql/sources/qbittorrent_query.graphql", Input: `type QBitTorrentDaemonQuery {
-  torrents(filter: QBitTorrentDaemonFilter): [QTorrent!]! @resolver
-}
-
-input QBitTorrentDaemonFilter {
-  sourcesCount: IntFilter
-}
-`, BuiltIn: false},
-	{Name: "../../../../graphql/sources/qbittorrent_types.graphql", Input: `type QTorrent {
-  name: String!
-  hash: String!
-  sourceFiles: [String!]! @resolver
-}
-`, BuiltIn: false},
-	{Name: "../../../../graphql/types/filters.graphql", Input: `input Pagination {
+	{Name: "../../../graphql/types/filters.graphql", Input: `input Pagination {
   offset: Int!
   limit: Int!
 }
@@ -621,7 +458,7 @@ input BooleanFilter @oneOf {
   eq: Boolean
 }
 `, BuiltIn: false},
-	{Name: "../../../../graphql/types/fs.graphql", Input: `interface FsEntry {
+	{Name: "../../../graphql/types/fs.graphql", Input: `interface FsEntry {
   name: String!
 }
 
@@ -657,7 +494,7 @@ type ResolverFS implements Dir & FsEntry {
 #   size: Int!
 # }
 `, BuiltIn: false},
-	{Name: "../../../../graphql/types/progress.graphql", Input: `interface Progress {
+	{Name: "../../../graphql/types/progress.graphql", Input: `interface Progress {
   current: Int!
   total: Int!
 }
@@ -720,90 +557,6 @@ func (ec *executionContext) field_Mutation_uploadFile_argsFile(
 	return zeroVal, nil
 }
 
-func (ec *executionContext) field_QBitTorrentDaemonMutation_cleanupUnregistred_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
-	var err error
-	args := map[string]any{}
-	arg0, err := ec.field_QBitTorrentDaemonMutation_cleanupUnregistred_argsRun(ctx, rawArgs)
-	if err != nil {
-		return nil, err
-	}
-	args["run"] = arg0
-	return args, nil
-}
-func (ec *executionContext) field_QBitTorrentDaemonMutation_cleanupUnregistred_argsRun(
-	ctx context.Context,
-	rawArgs map[string]any,
-) (bool, error) {
-	if _, ok := rawArgs["run"]; !ok {
-		var zeroVal bool
-		return zeroVal, nil
-	}
-
-	ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("run"))
-	if tmp, ok := rawArgs["run"]; ok {
-		return ec.unmarshalNBoolean2bool(ctx, tmp)
-	}
-
-	var zeroVal bool
-	return zeroVal, nil
-}
-
-func (ec *executionContext) field_QBitTorrentDaemonMutation_cleanup_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
-	var err error
-	args := map[string]any{}
-	arg0, err := ec.field_QBitTorrentDaemonMutation_cleanup_argsRun(ctx, rawArgs)
-	if err != nil {
-		return nil, err
-	}
-	args["run"] = arg0
-	return args, nil
-}
-func (ec *executionContext) field_QBitTorrentDaemonMutation_cleanup_argsRun(
-	ctx context.Context,
-	rawArgs map[string]any,
-) (bool, error) {
-	if _, ok := rawArgs["run"]; !ok {
-		var zeroVal bool
-		return zeroVal, nil
-	}
-
-	ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("run"))
-	if tmp, ok := rawArgs["run"]; ok {
-		return ec.unmarshalNBoolean2bool(ctx, tmp)
-	}
-
-	var zeroVal bool
-	return zeroVal, nil
-}
-
-func (ec *executionContext) field_QBitTorrentDaemonQuery_torrents_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
-	var err error
-	args := map[string]any{}
-	arg0, err := ec.field_QBitTorrentDaemonQuery_torrents_argsFilter(ctx, rawArgs)
-	if err != nil {
-		return nil, err
-	}
-	args["filter"] = arg0
-	return args, nil
-}
-func (ec *executionContext) field_QBitTorrentDaemonQuery_torrents_argsFilter(
-	ctx context.Context,
-	rawArgs map[string]any,
-) (*model.QBitTorrentDaemonFilter, error) {
-	if _, ok := rawArgs["filter"]; !ok {
-		var zeroVal *model.QBitTorrentDaemonFilter
-		return zeroVal, nil
-	}
-
-	ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("filter"))
-	if tmp, ok := rawArgs["filter"]; ok {
-		return ec.unmarshalOQBitTorrentDaemonFilter2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitTorrentDaemonFilter(ctx, tmp)
-	}
-
-	var zeroVal *model.QBitTorrentDaemonFilter
-	return zeroVal, nil
-}
-
 func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
 	var err error
 	args := map[string]any{}
@@ -1008,75 +761,6 @@ func (ec *executionContext) field___Type_fields_argsIncludeDeprecated(
 
 // region    **************************** field.gotpl *****************************
 
-func (ec *executionContext) _Mutation_qbitTorrentDaemon(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_Mutation_qbitTorrentDaemon(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) (any, error) {
-		directive0 := func(rctx context.Context) (any, error) {
-			ctx = rctx // use context from middleware stack in children
-			return ec.resolvers.Mutation().QbitTorrentDaemon(rctx)
-		}
-
-		directive1 := func(ctx context.Context) (any, error) {
-			if ec.directives.Resolver == nil {
-				var zeroVal *model.QBitTorrentDaemonMutation
-				return zeroVal, errors.New("directive resolver is not implemented")
-			}
-			return ec.directives.Resolver(ctx, nil, directive0)
-		}
-
-		tmp, err := directive1(rctx)
-		if err != nil {
-			return nil, graphql.ErrorOnPath(ctx, err)
-		}
-		if tmp == nil {
-			return nil, nil
-		}
-		if data, ok := tmp.(*model.QBitTorrentDaemonMutation); ok {
-			return data, nil
-		}
-		return nil, fmt.Errorf(`unexpected type %T from directive, should be *git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model.QBitTorrentDaemonMutation`, tmp)
-	})
-	if err != nil {
-		ec.Error(ctx, err)
-		return graphql.Null
-	}
-	if resTmp == nil {
-		return graphql.Null
-	}
-	res := resTmp.(*model.QBitTorrentDaemonMutation)
-	fc.Result = res
-	return ec.marshalOQBitTorrentDaemonMutation2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitTorrentDaemonMutation(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) fieldContext_Mutation_qbitTorrentDaemon(_ 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) {
-			switch field.Name {
-			case "cleanup":
-				return ec.fieldContext_QBitTorrentDaemonMutation_cleanup(ctx, field)
-			case "cleanupUnregistred":
-				return ec.fieldContext_QBitTorrentDaemonMutation_cleanupUnregistred(ctx, field)
-			}
-			return nil, fmt.Errorf("no field named %q was found under type QBitTorrentDaemonMutation", field.Name)
-		},
-	}
-	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 {
@@ -1261,587 +945,6 @@ func (ec *executionContext) fieldContext_Plugin_endpountSubPath(_ context.Contex
 	return fc, nil
 }
 
-func (ec *executionContext) _QBitCleanupResponse_count(ctx context.Context, field graphql.CollectedField, obj *model.QBitCleanupResponse) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitCleanupResponse_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) (any, 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_QBitCleanupResponse_count(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitCleanupResponse",
-		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) _QBitCleanupResponse_hashes(ctx context.Context, field graphql.CollectedField, obj *model.QBitCleanupResponse) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitCleanupResponse_hashes(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) (any, error) {
-		ctx = rctx // use context from middleware stack in children
-		return obj.Hashes, 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_QBitCleanupResponse_hashes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitCleanupResponse",
-		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) _QBitCleanupUnregistredResponse_count(ctx context.Context, field graphql.CollectedField, obj *model.QBitCleanupUnregistredResponse) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitCleanupUnregistredResponse_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) (any, 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_QBitCleanupUnregistredResponse_count(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitCleanupUnregistredResponse",
-		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) _QBitCleanupUnregistredResponse_hashes(ctx context.Context, field graphql.CollectedField, obj *model.QBitCleanupUnregistredResponse) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitCleanupUnregistredResponse_hashes(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) (any, error) {
-		ctx = rctx // use context from middleware stack in children
-		return obj.Hashes, 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_QBitCleanupUnregistredResponse_hashes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitCleanupUnregistredResponse",
-		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) _QBitTorrentDaemonMutation_cleanup(ctx context.Context, field graphql.CollectedField, obj *model.QBitTorrentDaemonMutation) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitTorrentDaemonMutation_cleanup(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) (any, error) {
-		directive0 := func(rctx context.Context) (any, error) {
-			ctx = rctx // use context from middleware stack in children
-			return ec.resolvers.QBitTorrentDaemonMutation().Cleanup(rctx, obj, fc.Args["run"].(bool))
-		}
-
-		directive1 := func(ctx context.Context) (any, error) {
-			if ec.directives.Resolver == nil {
-				var zeroVal *model.QBitCleanupResponse
-				return zeroVal, errors.New("directive resolver is not implemented")
-			}
-			return ec.directives.Resolver(ctx, obj, directive0)
-		}
-
-		tmp, err := directive1(rctx)
-		if err != nil {
-			return nil, graphql.ErrorOnPath(ctx, err)
-		}
-		if tmp == nil {
-			return nil, nil
-		}
-		if data, ok := tmp.(*model.QBitCleanupResponse); ok {
-			return data, nil
-		}
-		return nil, fmt.Errorf(`unexpected type %T from directive, should be *git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model.QBitCleanupResponse`, tmp)
-	})
-	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.QBitCleanupResponse)
-	fc.Result = res
-	return ec.marshalNQBitCleanupResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitCleanupResponse(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) fieldContext_QBitTorrentDaemonMutation_cleanup(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitTorrentDaemonMutation",
-		Field:      field,
-		IsMethod:   true,
-		IsResolver: true,
-		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
-			switch field.Name {
-			case "count":
-				return ec.fieldContext_QBitCleanupResponse_count(ctx, field)
-			case "hashes":
-				return ec.fieldContext_QBitCleanupResponse_hashes(ctx, field)
-			}
-			return nil, fmt.Errorf("no field named %q was found under type QBitCleanupResponse", field.Name)
-		},
-	}
-	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_QBitTorrentDaemonMutation_cleanup_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
-		ec.Error(ctx, err)
-		return fc, err
-	}
-	return fc, nil
-}
-
-func (ec *executionContext) _QBitTorrentDaemonMutation_cleanupUnregistred(ctx context.Context, field graphql.CollectedField, obj *model.QBitTorrentDaemonMutation) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitTorrentDaemonMutation_cleanupUnregistred(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) (any, error) {
-		directive0 := func(rctx context.Context) (any, error) {
-			ctx = rctx // use context from middleware stack in children
-			return ec.resolvers.QBitTorrentDaemonMutation().CleanupUnregistred(rctx, obj, fc.Args["run"].(bool))
-		}
-
-		directive1 := func(ctx context.Context) (any, error) {
-			if ec.directives.Resolver == nil {
-				var zeroVal *model.QBitCleanupUnregistredResponse
-				return zeroVal, errors.New("directive resolver is not implemented")
-			}
-			return ec.directives.Resolver(ctx, obj, directive0)
-		}
-
-		tmp, err := directive1(rctx)
-		if err != nil {
-			return nil, graphql.ErrorOnPath(ctx, err)
-		}
-		if tmp == nil {
-			return nil, nil
-		}
-		if data, ok := tmp.(*model.QBitCleanupUnregistredResponse); ok {
-			return data, nil
-		}
-		return nil, fmt.Errorf(`unexpected type %T from directive, should be *git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model.QBitCleanupUnregistredResponse`, tmp)
-	})
-	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.QBitCleanupUnregistredResponse)
-	fc.Result = res
-	return ec.marshalNQBitCleanupUnregistredResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitCleanupUnregistredResponse(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) fieldContext_QBitTorrentDaemonMutation_cleanupUnregistred(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitTorrentDaemonMutation",
-		Field:      field,
-		IsMethod:   true,
-		IsResolver: true,
-		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
-			switch field.Name {
-			case "count":
-				return ec.fieldContext_QBitCleanupUnregistredResponse_count(ctx, field)
-			case "hashes":
-				return ec.fieldContext_QBitCleanupUnregistredResponse_hashes(ctx, field)
-			}
-			return nil, fmt.Errorf("no field named %q was found under type QBitCleanupUnregistredResponse", field.Name)
-		},
-	}
-	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_QBitTorrentDaemonMutation_cleanupUnregistred_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
-		ec.Error(ctx, err)
-		return fc, err
-	}
-	return fc, nil
-}
-
-func (ec *executionContext) _QBitTorrentDaemonQuery_torrents(ctx context.Context, field graphql.CollectedField, obj *model.QBitTorrentDaemonQuery) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QBitTorrentDaemonQuery_torrents(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) (any, error) {
-		directive0 := func(rctx context.Context) (any, error) {
-			ctx = rctx // use context from middleware stack in children
-			return ec.resolvers.QBitTorrentDaemonQuery().Torrents(rctx, obj, fc.Args["filter"].(*model.QBitTorrentDaemonFilter))
-		}
-
-		directive1 := func(ctx context.Context) (any, error) {
-			if ec.directives.Resolver == nil {
-				var zeroVal []*model.QTorrent
-				return zeroVal, errors.New("directive resolver is not implemented")
-			}
-			return ec.directives.Resolver(ctx, obj, directive0)
-		}
-
-		tmp, err := directive1(rctx)
-		if err != nil {
-			return nil, graphql.ErrorOnPath(ctx, err)
-		}
-		if tmp == nil {
-			return nil, nil
-		}
-		if data, ok := tmp.([]*model.QTorrent); ok {
-			return data, nil
-		}
-		return nil, fmt.Errorf(`unexpected type %T from directive, should be []*git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model.QTorrent`, tmp)
-	})
-	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.QTorrent)
-	fc.Result = res
-	return ec.marshalNQTorrent2ᚕᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQTorrentᚄ(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) fieldContext_QBitTorrentDaemonQuery_torrents(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QBitTorrentDaemonQuery",
-		Field:      field,
-		IsMethod:   true,
-		IsResolver: true,
-		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
-			switch field.Name {
-			case "name":
-				return ec.fieldContext_QTorrent_name(ctx, field)
-			case "hash":
-				return ec.fieldContext_QTorrent_hash(ctx, field)
-			case "sourceFiles":
-				return ec.fieldContext_QTorrent_sourceFiles(ctx, field)
-			}
-			return nil, fmt.Errorf("no field named %q was found under type QTorrent", field.Name)
-		},
-	}
-	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_QBitTorrentDaemonQuery_torrents_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
-		ec.Error(ctx, err)
-		return fc, err
-	}
-	return fc, nil
-}
-
-func (ec *executionContext) _QTorrent_name(ctx context.Context, field graphql.CollectedField, obj *model.QTorrent) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QTorrent_name(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) (any, error) {
-		ctx = rctx // use context from middleware stack in children
-		return obj.Name, 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.marshalNString2string(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) fieldContext_QTorrent_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QTorrent",
-		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) _QTorrent_hash(ctx context.Context, field graphql.CollectedField, obj *model.QTorrent) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QTorrent_hash(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) (any, error) {
-		ctx = rctx // use context from middleware stack in children
-		return obj.Hash, 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.marshalNString2string(ctx, field.Selections, res)
-}
-
-func (ec *executionContext) fieldContext_QTorrent_hash(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QTorrent",
-		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) _QTorrent_sourceFiles(ctx context.Context, field graphql.CollectedField, obj *model.QTorrent) (ret graphql.Marshaler) {
-	fc, err := ec.fieldContext_QTorrent_sourceFiles(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) (any, error) {
-		directive0 := func(rctx context.Context) (any, error) {
-			ctx = rctx // use context from middleware stack in children
-			return ec.resolvers.QTorrent().SourceFiles(rctx, obj)
-		}
-
-		directive1 := func(ctx context.Context) (any, error) {
-			if ec.directives.Resolver == nil {
-				var zeroVal []string
-				return zeroVal, errors.New("directive resolver is not implemented")
-			}
-			return ec.directives.Resolver(ctx, obj, directive0)
-		}
-
-		tmp, err := directive1(rctx)
-		if err != nil {
-			return nil, graphql.ErrorOnPath(ctx, err)
-		}
-		if tmp == nil {
-			return nil, nil
-		}
-		if data, ok := tmp.([]string); ok {
-			return data, nil
-		}
-		return nil, fmt.Errorf(`unexpected type %T from directive, should be []string`, tmp)
-	})
-	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_QTorrent_sourceFiles(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
-	fc = &graphql.FieldContext{
-		Object:     "QTorrent",
-		Field:      field,
-		IsMethod:   true,
-		IsResolver: true,
-		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) _Query_plugins(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
 	fc, err := ec.fieldContext_Query_plugins(ctx, field)
 	if err != nil {
@@ -2250,8 +1353,6 @@ func (ec *executionContext) fieldContext_Schema_mutation(_ context.Context, fiel
 		IsResolver: false,
 		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
 			switch field.Name {
-			case "qbitTorrentDaemon":
-				return ec.fieldContext_Mutation_qbitTorrentDaemon(ctx, field)
 			case "uploadFile":
 				return ec.fieldContext_Mutation_uploadFile(ctx, field)
 			case "dedupeStorage":
@@ -4522,8 +3623,8 @@ func (ec *executionContext) fieldContext___Type_isOneOf(_ context.Context, field
 
 // region    **************************** input.gotpl *****************************
 
-func (ec *executionContext) unmarshalInputBooleanFilter(ctx context.Context, obj any) (model.BooleanFilter, error) {
-	var it model.BooleanFilter
+func (ec *executionContext) unmarshalInputBooleanFilter(ctx context.Context, obj any) (filter.BooleanFilter, error) {
+	var it filter.BooleanFilter
 	asMap := map[string]any{}
 	for k, v := range obj.(map[string]any) {
 		asMap[k] = v
@@ -4549,8 +3650,8 @@ func (ec *executionContext) unmarshalInputBooleanFilter(ctx context.Context, obj
 	return it, nil
 }
 
-func (ec *executionContext) unmarshalInputDateTimeFilter(ctx context.Context, obj any) (model.DateTimeFilter, error) {
-	var it model.DateTimeFilter
+func (ec *executionContext) unmarshalInputDateTimeFilter(ctx context.Context, obj any) (filter.DateTimeFilter, error) {
+	var it filter.DateTimeFilter
 	asMap := map[string]any{}
 	for k, v := range obj.(map[string]any) {
 		asMap[k] = v
@@ -4604,8 +3705,8 @@ func (ec *executionContext) unmarshalInputDateTimeFilter(ctx context.Context, ob
 	return it, nil
 }
 
-func (ec *executionContext) unmarshalInputIntFilter(ctx context.Context, obj any) (model.IntFilter, error) {
-	var it model.IntFilter
+func (ec *executionContext) unmarshalInputIntFilter(ctx context.Context, obj any) (filter.IntFilter, error) {
+	var it filter.IntFilter
 	asMap := map[string]any{}
 	for k, v := range obj.(map[string]any) {
 		asMap[k] = v
@@ -4700,35 +3801,8 @@ func (ec *executionContext) unmarshalInputPagination(ctx context.Context, obj an
 	return it, nil
 }
 
-func (ec *executionContext) unmarshalInputQBitTorrentDaemonFilter(ctx context.Context, obj any) (model.QBitTorrentDaemonFilter, error) {
-	var it model.QBitTorrentDaemonFilter
-	asMap := map[string]any{}
-	for k, v := range obj.(map[string]any) {
-		asMap[k] = v
-	}
-
-	fieldsInOrder := [...]string{"sourcesCount"}
-	for _, k := range fieldsInOrder {
-		v, ok := asMap[k]
-		if !ok {
-			continue
-		}
-		switch k {
-		case "sourcesCount":
-			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sourcesCount"))
-			data, err := ec.unmarshalOIntFilter2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐIntFilter(ctx, v)
-			if err != nil {
-				return it, err
-			}
-			it.SourcesCount = data
-		}
-	}
-
-	return it, nil
-}
-
-func (ec *executionContext) unmarshalInputStringFilter(ctx context.Context, obj any) (model.StringFilter, error) {
-	var it model.StringFilter
+func (ec *executionContext) unmarshalInputStringFilter(ctx context.Context, obj any) (filter.StringFilter, error) {
+	var it filter.StringFilter
 	asMap := map[string]any{}
 	for k, v := range obj.(map[string]any) {
 		asMap[k] = v
@@ -4883,10 +3957,6 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
 		switch field.Name {
 		case "__typename":
 			out.Values[i] = graphql.MarshalString("Mutation")
-		case "qbitTorrentDaemon":
-			out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
-				return ec._Mutation_qbitTorrentDaemon(ctx, field)
-			})
 		case "uploadFile":
 			out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
 				return ec._Mutation_uploadFile(ctx, field)
@@ -4965,350 +4035,6 @@ func (ec *executionContext) _Plugin(ctx context.Context, sel ast.SelectionSet, o
 	return out
 }
 
-var qBitCleanupResponseImplementors = []string{"QBitCleanupResponse"}
-
-func (ec *executionContext) _QBitCleanupResponse(ctx context.Context, sel ast.SelectionSet, obj *model.QBitCleanupResponse) graphql.Marshaler {
-	fields := graphql.CollectFields(ec.OperationContext, sel, qBitCleanupResponseImplementors)
-
-	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("QBitCleanupResponse")
-		case "count":
-			out.Values[i] = ec._QBitCleanupResponse_count(ctx, field, obj)
-			if out.Values[i] == graphql.Null {
-				out.Invalids++
-			}
-		case "hashes":
-			out.Values[i] = ec._QBitCleanupResponse_hashes(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 qBitCleanupUnregistredResponseImplementors = []string{"QBitCleanupUnregistredResponse"}
-
-func (ec *executionContext) _QBitCleanupUnregistredResponse(ctx context.Context, sel ast.SelectionSet, obj *model.QBitCleanupUnregistredResponse) graphql.Marshaler {
-	fields := graphql.CollectFields(ec.OperationContext, sel, qBitCleanupUnregistredResponseImplementors)
-
-	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("QBitCleanupUnregistredResponse")
-		case "count":
-			out.Values[i] = ec._QBitCleanupUnregistredResponse_count(ctx, field, obj)
-			if out.Values[i] == graphql.Null {
-				out.Invalids++
-			}
-		case "hashes":
-			out.Values[i] = ec._QBitCleanupUnregistredResponse_hashes(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 qBitTorrentDaemonMutationImplementors = []string{"QBitTorrentDaemonMutation"}
-
-func (ec *executionContext) _QBitTorrentDaemonMutation(ctx context.Context, sel ast.SelectionSet, obj *model.QBitTorrentDaemonMutation) graphql.Marshaler {
-	fields := graphql.CollectFields(ec.OperationContext, sel, qBitTorrentDaemonMutationImplementors)
-
-	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("QBitTorrentDaemonMutation")
-		case "cleanup":
-			field := field
-
-			innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
-				defer func() {
-					if r := recover(); r != nil {
-						ec.Error(ctx, ec.Recover(ctx, r))
-					}
-				}()
-				res = ec._QBitTorrentDaemonMutation_cleanup(ctx, field, obj)
-				if res == graphql.Null {
-					atomic.AddUint32(&fs.Invalids, 1)
-				}
-				return res
-			}
-
-			if field.Deferrable != nil {
-				dfs, ok := deferred[field.Deferrable.Label]
-				di := 0
-				if ok {
-					dfs.AddField(field)
-					di = len(dfs.Values) - 1
-				} else {
-					dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
-					deferred[field.Deferrable.Label] = dfs
-				}
-				dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
-					return innerFunc(ctx, dfs)
-				})
-
-				// don't run the out.Concurrently() call below
-				out.Values[i] = graphql.Null
-				continue
-			}
-
-			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
-		case "cleanupUnregistred":
-			field := field
-
-			innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
-				defer func() {
-					if r := recover(); r != nil {
-						ec.Error(ctx, ec.Recover(ctx, r))
-					}
-				}()
-				res = ec._QBitTorrentDaemonMutation_cleanupUnregistred(ctx, field, obj)
-				if res == graphql.Null {
-					atomic.AddUint32(&fs.Invalids, 1)
-				}
-				return res
-			}
-
-			if field.Deferrable != nil {
-				dfs, ok := deferred[field.Deferrable.Label]
-				di := 0
-				if ok {
-					dfs.AddField(field)
-					di = len(dfs.Values) - 1
-				} else {
-					dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
-					deferred[field.Deferrable.Label] = dfs
-				}
-				dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
-					return innerFunc(ctx, dfs)
-				})
-
-				// don't run the out.Concurrently() call below
-				out.Values[i] = graphql.Null
-				continue
-			}
-
-			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
-		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 qBitTorrentDaemonQueryImplementors = []string{"QBitTorrentDaemonQuery"}
-
-func (ec *executionContext) _QBitTorrentDaemonQuery(ctx context.Context, sel ast.SelectionSet, obj *model.QBitTorrentDaemonQuery) graphql.Marshaler {
-	fields := graphql.CollectFields(ec.OperationContext, sel, qBitTorrentDaemonQueryImplementors)
-
-	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("QBitTorrentDaemonQuery")
-		case "torrents":
-			field := field
-
-			innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
-				defer func() {
-					if r := recover(); r != nil {
-						ec.Error(ctx, ec.Recover(ctx, r))
-					}
-				}()
-				res = ec._QBitTorrentDaemonQuery_torrents(ctx, field, obj)
-				if res == graphql.Null {
-					atomic.AddUint32(&fs.Invalids, 1)
-				}
-				return res
-			}
-
-			if field.Deferrable != nil {
-				dfs, ok := deferred[field.Deferrable.Label]
-				di := 0
-				if ok {
-					dfs.AddField(field)
-					di = len(dfs.Values) - 1
-				} else {
-					dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
-					deferred[field.Deferrable.Label] = dfs
-				}
-				dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
-					return innerFunc(ctx, dfs)
-				})
-
-				// don't run the out.Concurrently() call below
-				out.Values[i] = graphql.Null
-				continue
-			}
-
-			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
-		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 qTorrentImplementors = []string{"QTorrent"}
-
-func (ec *executionContext) _QTorrent(ctx context.Context, sel ast.SelectionSet, obj *model.QTorrent) graphql.Marshaler {
-	fields := graphql.CollectFields(ec.OperationContext, sel, qTorrentImplementors)
-
-	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("QTorrent")
-		case "name":
-			out.Values[i] = ec._QTorrent_name(ctx, field, obj)
-			if out.Values[i] == graphql.Null {
-				atomic.AddUint32(&out.Invalids, 1)
-			}
-		case "hash":
-			out.Values[i] = ec._QTorrent_hash(ctx, field, obj)
-			if out.Values[i] == graphql.Null {
-				atomic.AddUint32(&out.Invalids, 1)
-			}
-		case "sourceFiles":
-			field := field
-
-			innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
-				defer func() {
-					if r := recover(); r != nil {
-						ec.Error(ctx, ec.Recover(ctx, r))
-					}
-				}()
-				res = ec._QTorrent_sourceFiles(ctx, field, obj)
-				if res == graphql.Null {
-					atomic.AddUint32(&fs.Invalids, 1)
-				}
-				return res
-			}
-
-			if field.Deferrable != nil {
-				dfs, ok := deferred[field.Deferrable.Label]
-				di := 0
-				if ok {
-					dfs.AddField(field)
-					di = len(dfs.Values) - 1
-				} else {
-					dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
-					deferred[field.Deferrable.Label] = dfs
-				}
-				dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
-					return innerFunc(ctx, dfs)
-				})
-
-				// don't run the out.Concurrently() call below
-				out.Values[i] = graphql.Null
-				continue
-			}
-
-			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
-		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 queryImplementors = []string{"Query"}
 
 func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler {
@@ -6179,80 +4905,6 @@ func (ec *executionContext) marshalNPlugin2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtst
 	return ec._Plugin(ctx, sel, v)
 }
 
-func (ec *executionContext) marshalNQBitCleanupResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitCleanupResponse(ctx context.Context, sel ast.SelectionSet, v *model.QBitCleanupResponse) 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._QBitCleanupResponse(ctx, sel, v)
-}
-
-func (ec *executionContext) marshalNQBitCleanupUnregistredResponse2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitCleanupUnregistredResponse(ctx context.Context, sel ast.SelectionSet, v *model.QBitCleanupUnregistredResponse) 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._QBitCleanupUnregistredResponse(ctx, sel, v)
-}
-
-func (ec *executionContext) marshalNQTorrent2ᚕᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQTorrentᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.QTorrent) graphql.Marshaler {
-	ret := make(graphql.Array, len(v))
-	var wg sync.WaitGroup
-	isLen1 := len(v) == 1
-	if !isLen1 {
-		wg.Add(len(v))
-	}
-	for i := range v {
-		i := i
-		fc := &graphql.FieldContext{
-			Index:  &i,
-			Result: &v[i],
-		}
-		ctx := graphql.WithFieldContext(ctx, fc)
-		f := func(i int) {
-			defer func() {
-				if r := recover(); r != nil {
-					ec.Error(ctx, ec.Recover(ctx, r))
-					ret = nil
-				}
-			}()
-			if !isLen1 {
-				defer wg.Done()
-			}
-			ret[i] = ec.marshalNQTorrent2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQTorrent(ctx, sel, v[i])
-		}
-		if isLen1 {
-			f(i)
-		} else {
-			go f(i)
-		}
-
-	}
-	wg.Wait()
-
-	for _, e := range ret {
-		if e == graphql.Null {
-			return graphql.Null
-		}
-	}
-
-	return ret
-}
-
-func (ec *executionContext) marshalNQTorrent2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQTorrent(ctx context.Context, sel ast.SelectionSet, v *model.QTorrent) 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._QTorrent(ctx, sel, v)
-}
-
 func (ec *executionContext) unmarshalNString2string(ctx context.Context, v any) (string, error) {
 	res, err := graphql.UnmarshalString(v)
 	return res, graphql.ErrorOnPath(ctx, err)
@@ -6268,36 +4920,6 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
 	return res
 }
 
-func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v any) ([]string, error) {
-	var vSlice []any
-	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) unmarshalNUpload2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚐUpload(ctx context.Context, v any) (graphql.Upload, error) {
 	res, err := graphql.UnmarshalUpload(v)
 	return res, graphql.ErrorOnPath(ctx, err)
@@ -6665,14 +5287,6 @@ func (ec *executionContext) marshalOInt2ᚖint64(ctx context.Context, sel ast.Se
 	return res
 }
 
-func (ec *executionContext) unmarshalOIntFilter2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐIntFilter(ctx context.Context, v any) (*model.IntFilter, error) {
-	if v == nil {
-		return nil, nil
-	}
-	res, err := ec.unmarshalInputIntFilter(ctx, v)
-	return &res, graphql.ErrorOnPath(ctx, err)
-}
-
 func (ec *executionContext) marshalOMutation2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐMutation(ctx context.Context, sel ast.SelectionSet, v *model.Mutation) graphql.Marshaler {
 	if v == nil {
 		return graphql.Null
@@ -6687,21 +5301,6 @@ func (ec *executionContext) marshalOProgress2gitᚗkmsignᚗruᚋroyalcatᚋtsto
 	return ec._Progress(ctx, sel, v)
 }
 
-func (ec *executionContext) unmarshalOQBitTorrentDaemonFilter2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitTorrentDaemonFilter(ctx context.Context, v any) (*model.QBitTorrentDaemonFilter, error) {
-	if v == nil {
-		return nil, nil
-	}
-	res, err := ec.unmarshalInputQBitTorrentDaemonFilter(ctx, v)
-	return &res, graphql.ErrorOnPath(ctx, err)
-}
-
-func (ec *executionContext) marshalOQBitTorrentDaemonMutation2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQBitTorrentDaemonMutation(ctx context.Context, sel ast.SelectionSet, v *model.QBitTorrentDaemonMutation) graphql.Marshaler {
-	if v == nil {
-		return graphql.Null
-	}
-	return ec._QBitTorrentDaemonMutation(ctx, sel, v)
-}
-
 func (ec *executionContext) marshalOQuery2ᚖgitᚗkmsignᚗruᚋroyalcatᚋtstorᚋserverᚋsrcᚋdeliveryᚋgraphqlᚋmodelᚐQuery(ctx context.Context, sel ast.SelectionSet, v *model.Query) graphql.Marshaler {
 	if v == nil {
 		return graphql.Null
diff --git a/server/src/delivery/graphql/model/entry.go b/server/src/delivery/graphql/model/entry.go
index 0eca47a..0c38b85 100644
--- a/server/src/delivery/graphql/model/entry.go
+++ b/server/src/delivery/graphql/model/entry.go
@@ -52,3 +52,51 @@ func FillFsEntry(ctx context.Context, e FsElem, fs vfs.Filesystem, path string)
 		}
 	}
 }
+
+func ReadEntries(ctx context.Context, fs vfs.Filesystem, path string) ([]FsEntry, error) {
+	entries, err := fs.ReadDir(ctx, path)
+	if err != nil {
+		return nil, err
+	}
+	out := []FsEntry{}
+	for _, e := range entries {
+		entry, err := FillFsEntry(ctx, e, fs, ".")
+		if err != nil {
+			return nil, err
+		}
+		out = append(out, entry)
+	}
+	return out, nil
+}
+
+func (obj *ResolverFs) ResolverEntries(ctx context.Context) ([]FsEntry, error) {
+	entries, err := obj.FS.ReadDir(ctx, ".")
+	if err != nil {
+		return nil, err
+	}
+	out := []FsEntry{}
+	for _, e := range entries {
+		entry, err := FillFsEntry(ctx, e, obj.FS, ".")
+		if err != nil {
+			return nil, err
+		}
+		out = append(out, entry)
+	}
+	return out, nil
+}
+
+func (obj *SimpleDir) SimpleDirEntries(ctx context.Context) ([]FsEntry, error) {
+	entries, err := obj.FS.ReadDir(ctx, obj.Path)
+	if err != nil {
+		return nil, err
+	}
+	out := []FsEntry{}
+	for _, e := range entries {
+		entry, err := FillFsEntry(ctx, e, obj.FS, obj.Path)
+		if err != nil {
+			return nil, err
+		}
+		out = append(out, entry)
+	}
+	return out, nil
+}
diff --git a/server/src/delivery/graphql/model/models_gen.go b/server/src/delivery/graphql/model/models_gen.go
index 095f1b8..293b1f8 100644
--- a/server/src/delivery/graphql/model/models_gen.go
+++ b/server/src/delivery/graphql/model/models_gen.go
@@ -3,8 +3,6 @@
 package model
 
 import (
-	"time"
-
 	"git.kmsign.ru/royalcat/tstor/server/src/vfs"
 )
 
@@ -33,27 +31,6 @@ type Progress interface {
 	GetTotal() int64
 }
 
-type BooleanFilter struct {
-	Eq *bool `json:"eq,omitempty"`
-}
-
-type DateTimeFilter struct {
-	Eq  *time.Time `json:"eq,omitempty"`
-	Gt  *time.Time `json:"gt,omitempty"`
-	Lt  *time.Time `json:"lt,omitempty"`
-	Gte *time.Time `json:"gte,omitempty"`
-	Lte *time.Time `json:"lte,omitempty"`
-}
-
-type IntFilter struct {
-	Eq  *int64  `json:"eq,omitempty"`
-	Gt  *int64  `json:"gt,omitempty"`
-	Lt  *int64  `json:"lt,omitempty"`
-	Gte *int64  `json:"gte,omitempty"`
-	Lte *int64  `json:"lte,omitempty"`
-	In  []int64 `json:"in,omitempty"`
-}
-
 type Mutation struct {
 }
 
@@ -67,35 +44,6 @@ type Plugin struct {
 	EndpountSubPath *string `json:"endpountSubPath,omitempty"`
 }
 
-type QBitCleanupResponse struct {
-	Count  int64    `json:"count"`
-	Hashes []string `json:"hashes"`
-}
-
-type QBitCleanupUnregistredResponse struct {
-	Count  int64    `json:"count"`
-	Hashes []string `json:"hashes"`
-}
-
-type QBitTorrentDaemonFilter struct {
-	SourcesCount *IntFilter `json:"sourcesCount,omitempty"`
-}
-
-type QBitTorrentDaemonMutation struct {
-	Cleanup            *QBitCleanupResponse            `json:"cleanup"`
-	CleanupUnregistred *QBitCleanupUnregistredResponse `json:"cleanupUnregistred"`
-}
-
-type QBitTorrentDaemonQuery struct {
-	Torrents []*QTorrent `json:"torrents"`
-}
-
-type QTorrent struct {
-	Name        string   `json:"name"`
-	Hash        string   `json:"hash"`
-	SourceFiles []string `json:"sourceFiles"`
-}
-
 type Query struct {
 }
 
@@ -158,12 +106,6 @@ func (this SimpleFile) GetSize() int64  { return this.Size }
 
 func (SimpleFile) IsFsEntry() {}
 
-type StringFilter struct {
-	Eq     *string  `json:"eq,omitempty"`
-	Substr *string  `json:"substr,omitempty"`
-	In     []string `json:"in,omitempty"`
-}
-
 type Subscription struct {
 }
 
diff --git a/server/src/delivery/graphql/resolver/fs.resolvers.go b/server/src/delivery/graphql/resolver/fs.resolvers.go
index e4cb3ea..8060b33 100644
--- a/server/src/delivery/graphql/resolver/fs.resolvers.go
+++ b/server/src/delivery/graphql/resolver/fs.resolvers.go
@@ -2,7 +2,7 @@ package resolver
 
 // This file will be automatically regenerated based on the schema, any resolver implementations
 // will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
+// Code generated by github.com/99designs/gqlgen version v0.17.70
 
 import (
 	"context"
@@ -13,36 +13,12 @@ import (
 
 // Entries is the resolver for the entries field.
 func (r *resolverFSResolver) Entries(ctx context.Context, obj *model.ResolverFs) ([]model.FsEntry, error) {
-	entries, err := obj.FS.ReadDir(ctx, ".")
-	if err != nil {
-		return nil, err
-	}
-	out := []model.FsEntry{}
-	for _, e := range entries {
-		entry, err := model.FillFsEntry(ctx, e, obj.FS, ".")
-		if err != nil {
-			return nil, err
-		}
-		out = append(out, entry)
-	}
-	return out, nil
+	return obj.ResolverEntries(ctx)
 }
 
 // Entries is the resolver for the entries field.
 func (r *simpleDirResolver) Entries(ctx context.Context, obj *model.SimpleDir) ([]model.FsEntry, error) {
-	entries, err := obj.FS.ReadDir(ctx, obj.Path)
-	if err != nil {
-		return nil, err
-	}
-	out := []model.FsEntry{}
-	for _, e := range entries {
-		entry, err := model.FillFsEntry(ctx, e, obj.FS, obj.Path)
-		if err != nil {
-			return nil, err
-		}
-		out = append(out, entry)
-	}
-	return out, nil
+	return obj.SimpleDirEntries(ctx)
 }
 
 // ResolverFS returns graph.ResolverFSResolver implementation.
diff --git a/server/src/delivery/graphql/resolver/mutation.resolvers.go b/server/src/delivery/graphql/resolver/mutation.resolvers.go
index f9985f9..a9ff9e1 100644
--- a/server/src/delivery/graphql/resolver/mutation.resolvers.go
+++ b/server/src/delivery/graphql/resolver/mutation.resolvers.go
@@ -2,7 +2,7 @@ package resolver
 
 // This file will be automatically regenerated based on the schema, any resolver implementations
 // will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
+// Code generated by github.com/99designs/gqlgen version v0.17.70
 
 import (
 	"context"
@@ -12,15 +12,9 @@ import (
 	pathlib "path"
 
 	graph "git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql"
-	"git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model"
 	"github.com/99designs/gqlgen/graphql"
 )
 
-// QbitTorrentDaemon is the resolver for the qbitTorrentDaemon field.
-func (r *mutationResolver) QbitTorrentDaemon(ctx context.Context) (*model.QBitTorrentDaemonMutation, error) {
-	return &model.QBitTorrentDaemonMutation{}, nil
-}
-
 // UploadFile is the resolver for the uploadFile field.
 func (r *mutationResolver) UploadFile(ctx context.Context, dir string, file graphql.Upload) (bool, error) {
 	dirInfo, err := r.SourceFS.Stat(dir)
diff --git a/server/src/delivery/graphql/resolver/qbittorrent_mutation.resolvers.go b/server/src/delivery/graphql/resolver/qbittorrent_mutation.resolvers.go
deleted file mode 100644
index 5821504..0000000
--- a/server/src/delivery/graphql/resolver/qbittorrent_mutation.resolvers.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package resolver
-
-// This file will be automatically regenerated based on the schema, any resolver implementations
-// will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
-
-import (
-	"context"
-
-	graph "git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql"
-	"git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model"
-)
-
-// Cleanup is the resolver for the cleanup field.
-func (r *qBitTorrentDaemonMutationResolver) Cleanup(ctx context.Context, obj *model.QBitTorrentDaemonMutation, run bool) (*model.QBitCleanupResponse, error) {
-	// hahses, err := r.QBitTorrentDaemon.Cleanup(ctx, run)
-	// if err != nil {
-	// 	return nil, err
-	// }
-	// return &model.QBitCleanupResponse{
-	// 	Count:  int64(len(hahses)),
-	// 	Hashes: hahses,
-	// }, nil
-	panic("not implemented")
-}
-
-// CleanupUnregistred is the resolver for the cleanupUnregistred field.
-func (r *qBitTorrentDaemonMutationResolver) CleanupUnregistred(ctx context.Context, obj *model.QBitTorrentDaemonMutation, run bool) (*model.QBitCleanupUnregistredResponse, error) {
-	// hahses, err := r.QBitTorrentDaemon.CleanupUnregistred(ctx, run)
-	// if err != nil {
-	// 	return nil, err
-	// }
-	// return &model.QBitCleanupUnregistredResponse{
-	// 	Count:  int64(len(hahses)),
-	// 	Hashes: hahses,
-	// }, nil
-	panic("not implemented")
-}
-
-// QBitTorrentDaemonMutation returns graph.QBitTorrentDaemonMutationResolver implementation.
-func (r *Resolver) QBitTorrentDaemonMutation() graph.QBitTorrentDaemonMutationResolver {
-	return &qBitTorrentDaemonMutationResolver{r}
-}
-
-type qBitTorrentDaemonMutationResolver struct{ *Resolver }
diff --git a/server/src/delivery/graphql/resolver/qbittorrent_query.resolvers.go b/server/src/delivery/graphql/resolver/qbittorrent_query.resolvers.go
deleted file mode 100644
index ff99ab8..0000000
--- a/server/src/delivery/graphql/resolver/qbittorrent_query.resolvers.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package resolver
-
-// This file will be automatically regenerated based on the schema, any resolver implementations
-// will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
-
-import (
-	"context"
-
-	graph "git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql"
-	"git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model"
-)
-
-// Torrents is the resolver for the torrents field.
-func (r *qBitTorrentDaemonQueryResolver) Torrents(ctx context.Context, obj *model.QBitTorrentDaemonQuery, filter *model.QBitTorrentDaemonFilter) ([]*model.QTorrent, error) {
-	// info, err := r.QBitTorrentDaemon.ListTorrents(ctx)
-	// if err != nil {
-	// 	return nil, fmt.Errorf("error listing torrents: %w", err)
-	// }
-
-	// out := make([]*model.QTorrent, len(info))
-	// for i, v := range info {
-	// 	out[i] = &model.QTorrent{
-	// 		Name: v.Name,
-	// 		Hash: v.Hash,
-	// 	}
-	// }
-
-	// if filter != nil {
-	// 	if filter.SourcesCount != nil {
-	// 		for _, t := range out {
-	// 			srcs, err := r.QBitTorrentDaemon.SourceFiles(ctx, t.Hash)
-	// 			if err != nil {
-	// 				return nil, fmt.Errorf("hash %s failed listing source files: %w", t.Hash, err)
-	// 			}
-	// 			t.SourceFiles = srcs
-	// 		}
-
-	// 		out = slices.DeleteFunc(out, func(t *model.QTorrent) bool {
-	// 			return !filter.SourcesCount.Include(int64(len(t.SourceFiles)))
-	// 		})
-	// 	}
-	// }
-	// return out, nil
-
-	panic("not implemented")
-}
-
-// QBitTorrentDaemonQuery returns graph.QBitTorrentDaemonQueryResolver implementation.
-func (r *Resolver) QBitTorrentDaemonQuery() graph.QBitTorrentDaemonQueryResolver {
-	return &qBitTorrentDaemonQueryResolver{r}
-}
-
-type qBitTorrentDaemonQueryResolver struct{ *Resolver }
diff --git a/server/src/delivery/graphql/resolver/qbittorrent_types.resolvers.go b/server/src/delivery/graphql/resolver/qbittorrent_types.resolvers.go
deleted file mode 100644
index 2588249..0000000
--- a/server/src/delivery/graphql/resolver/qbittorrent_types.resolvers.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package resolver
-
-// This file will be automatically regenerated based on the schema, any resolver implementations
-// will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
-
-import (
-	"context"
-
-	graph "git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql"
-	"git.kmsign.ru/royalcat/tstor/server/src/delivery/graphql/model"
-)
-
-// SourceFiles is the resolver for the sourceFiles field.
-func (r *qTorrentResolver) SourceFiles(ctx context.Context, obj *model.QTorrent) ([]string, error) {
-	// return r.QBitTorrentDaemon.SourceFiles(ctx, obj.Hash)
-	panic("not implemented")
-}
-
-// QTorrent returns graph.QTorrentResolver implementation.
-func (r *Resolver) QTorrent() graph.QTorrentResolver { return &qTorrentResolver{r} }
-
-type qTorrentResolver struct{ *Resolver }
diff --git a/server/src/delivery/graphql/resolver/query.resolvers.go b/server/src/delivery/graphql/resolver/query.resolvers.go
index 0937fcf..21bba95 100644
--- a/server/src/delivery/graphql/resolver/query.resolvers.go
+++ b/server/src/delivery/graphql/resolver/query.resolvers.go
@@ -2,7 +2,7 @@ package resolver
 
 // This file will be automatically regenerated based on the schema, any resolver implementations
 // will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
+// Code generated by github.com/99designs/gqlgen version v0.17.70
 
 import (
 	"context"
diff --git a/server/src/delivery/graphql/resolver/subscription.resolvers.go b/server/src/delivery/graphql/resolver/subscription.resolvers.go
index d92377f..da0deeb 100644
--- a/server/src/delivery/graphql/resolver/subscription.resolvers.go
+++ b/server/src/delivery/graphql/resolver/subscription.resolvers.go
@@ -2,7 +2,7 @@ package resolver
 
 // This file will be automatically regenerated based on the schema, any resolver implementations
 // will be copied through when generating and any unknown code will be moved to the end.
-// Code generated by github.com/99designs/gqlgen version v0.17.68
+// Code generated by github.com/99designs/gqlgen version v0.17.70
 
 import (
 	"context"