cista 0.4.1__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. cista-0.5.0/PKG-INFO +140 -0
  2. cista-0.5.0/README.md +116 -0
  3. {cista-0.4.1 → cista-0.5.0}/cista/__main__.py +33 -6
  4. {cista-0.4.1 → cista-0.5.0}/cista/_version.py +1 -1
  5. {cista-0.4.1 → cista-0.5.0}/cista/app.py +14 -5
  6. {cista-0.4.1 → cista-0.5.0}/cista/config.py +5 -2
  7. {cista-0.4.1 → cista-0.5.0}/cista/watching.py +5 -1
  8. cista-0.4.1/cista/wwwroot/assets/add-file-a9d3c136.js → cista-0.5.0/cista/wwwroot/assets/add-file-78f95102.js +1 -1
  9. cista-0.4.1/cista/wwwroot/assets/add-folder-1067f64c.js → cista-0.5.0/cista/wwwroot/assets/add-folder-ef91bb0e.js +1 -1
  10. cista-0.4.1/cista/wwwroot/assets/arrow-3f20395b.js → cista-0.5.0/cista/wwwroot/assets/arrow-c279db10.js +1 -1
  11. cista-0.4.1/cista/wwwroot/assets/arrows-h-e15dd929.js → cista-0.5.0/cista/wwwroot/assets/arrows-h-0090937e.js +1 -1
  12. cista-0.4.1/cista/wwwroot/assets/arrows-v-aa28c1fb.js → cista-0.5.0/cista/wwwroot/assets/arrows-v-05d0dc3e.js +1 -1
  13. cista-0.4.1/cista/wwwroot/assets/check-79aef249.js → cista-0.5.0/cista/wwwroot/assets/check-736f9156.js +1 -1
  14. cista-0.4.1/cista/wwwroot/assets/code-e36c79c2.js → cista-0.5.0/cista/wwwroot/assets/code-f442e1ae.js +1 -1
  15. cista-0.4.1/cista/wwwroot/assets/cog-7564b1dd.js → cista-0.5.0/cista/wwwroot/assets/cog-fcdd928d.js +1 -1
  16. cista-0.4.1/cista/wwwroot/assets/copy-e3929780.js → cista-0.5.0/cista/wwwroot/assets/copy-f9304d76.js +1 -1
  17. cista-0.4.1/cista/wwwroot/assets/create-file-a4cd2759.js → cista-0.5.0/cista/wwwroot/assets/create-file-5cfbca5b.js +1 -1
  18. cista-0.4.1/cista/wwwroot/assets/create-folder-cb1e0138.js → cista-0.5.0/cista/wwwroot/assets/create-folder-f3416e7f.js +1 -1
  19. cista-0.4.1/cista/wwwroot/assets/cross-d73eb841.js → cista-0.5.0/cista/wwwroot/assets/cross-34310f33.js +1 -1
  20. cista-0.4.1/cista/wwwroot/assets/disk-db1f0765.js → cista-0.5.0/cista/wwwroot/assets/disk-9de14290.js +1 -1
  21. cista-0.4.1/cista/wwwroot/assets/download-a3d43d2f.js → cista-0.5.0/cista/wwwroot/assets/download-40f6e8d9.js +1 -1
  22. cista-0.4.1/cista/wwwroot/assets/exclamation-2902e1df.js → cista-0.5.0/cista/wwwroot/assets/exclamation-67d2f487.js +1 -1
  23. cista-0.4.1/cista/wwwroot/assets/eye-8d101b8e.js → cista-0.5.0/cista/wwwroot/assets/eye-1a9cae12.js +1 -1
  24. cista-0.4.1/cista/wwwroot/assets/find-33f8a0d2.js → cista-0.5.0/cista/wwwroot/assets/find-f49bedc3.js +1 -1
  25. cista-0.4.1/cista/wwwroot/assets/fullscreen-11067704.js → cista-0.5.0/cista/wwwroot/assets/fullscreen-6e83f85d.js +1 -1
  26. cista-0.4.1/cista/wwwroot/assets/github-01e6b073.js → cista-0.5.0/cista/wwwroot/assets/github-33da7a52.js +1 -1
  27. cista-0.4.1/cista/wwwroot/assets/index-ba73bda8.js → cista-0.5.0/cista/wwwroot/assets/index-6716899e.js +4 -4
  28. cista-0.4.1/cista/wwwroot/assets/index-174b17cf.css → cista-0.5.0/cista/wwwroot/assets/index-bcee9add.css +1 -1
  29. cista-0.4.1/cista/wwwroot/assets/info-c4a3f8c5.js → cista-0.5.0/cista/wwwroot/assets/info-9a003b6c.js +1 -1
  30. cista-0.4.1/cista/wwwroot/assets/link-ed858213.js → cista-0.5.0/cista/wwwroot/assets/link-b5bf40a7.js +1 -1
  31. cista-0.4.1/cista/wwwroot/assets/logo-27323863.js → cista-0.5.0/cista/wwwroot/assets/logo-adde2ca4.js +1 -1
  32. cista-0.4.1/cista/wwwroot/assets/loop-5dd137a3.js → cista-0.5.0/cista/wwwroot/assets/loop-762ab430.js +1 -1
  33. cista-0.4.1/cista/wwwroot/assets/menu-1032d481.js → cista-0.5.0/cista/wwwroot/assets/menu-633b2a61.js +1 -1
  34. cista-0.4.1/cista/wwwroot/assets/next-eb6c8a7f.js → cista-0.5.0/cista/wwwroot/assets/next-d9d1d510.js +1 -1
  35. cista-0.4.1/cista/wwwroot/assets/open-d6baab3e.js → cista-0.5.0/cista/wwwroot/assets/open-91351e45.js +1 -1
  36. cista-0.4.1/cista/wwwroot/assets/paste-dbc34e03.js → cista-0.5.0/cista/wwwroot/assets/paste-d3f337c1.js +1 -1
  37. cista-0.4.1/cista/wwwroot/assets/pause-5bc73725.js → cista-0.5.0/cista/wwwroot/assets/pause-8f82e536.js +1 -1
  38. cista-0.4.1/cista/wwwroot/assets/pencil-d5ffe2dc.js → cista-0.5.0/cista/wwwroot/assets/pencil-0b434534.js +1 -1
  39. cista-0.4.1/cista/wwwroot/assets/play-7817e413.js → cista-0.5.0/cista/wwwroot/assets/play-e0e51167.js +1 -1
  40. cista-0.4.1/cista/wwwroot/assets/plus-0c299339.js → cista-0.5.0/cista/wwwroot/assets/plus-e2a2ec0f.js +1 -1
  41. cista-0.4.1/cista/wwwroot/assets/previous-626a4acb.js → cista-0.5.0/cista/wwwroot/assets/previous-cd61ebe6.js +1 -1
  42. cista-0.4.1/cista/wwwroot/assets/reload-128d6c02.js → cista-0.5.0/cista/wwwroot/assets/reload-a9c668b2.js +1 -1
  43. cista-0.4.1/cista/wwwroot/assets/rename-aa3dba61.js → cista-0.5.0/cista/wwwroot/assets/rename-bd15329b.js +1 -1
  44. cista-0.4.1/cista/wwwroot/assets/scissors-bd9fe56f.js → cista-0.5.0/cista/wwwroot/assets/scissors-dcbf78c0.js +1 -1
  45. cista-0.4.1/cista/wwwroot/assets/shuffle-7f5be9e9.js → cista-0.5.0/cista/wwwroot/assets/shuffle-74e9ea1c.js +1 -1
  46. cista-0.4.1/cista/wwwroot/assets/signin-d3d6ced4.js → cista-0.5.0/cista/wwwroot/assets/signin-bbf26a1b.js +1 -1
  47. cista-0.4.1/cista/wwwroot/assets/signout-fc3c85db.js → cista-0.5.0/cista/wwwroot/assets/signout-caa34d68.js +1 -1
  48. cista-0.4.1/cista/wwwroot/assets/skip-b98696e7.js → cista-0.5.0/cista/wwwroot/assets/skip-423d5cf0.js +1 -1
  49. cista-0.4.1/cista/wwwroot/assets/spinner-b41d7188.js → cista-0.5.0/cista/wwwroot/assets/spinner-b299e14e.js +1 -1
  50. cista-0.4.1/cista/wwwroot/assets/stop-c58e520a.js → cista-0.5.0/cista/wwwroot/assets/stop-91578a62.js +1 -1
  51. cista-0.4.1/cista/wwwroot/assets/trash-d4df4c21.js → cista-0.5.0/cista/wwwroot/assets/trash-3b7b72a3.js +1 -1
  52. cista-0.4.1/cista/wwwroot/assets/triangle-12112b17.js → cista-0.5.0/cista/wwwroot/assets/triangle-724a2314.js +1 -1
  53. cista-0.4.1/cista/wwwroot/assets/unfullscreen-a97c74fb.js → cista-0.5.0/cista/wwwroot/assets/unfullscreen-29f4977c.js +1 -1
  54. cista-0.4.1/cista/wwwroot/assets/up-arrow-23c1796b.js → cista-0.5.0/cista/wwwroot/assets/up-arrow-ceb58d59.js +1 -1
  55. cista-0.4.1/cista/wwwroot/assets/upload-cloud-4f346520.js → cista-0.5.0/cista/wwwroot/assets/upload-cloud-936fb8b2.js +1 -1
  56. cista-0.4.1/cista/wwwroot/assets/user-074e37bb.js → cista-0.5.0/cista/wwwroot/assets/user-ab4ed9ac.js +1 -1
  57. cista-0.4.1/cista/wwwroot/assets/user-cog-64e9a313.js → cista-0.5.0/cista/wwwroot/assets/user-cog-887c6f3f.js +1 -1
  58. cista-0.4.1/cista/wwwroot/assets/volume-high-cfc5dfaf.js → cista-0.5.0/cista/wwwroot/assets/volume-high-74a17568.js +1 -1
  59. cista-0.4.1/cista/wwwroot/assets/volume-low-1ef7167e.js → cista-0.5.0/cista/wwwroot/assets/volume-low-f7170d5f.js +1 -1
  60. cista-0.4.1/cista/wwwroot/assets/volume-medium-a7aea406.js → cista-0.5.0/cista/wwwroot/assets/volume-medium-7b16c1db.js +1 -1
  61. cista-0.4.1/cista/wwwroot/assets/volume-mute-d74a4abf.js → cista-0.5.0/cista/wwwroot/assets/volume-mute-0c7078a1.js +1 -1
  62. cista-0.4.1/cista/wwwroot/assets/window-cross-f8232e18.js → cista-0.5.0/cista/wwwroot/assets/window-cross-e3a75b33.js +1 -1
  63. cista-0.4.1/cista/wwwroot/assets/window-76484866.js → cista-0.5.0/cista/wwwroot/assets/window-f7f79ada.js +1 -1
  64. cista-0.4.1/cista/wwwroot/assets/wordwrap-ae2f69a5.js → cista-0.5.0/cista/wwwroot/assets/wordwrap-3bcce83c.js +1 -1
  65. cista-0.4.1/cista/wwwroot/assets/zoomin-401eeaf9.js → cista-0.5.0/cista/wwwroot/assets/zoomin-bd27188c.js +1 -1
  66. cista-0.4.1/cista/wwwroot/assets/zoomout-ad6f32e8.js → cista-0.5.0/cista/wwwroot/assets/zoomout-31844707.js +1 -1
  67. {cista-0.4.1 → cista-0.5.0}/cista/wwwroot/index.html +2 -2
  68. cista-0.4.1/PKG-INFO +0 -102
  69. cista-0.4.1/README.md +0 -78
  70. {cista-0.4.1 → cista-0.5.0}/.gitignore +0 -0
  71. {cista-0.4.1 → cista-0.5.0}/cista/__init__.py +0 -0
  72. {cista-0.4.1 → cista-0.5.0}/cista/api.py +0 -0
  73. {cista-0.4.1 → cista-0.5.0}/cista/auth.py +0 -0
  74. {cista-0.4.1 → cista-0.5.0}/cista/droppy.py +0 -0
  75. {cista-0.4.1 → cista-0.5.0}/cista/fileio.py +0 -0
  76. {cista-0.4.1 → cista-0.5.0}/cista/protocol.py +0 -0
  77. {cista-0.4.1 → cista-0.5.0}/cista/serve.py +0 -0
  78. {cista-0.4.1 → cista-0.5.0}/cista/server80.py +0 -0
  79. {cista-0.4.1 → cista-0.5.0}/cista/session.py +0 -0
  80. {cista-0.4.1 → cista-0.5.0}/cista/util/__init__.py +0 -0
  81. {cista-0.4.1 → cista-0.5.0}/cista/util/apphelpers.py +0 -0
  82. {cista-0.4.1 → cista-0.5.0}/cista/util/asynclink.py +0 -0
  83. {cista-0.4.1 → cista-0.5.0}/cista/util/filename.py +0 -0
  84. {cista-0.4.1 → cista-0.5.0}/cista/util/lrucache.py +0 -0
  85. {cista-0.4.1 → cista-0.5.0}/cista/util/pwgen.py +0 -0
  86. {cista-0.4.1 → cista-0.5.0}/cista/wwwroot/assets/logo-97d1d7eb.svg +0 -0
  87. {cista-0.4.1 → cista-0.5.0}/cista/wwwroot/robots.txt +0 -0
  88. {cista-0.4.1 → cista-0.5.0}/pyproject.toml +0 -0
cista-0.5.0/PKG-INFO ADDED
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.1
2
+ Name: cista
3
+ Version: 0.5.0
4
+ Summary: Dropbox-like file server with modern web interface
5
+ Project-URL: Homepage, https://git.zi.fi/Vasanko/cista-storage
6
+ Author: Vasanko
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: argon2-cffi
9
+ Requires-Dist: blake3
10
+ Requires-Dist: brotli
11
+ Requires-Dist: docopt
12
+ Requires-Dist: inotify
13
+ Requires-Dist: msgspec
14
+ Requires-Dist: natsort
15
+ Requires-Dist: pathvalidate
16
+ Requires-Dist: pyjwt
17
+ Requires-Dist: sanic
18
+ Requires-Dist: stream-zip
19
+ Requires-Dist: tomli-w
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest; extra == 'dev'
22
+ Requires-Dist: ruff; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # Cista Web Storage
26
+
27
+ <img src="https://git.zi.fi/Vasanko/cista-storage/raw/branch/main/docs/cista.jpg" align=right width=250>
28
+
29
+ Cista takes its name from the ancient cistae, metal containers used by Greeks and Egyptians to safeguard valuable items. This modern application provides a browser interface for secure and accessible file storage, echoing the trust and reliability of its historical namesake.
30
+
31
+ This is a cutting-edge **file and document server** designed for speed, efficiency, and unparalleled ease of use. Experience **lightning-fast browsing**, thanks to the file list maintained directly in your browser and updated from server filesystem events, coupled with our highly optimized code. Fully **keyboard-navigable** and with a responsive layout, Cista flawlessly adapts to your devices, providing a seamless experience wherever you are. Our powerful **instant search** means you're always just a few keystrokes away from finding exactly what you need. Press **1/2/3** to switch ordering, navigate with all four arrow keys (+Shift to select). Or click your way around on **breadcrumbs that remember where you were**.
32
+
33
+ The Cista project started as an inevitable remake of [Droppy](https://github.com/droppyjs/droppy) which we used and loved despite its numerous bugs. Cista Storage stands out in handling even the most exotic filenames, ensuring a smooth experience where others falter.
34
+
35
+ All of this is wrapped in an intuitive interface with automatic light and dark themes, making Cista Storage the ideal choice for anyone seeking a reliable, versatile, and quick file storage solution. Quickly setup your own Cista where your files are just a click away, safe, and always accessible.
36
+
37
+ Experience Cista by visiting [Cista Demo](https://drop.zi.fi) for a test run and perhaps upload something...
38
+
39
+
40
+ ## Getting Started
41
+ ### Installation
42
+
43
+ To install the cista application, use:
44
+
45
+ ```fish
46
+ pip install cista
47
+ ```
48
+
49
+ Note: Some Linux distributions might need `--break-system-packages` to install Python packages, which are safely installed in the user's home folder. As an alternative to avoid installation, run it with command `pipx run cista`
50
+
51
+ ### Running the Server
52
+
53
+ Create an account: (or run a public server without authentication)
54
+ ```fish
55
+ cista --user yourname --privileged
56
+ ```
57
+
58
+ Serve your files at http://localhost:8000:
59
+ ```fish
60
+ cista -l :8000 /path/to/files
61
+ ```
62
+
63
+ The server remembers its settings in the config folder (default `~/.local/share/cista/`), including the listen port and directory, for future runs without arguments.
64
+
65
+ ### Internet Access
66
+
67
+ To use your own TLS certificates, place them in the config folder and run:
68
+
69
+ ```fish
70
+ cista -l cista.example.com
71
+ ```
72
+
73
+ Most admins instead find the [Caddy](https://caddyserver.com/) web server convenient for its auto TLS certificates and all. A proxy also allows running multiple web services or Cista instances on the same IP address. Caddy configuration **/etc/caddy/Caddyfile** is dead simple:
74
+
75
+ ```Caddyfile
76
+ cista.example.com {
77
+ reverse_proxy :8000
78
+ }
79
+ ```
80
+
81
+ ## Development setup
82
+
83
+ For rapid development, we use the Vite development server for the Vue frontend, while running the backend on port 8000 that Vite proxies backend requests to. Each server live reloads whenever its code or configuration are modified.
84
+
85
+ ```fish
86
+ cd frontend
87
+ npm install
88
+ npm run dev
89
+ ```
90
+
91
+ Concurrently, start the backend on another terminal:
92
+
93
+ ```fish
94
+ hatch shell
95
+ pip install -e '.[dev]'
96
+ cista --dev -l :8000 /path/to/files
97
+ ```
98
+
99
+ We use `hatch shell` for installing on a virtual environment, to not disturb the rest of the system with our hacking.
100
+
101
+ Vue is used to build files in `cista/wwwroot`, included prebuilt in the Python package. Running `hatch build` builds the frontend and creates a NodeJS-independent Python package.
102
+
103
+ ## System Deployment
104
+
105
+ This setup allows easy addition of storages, each with its own domain, configuration, and files.
106
+
107
+ Assuming a restricted user account **storage** for serving files and that cista is installed system-wide or on this account (check with `sudo -u storage -s`). Alternatively, use `pipx run cista` or `hatch run cista` as the ExecStart command.
108
+
109
+ Create **/etc/systemd/system/cista@.service**:
110
+
111
+ ```ini
112
+ [Unit]
113
+ Description=Cista storage %i
114
+
115
+ [Service]
116
+ User=storage
117
+ ExecStart=cista -c /srv/cista/%i -l /srv/cista/%i/socket /media/storage/@%i/
118
+ Restart=always
119
+
120
+ [Install]
121
+ WantedBy=multi-user.target
122
+ ```
123
+
124
+ This setup supports multiple storages, each under `/media/storage/<domain>` for files and `/srv/cista/<domain>/` for configuration. UNIX sockets are used instead of numeric ports for convenience.
125
+
126
+ ```fish
127
+ systemctl daemon-reload
128
+ systemctl enable --now cista@foo.example.com
129
+ systemctl enable --now cista@bar.example.com
130
+ ```
131
+
132
+ Public exposure is easiest using the Caddy web server, but Nginx or others also work. Run the server with -l domain.example.com if you have TLS certificates in the config folder.
133
+
134
+ **/etc/caddy/Caddyfile**:
135
+
136
+ ```Caddyfile
137
+ foo.example.com, bar.example.com {
138
+ reverse_proxy unix//srv/cista/{host}/socket
139
+ }
140
+ ```
cista-0.5.0/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # Cista Web Storage
2
+
3
+ <img src="https://git.zi.fi/Vasanko/cista-storage/raw/branch/main/docs/cista.jpg" align=right width=250>
4
+
5
+ Cista takes its name from the ancient cistae, metal containers used by Greeks and Egyptians to safeguard valuable items. This modern application provides a browser interface for secure and accessible file storage, echoing the trust and reliability of its historical namesake.
6
+
7
+ This is a cutting-edge **file and document server** designed for speed, efficiency, and unparalleled ease of use. Experience **lightning-fast browsing**, thanks to the file list maintained directly in your browser and updated from server filesystem events, coupled with our highly optimized code. Fully **keyboard-navigable** and with a responsive layout, Cista flawlessly adapts to your devices, providing a seamless experience wherever you are. Our powerful **instant search** means you're always just a few keystrokes away from finding exactly what you need. Press **1/2/3** to switch ordering, navigate with all four arrow keys (+Shift to select). Or click your way around on **breadcrumbs that remember where you were**.
8
+
9
+ The Cista project started as an inevitable remake of [Droppy](https://github.com/droppyjs/droppy) which we used and loved despite its numerous bugs. Cista Storage stands out in handling even the most exotic filenames, ensuring a smooth experience where others falter.
10
+
11
+ All of this is wrapped in an intuitive interface with automatic light and dark themes, making Cista Storage the ideal choice for anyone seeking a reliable, versatile, and quick file storage solution. Quickly setup your own Cista where your files are just a click away, safe, and always accessible.
12
+
13
+ Experience Cista by visiting [Cista Demo](https://drop.zi.fi) for a test run and perhaps upload something...
14
+
15
+
16
+ ## Getting Started
17
+ ### Installation
18
+
19
+ To install the cista application, use:
20
+
21
+ ```fish
22
+ pip install cista
23
+ ```
24
+
25
+ Note: Some Linux distributions might need `--break-system-packages` to install Python packages, which are safely installed in the user's home folder. As an alternative to avoid installation, run it with command `pipx run cista`
26
+
27
+ ### Running the Server
28
+
29
+ Create an account: (or run a public server without authentication)
30
+ ```fish
31
+ cista --user yourname --privileged
32
+ ```
33
+
34
+ Serve your files at http://localhost:8000:
35
+ ```fish
36
+ cista -l :8000 /path/to/files
37
+ ```
38
+
39
+ The server remembers its settings in the config folder (default `~/.local/share/cista/`), including the listen port and directory, for future runs without arguments.
40
+
41
+ ### Internet Access
42
+
43
+ To use your own TLS certificates, place them in the config folder and run:
44
+
45
+ ```fish
46
+ cista -l cista.example.com
47
+ ```
48
+
49
+ Most admins instead find the [Caddy](https://caddyserver.com/) web server convenient for its auto TLS certificates and all. A proxy also allows running multiple web services or Cista instances on the same IP address. Caddy configuration **/etc/caddy/Caddyfile** is dead simple:
50
+
51
+ ```Caddyfile
52
+ cista.example.com {
53
+ reverse_proxy :8000
54
+ }
55
+ ```
56
+
57
+ ## Development setup
58
+
59
+ For rapid development, we use the Vite development server for the Vue frontend, while running the backend on port 8000 that Vite proxies backend requests to. Each server live reloads whenever its code or configuration are modified.
60
+
61
+ ```fish
62
+ cd frontend
63
+ npm install
64
+ npm run dev
65
+ ```
66
+
67
+ Concurrently, start the backend on another terminal:
68
+
69
+ ```fish
70
+ hatch shell
71
+ pip install -e '.[dev]'
72
+ cista --dev -l :8000 /path/to/files
73
+ ```
74
+
75
+ We use `hatch shell` for installing on a virtual environment, to not disturb the rest of the system with our hacking.
76
+
77
+ Vue is used to build files in `cista/wwwroot`, included prebuilt in the Python package. Running `hatch build` builds the frontend and creates a NodeJS-independent Python package.
78
+
79
+ ## System Deployment
80
+
81
+ This setup allows easy addition of storages, each with its own domain, configuration, and files.
82
+
83
+ Assuming a restricted user account **storage** for serving files and that cista is installed system-wide or on this account (check with `sudo -u storage -s`). Alternatively, use `pipx run cista` or `hatch run cista` as the ExecStart command.
84
+
85
+ Create **/etc/systemd/system/cista@.service**:
86
+
87
+ ```ini
88
+ [Unit]
89
+ Description=Cista storage %i
90
+
91
+ [Service]
92
+ User=storage
93
+ ExecStart=cista -c /srv/cista/%i -l /srv/cista/%i/socket /media/storage/@%i/
94
+ Restart=always
95
+
96
+ [Install]
97
+ WantedBy=multi-user.target
98
+ ```
99
+
100
+ This setup supports multiple storages, each under `/media/storage/<domain>` for files and `/srv/cista/<domain>/` for configuration. UNIX sockets are used instead of numeric ports for convenience.
101
+
102
+ ```fish
103
+ systemctl daemon-reload
104
+ systemctl enable --now cista@foo.example.com
105
+ systemctl enable --now cista@bar.example.com
106
+ ```
107
+
108
+ Public exposure is easiest using the Caddy web server, but Nginx or others also work. Run the server with -l domain.example.com if you have TLS certificates in the config folder.
109
+
110
+ **/etc/caddy/Caddyfile**:
111
+
112
+ ```Caddyfile
113
+ foo.example.com, bar.example.com {
114
+ reverse_proxy unix//srv/cista/{host}/socket
115
+ }
116
+ ```
@@ -62,12 +62,15 @@ def _main():
62
62
  _confdir(args)
63
63
  exists = config.conffile.exists()
64
64
  import_droppy = args["--import-droppy"]
65
- necessary_opts = exists or import_droppy or path and listen
65
+ necessary_opts = exists or import_droppy or path
66
66
  if not necessary_opts:
67
67
  # Maybe run without arguments
68
68
  print(doc)
69
69
  print(
70
- "No config file found! Get started with:\n cista -l :8000 /path/to/files, or\n cista -l example.com --import-droppy # Uses Droppy files\n",
70
+ "No config file found! Get started with one of:\n"
71
+ " cista --user yourname --privileged\n"
72
+ " cista --import-droppy\n"
73
+ " cista -l :8000 /path/to/files\n"
71
74
  )
72
75
  return 1
73
76
  settings = {}
@@ -79,8 +82,15 @@ def _main():
79
82
  settings = droppy.readconf()
80
83
  if path:
81
84
  settings["path"] = path
85
+ elif not exists:
86
+ settings["path"] = Path.home() / "Downloads"
82
87
  if listen:
83
88
  settings["listen"] = listen
89
+ elif not exists:
90
+ settings["listen"] = ":8000"
91
+ if not exists and not import_droppy:
92
+ # We have no users, so make it public
93
+ settings["public"] = True
84
94
  operation = config.update_config(settings)
85
95
  print(f"Config {operation}: {config.conffile}")
86
96
  # Prepare to serve
@@ -112,11 +122,23 @@ def _confdir(args):
112
122
 
113
123
  def _user(args):
114
124
  _confdir(args)
115
- config.load_config()
125
+ if config.conffile.exists():
126
+ config.load_config()
127
+ operation = False
128
+ else:
129
+ # Defaults for new config when user is created
130
+ operation = config.update_config(
131
+ {
132
+ "listen": ":8000",
133
+ "path": Path.home() / "Downloads",
134
+ "public": False,
135
+ }
136
+ )
137
+ print(f"Config {operation}: {config.conffile}\n")
138
+
116
139
  name = args["--user"]
117
140
  if not name or not name.isidentifier():
118
141
  raise ValueError("Invalid username")
119
- config.load_config()
120
142
  u = config.config.users.get(name)
121
143
  info = f"User {name}" if u else f"New user {name}"
122
144
  changes = {}
@@ -128,12 +150,17 @@ def _user(args):
128
150
  info += " (admin)" if oldadmin else ""
129
151
  if args["--password"] or not u:
130
152
  changes["password"] = pw = pwgen.generate()
131
- info += f"\n Password: {pw}"
132
- res = config.update_user(args["--user"], changes)
153
+ info += f"\n Password: {pw}\n"
154
+ res = config.update_user(name, changes)
133
155
  print(info)
134
156
  if res == "read":
135
157
  print(" No changes")
136
158
 
159
+ if operation == "created":
160
+ print(
161
+ "Now you can run the server:\n cista # defaults set: -l :8000 ~/Downloads\n"
162
+ )
163
+
137
164
 
138
165
  if __name__ == "__main__":
139
166
  sys.exit(main())
@@ -1,2 +1,2 @@
1
1
  # This file is automatically generated by hatch build.
2
- __version__ = '0.4.1'
2
+ __version__ = '0.5.0'
@@ -11,7 +11,7 @@ import brotli
11
11
  import sanic.helpers
12
12
  from blake3 import blake3
13
13
  from sanic import Blueprint, Sanic, empty, raw
14
- from sanic.exceptions import Forbidden, NotFound, ServerError
14
+ from sanic.exceptions import Forbidden, NotFound
15
15
  from sanic.log import logging
16
16
  from stream_zip import ZIP_AUTO, stream_zip
17
17
 
@@ -120,10 +120,19 @@ def _load_wwwroot(www):
120
120
  br = False
121
121
  wwwnew[name] = data, br, headers
122
122
  if not wwwnew:
123
- raise ServerError(
124
- "Web frontend missing. Did you forget npm run build?",
125
- extra={"wwwroot": str(base)},
126
- quiet=True,
123
+ msg = f"Web frontend missing from {base}\n Did you forget: hatch build\n"
124
+ if not www:
125
+ logging.warning(msg)
126
+ if not app.debug:
127
+ msg = "Web frontend missing. Cista installation is broken.\n"
128
+ wwwnew[""] = (
129
+ msg.encode(),
130
+ False,
131
+ {
132
+ "etag": "error",
133
+ "content-type": "text/plain",
134
+ "cache-control": "no-store",
135
+ },
127
136
  )
128
137
  return wwwnew
129
138
 
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import secrets
4
+ import sys
4
5
  from functools import wraps
5
6
  from hashlib import sha256
6
7
  from pathlib import Path, PurePath
@@ -90,6 +91,8 @@ def config_update(modify):
90
91
  return "read"
91
92
  f.write(new)
92
93
  f.close()
94
+ if sys.platform == "win32":
95
+ conffile.unlink() # Windows doesn't support atomic replace
93
96
  tmpname.rename(conffile) # Atomic replace
94
97
  except:
95
98
  f.close()
@@ -135,7 +138,7 @@ def update_user(conf: Config, name: str, changes: dict) -> Config:
135
138
  # Encode into dict, update values with new, convert to Config
136
139
  try:
137
140
  u = conf.users[name].__copy__()
138
- except KeyError:
141
+ except (KeyError, AttributeError):
139
142
  u = User()
140
143
  if "password" in changes:
141
144
  from . import auth
@@ -144,7 +147,7 @@ def update_user(conf: Config, name: str, changes: dict) -> Config:
144
147
  del changes["password"]
145
148
  udict = msgspec.to_builtins(u, enc_hook=enc_hook)
146
149
  udict.update(changes)
147
- settings = msgspec.to_builtins(conf, enc_hook=enc_hook)
150
+ settings = msgspec.to_builtins(conf, enc_hook=enc_hook) if conf else {"users": {}}
148
151
  settings["users"][name] = msgspec.convert(udict, User, dec_hook=dec_hook)
149
152
  return msgspec.convert(settings, Config, dec_hook=dec_hook)
150
153
 
@@ -129,7 +129,7 @@ def watcher_thread(loop):
129
129
  global rootpath
130
130
  import inotify.adapters
131
131
 
132
- while True:
132
+ while not quit:
133
133
  rootpath = config.config.path
134
134
  i = inotify.adapters.InotifyTree(rootpath.as_posix())
135
135
  # Initialize the tree from filesystem
@@ -218,11 +218,15 @@ def _walk(rel: PurePosixPath, isfile: int, st: stat_result) -> list[FileEntry]:
218
218
  try:
219
219
  li = []
220
220
  for f in path.iterdir():
221
+ if quit:
222
+ raise SystemExit("quit")
221
223
  if f.name.startswith("."):
222
224
  continue # No dotfiles
223
225
  s = f.stat()
224
226
  li.append((int(not stat.S_ISDIR(s.st_mode)), f.name, s))
225
227
  for [isfile, name, s] in humansorted(li):
228
+ if quit:
229
+ raise SystemExit("quit")
226
230
  subtree = _walk(rel / name, isfile, s)
227
231
  child = subtree[0]
228
232
  entry.mtime = max(entry.mtime, child.mtime)
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 28 28"},c=o("path",{d:"M19.2 2.6H6.1V29h19.8V9.3l-6.7-6.7zM18.5 16v7.1h-5.3V16H8.7l7.1-7.1L23 16h-4.5z"},null,-1),n=[c];function a(r,d){return e(),t("svg",s,[...n])}const h={render:a};export{h as default,a as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 28 28"},c=o("path",{d:"M19.2 2.6H6.1V29h19.8V9.3l-6.7-6.7zM18.5 16v7.1h-5.3V16H8.7l7.1-7.1L23 16h-4.5z"},null,-1),n=[c];function a(r,d){return e(),t("svg",s,[...n])}const h={render:a};export{h as default,a as render};
@@ -1 +1 @@
1
- import{o as e,c as o,a as t}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},c=t("path",{d:"M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20H0zm18.3 9.5V27h-5.6v-7.5H8l7.5-7.5 7.5 7.5h-4.7z"},null,-1),n=[c];function r(a,l){return e(),o("svg",s,[...n])}const h={render:r};export{h as default,r as render};
1
+ import{o as e,c as o,a as t}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},c=t("path",{d:"M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20H0zm18.3 9.5V27h-5.6v-7.5H8l7.5-7.5 7.5 7.5h-4.7z"},null,-1),n=[c];function r(a,l){return e(),o("svg",s,[...n])}const h={render:r};export{h as default,r as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const c={xmlns:"http://www.w3.org/2000/svg",width:"640",height:"640",viewBox:"0 -32 640 640"},s=o("path",{d:"M495.46 365.98c-13.03-13.37-150.24-144.06-150.24-144.06A35.16 35.16 0 0 0 320 211.2a35.06 35.06 0 0 0-25.22 10.72s-137.2 130.7-150.27 144.06c-13 13.38-13.9 37.44 0 51.72 14 14.24 33.4 15.4 50.48 0L320 297.8l125.02 119.9c17.1 15.4 36.55 14.24 50.44 0 13.95-14.3 13.08-38.37 0-51.72z"},null,-1),r=[s];function a(n,d){return e(),t("svg",c,[...r])}const i={render:a};export{i as default,a as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const c={xmlns:"http://www.w3.org/2000/svg",width:"640",height:"640",viewBox:"0 -32 640 640"},s=o("path",{d:"M495.46 365.98c-13.03-13.37-150.24-144.06-150.24-144.06A35.16 35.16 0 0 0 320 211.2a35.06 35.06 0 0 0-25.22 10.72s-137.2 130.7-150.27 144.06c-13 13.38-13.9 37.44 0 51.72 14 14.24 33.4 15.4 50.48 0L320 297.8l125.02 119.9c17.1 15.4 36.55 14.24 50.44 0 13.95-14.3 13.08-38.37 0-51.72z"},null,-1),r=[s];function a(n,d){return e(),t("svg",c,[...r])}const i={render:a};export{i as default,a as render};
@@ -1 +1 @@
1
- import{o as e,c as o,a as t}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-6 -2 44 36"},r=t("path",{d:"M12 18H6v4l-6-6 6-6v4h6zm8-4h6v-4l6 6-6 6v-4h-6z"},null,-1),c=[r];function n(a,h){return e(),o("svg",s,[...c])}const d={render:n};export{d as default,n as render};
1
+ import{o as e,c as o,a as t}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-6 -2 44 36"},r=t("path",{d:"M12 18H6v4l-6-6 6-6v4h6zm8-4h6v-4l6 6-6 6v-4h-6z"},null,-1),c=[r];function n(a,h){return e(),o("svg",s,[...c])}const d={render:n};export{d as default,n as render};
@@ -1 +1 @@
1
- import{o as e,c as o,a as t}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -6 16 44"},r=t("path",{d:"M8 20v6h4l-6 6-6-6h4v-6zm-4-8V6H0l6-6 6 6H8v6z"},null,-1),c=[r];function n(a,l){return e(),o("svg",s,[...c])}const h={render:n};export{h as default,n as render};
1
+ import{o as e,c as o,a as t}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -6 16 44"},r=t("path",{d:"M8 20v6h4l-6 6-6-6h4v-6zm-4-8V6H0l6-6 6 6H8v6z"},null,-1),c=[r];function n(a,l){return e(),o("svg",s,[...c])}const h={render:n};export{h as default,n as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const c={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512",viewBox:"-48 0 512 512"},s=o("path",{d:"M320 96 128 288l-64-64-64 64 128 128 256-256-64-64z"},null,-1),n=[s];function r(a,h){return e(),t("svg",c,[...n])}const i={render:r};export{i as default,r as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const c={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512",viewBox:"-48 0 512 512"},s=o("path",{d:"M320 96 128 288l-64-64-64 64 128 128 256-256-64-64z"},null,-1),n=[s];function r(a,h){return e(),t("svg",c,[...n])}const i={render:r};export{i as default,r as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512",viewBox:"-24 8 512 512"},c=o("path",{d:"m304 96-48 48 112 112-112 112 48 48 144-160L304 96zm-160 0L0 256l144 160 48-48L80 256l112-112-48-48z"},null,-1),n=[c];function r(a,d){return e(),t("svg",s,[...n])}const l={render:r};export{l as default,r as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512",viewBox:"-24 8 512 512"},c=o("path",{d:"m304 96-48 48 112 112-112 112 48 48 144-160L304 96zm-160 0L0 256l144 160 48-48L80 256l112-112-48-48z"},null,-1),n=[c];function r(a,d){return e(),t("svg",s,[...n])}const l={render:r};export{l as default,r as render};
@@ -1 +1 @@
1
- import{o as e,c as o,a as t}from"./index-ba73bda8.js";const c={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 448 512"},s=t("path",{d:"M223.97 175A81 81 0 0 0 143 256c0 44.7 36.27 81.03 80.97 81.03 44.72 0 80.72-36.34 80.72-81.03 0-44.73-36-81-80.8-81zM386.3 302.53l-14.58 35.16 29.47 57.8-36.1 36.1-59.3-28-35.2 14.4-17.87 54.6-2.28 7.24h-51L177.4 418.2l-35.17-14.5-57.9 29.4-36.1-36.1 27.97-59.2-14.47-35.12L0 282.6v-51l61.7-22.1 14.5-35.1-25.96-51.23-3.43-6.72 36.1-36.03 59.3 27.92 35.1-14.5 17.9-54.6 2.3-7.24h51l22.1 61.73 35.07 14.52 58.04-29.4 36.06 36.03-27.96 59.2 14.42 35.17 61.8 20.13v50.97l-61.67 22.18z"},null,-1),n=[s];function l(r,a){return e(),o("svg",c,[...n])}const h={render:l};export{h as default,l as render};
1
+ import{o as e,c as o,a as t}from"./index-6716899e.js";const c={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 448 512"},s=t("path",{d:"M223.97 175A81 81 0 0 0 143 256c0 44.7 36.27 81.03 80.97 81.03 44.72 0 80.72-36.34 80.72-81.03 0-44.73-36-81-80.8-81zM386.3 302.53l-14.58 35.16 29.47 57.8-36.1 36.1-59.3-28-35.2 14.4-17.87 54.6-2.28 7.24h-51L177.4 418.2l-35.17-14.5-57.9 29.4-36.1-36.1 27.97-59.2-14.47-35.12L0 282.6v-51l61.7-22.1 14.5-35.1-25.96-51.23-3.43-6.72 36.1-36.03 59.3 27.92 35.1-14.5 17.9-54.6 2.3-7.24h51l22.1 61.73 35.07 14.52 58.04-29.4 36.06 36.03-27.96 59.2 14.42 35.17 61.8 20.13v50.97l-61.67 22.18z"},null,-1),n=[s];function l(r,a){return e(),o("svg",c,[...n])}const h={render:l};export{h as default,l as render};
@@ -1 +1 @@
1
- import{o as e,c as o,a as t}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -2 36 36"},c=t("path",{d:"M26 8h-6V6l-6-6H0v24h12v8h20V14l-6-6zm0 2.83L29.17 14H26v-3.17zm-12-8L17.17 6H14V2.83zM2 2h10v6h6v14H2V2zm28 28H14v-6h6V10h4v6h6v14z"},null,-1),h=[c];function n(r,a){return e(),o("svg",s,[...h])}const l={render:n};export{l as default,n as render};
1
+ import{o as e,c as o,a as t}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -2 36 36"},c=t("path",{d:"M26 8h-6V6l-6-6H0v24h12v8h20V14l-6-6zm0 2.83L29.17 14H26v-3.17zm-12-8L17.17 6H14V2.83zM2 2h10v6h6v14H2V2zm28 28H14v-6h6V10h4v6h6v14z"},null,-1),h=[c];function n(r,a){return e(),o("svg",s,[...h])}const l={render:n};export{l as default,n as render};
@@ -1 +1 @@
1
- import{o as e,c,a as t}from"./index-ba73bda8.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},s=t("path",{d:"M19.2 2.6H6.1V29h19.8V9.3l-6.7-6.7zm3 15c0 .2-.2.4-.4.4h-4.4v4.4c0 .2-.2.4-.4.4h-2.4c-.2 0-.4-.2-.4-.4V18H9.9c-.2 0-.4-.2-.4-.4v-2.4c0-.2.2-.4.4-.4h4.4v-4.4c0-.2.2-.4.4-.4H17c.2 0 .4.2.4.4v4.4h4.4c.2 0 .4.2.4.4v2.4z"},null,-1),n=[s];function r(a,h){return e(),c("svg",o,[...n])}const d={render:r};export{d as default,r as render};
1
+ import{o as e,c,a as t}from"./index-6716899e.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},s=t("path",{d:"M19.2 2.6H6.1V29h19.8V9.3l-6.7-6.7zm3 15c0 .2-.2.4-.4.4h-4.4v4.4c0 .2-.2.4-.4.4h-2.4c-.2 0-.4-.2-.4-.4V18H9.9c-.2 0-.4-.2-.4-.4v-2.4c0-.2.2-.4.4-.4h4.4v-4.4c0-.2.2-.4.4-.4H17c.2 0 .4.2.4.4v4.4h4.4c.2 0 .4.2.4.4v2.4z"},null,-1),n=[s];function r(a,h){return e(),c("svg",o,[...n])}const d={render:r};export{d as default,r as render};
@@ -1 +1 @@
1
- import{o as e,c,a as t}from"./index-ba73bda8.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},s=t("path",{d:"M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20H0zm22.8 11.2c0 .3-.2.5-.5.5h-5.2v5.2c0 .3-.2.5-.5.5h-2.8c-.3 0-.5-.2-.5-.5v-5.2H8.1c-.3 0-.5-.2-.5-.5v-2.8c0-.3.2-.5.5-.5h5.2v-5.2c0-.3.2-.5.5-.5h2.8c.3 0 .5.2.5.5v5.2h5.2c.3 0 .5.2.5.5v2.8z"},null,-1),r=[s];function h(n,a){return e(),c("svg",o,[...r])}const d={render:h};export{d as default,h as render};
1
+ import{o as e,c,a as t}from"./index-6716899e.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},s=t("path",{d:"M29 6H16l-1-2H4L2 8h28zM0 10l2 20h28l2-20H0zm22.8 11.2c0 .3-.2.5-.5.5h-5.2v5.2c0 .3-.2.5-.5.5h-2.8c-.3 0-.5-.2-.5-.5v-5.2H8.1c-.3 0-.5-.2-.5-.5v-2.8c0-.3.2-.5.5-.5h5.2v-5.2c0-.3.2-.5.5-.5h2.8c.3 0 .5.2.5.5v5.2h5.2c.3 0 .5.2.5.5v2.8z"},null,-1),r=[s];function h(n,a){return e(),c("svg",o,[...r])}const d={render:h};export{d as default,h as render};
@@ -1 +1 @@
1
- import{o as e,c as o,a as t}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},c=t("path",{d:"M25.3 8.56 17.88 16l7.44 7.44-1.86 1.87L16 17.9l-7.44 7.4-1.86-1.85L14.12 16 6.68 8.56 8.55 6.7 16 14.12l7.44-7.44z"},null,-1),n=[c];function r(a,l){return e(),o("svg",s,[...n])}const _={render:r};export{_ as default,r as render};
1
+ import{o as e,c as o,a as t}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},c=t("path",{d:"M25.3 8.56 17.88 16l7.44 7.44-1.86 1.87L16 17.9l-7.44 7.4-1.86-1.85L14.12 16 6.68 8.56 8.55 6.7 16 14.12l7.44-7.44z"},null,-1),n=[c];function r(a,l){return e(),o("svg",s,[...n])}const _={render:r};export{_ as default,r as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},a=o("path",{d:"M24.27 3.2H6.4a3.2 3.2 0 0 0-3.2 3.2v19.2a3.2 3.2 0 0 0 3.2 3.2h19.2a3.2 3.2 0 0 0 3.2-3.2V8.2l-4.53-5zm-1.87 9.6c0 .88-.72 1.6-1.6 1.6h-9.6a1.6 1.6 0 0 1-1.6-1.6v-8h12.8v8zm-1.6-6.4h-3.2v6.4h3.2V6.4z"},null,-1),c=[a];function n(r,h){return e(),t("svg",s,[...c])}const l={render:n};export{l as default,n as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},a=o("path",{d:"M24.27 3.2H6.4a3.2 3.2 0 0 0-3.2 3.2v19.2a3.2 3.2 0 0 0 3.2 3.2h19.2a3.2 3.2 0 0 0 3.2-3.2V8.2l-4.53-5zm-1.87 9.6c0 .88-.72 1.6-1.6 1.6h-9.6a1.6 1.6 0 0 1-1.6-1.6v-8h12.8v8zm-1.6-6.4h-3.2v6.4h3.2V6.4z"},null,-1),c=[a];function n(r,h){return e(),t("svg",s,[...c])}const l={render:n};export{l as default,n as render};
@@ -1 +1 @@
1
- import{o as c,c as s,a as e}from"./index-ba73bda8.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 30 30"},t=e("path",{d:"M23 25.9c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3c-.3 0-.6.1-.8.3-.2.2-.3.5-.3.8s.1.6.3.8c.2.2.5.3.8.3.3 0 .6-.1.8-.3.2-.3.3-.5.3-.8zm4.6 0c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3c-.3 0-.6.1-.8.3-.2.2-.3.5-.3.8s.1.6.3.8c.2.2.5.3.8.3.3 0 .6-.1.8-.3.2-.3.3-.5.3-.8zm2.3-4v5.7c0 .5-.2.9-.5 1.2-.3.3-.7.5-1.2.5H1.9c-.5 0-.9-.2-1.2-.5s-.5-.7-.5-1.2v-5.7c0-.5.2-.9.5-1.2.3-.3.7-.5 1.2-.5h8.3l2.4 2.4c.7.7 1.5 1 2.4 1 .9 0 1.7-.3 2.4-1l2.4-2.4h8.3c.5 0 .9.2 1.2.5.4.3.6.7.6 1.2zm-5.8-10.2c.2.5.1.9-.3 1.3l-8 8c-.2.2-.5.3-.8.3-.3 0-.6-.1-.8-.3l-8-8c-.4-.3-.5-.8-.3-1.3S6.5 11 7 11h4.6V3c0-.3.1-.6.3-.8s.5-.3.8-.3h4.6c.3 0 .6.1.8.3s.3.5.3.8v8H23c.5 0 .8.2 1.1.7z"},null,-1),n=[t];function a(l,r){return c(),s("svg",o,[...n])}const h={render:a};export{h as default,a as render};
1
+ import{o as c,c as s,a as e}from"./index-6716899e.js";const o={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 30 30"},t=e("path",{d:"M23 25.9c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3c-.3 0-.6.1-.8.3-.2.2-.3.5-.3.8s.1.6.3.8c.2.2.5.3.8.3.3 0 .6-.1.8-.3.2-.3.3-.5.3-.8zm4.6 0c0-.3-.1-.6-.3-.8s-.5-.3-.8-.3c-.3 0-.6.1-.8.3-.2.2-.3.5-.3.8s.1.6.3.8c.2.2.5.3.8.3.3 0 .6-.1.8-.3.2-.3.3-.5.3-.8zm2.3-4v5.7c0 .5-.2.9-.5 1.2-.3.3-.7.5-1.2.5H1.9c-.5 0-.9-.2-1.2-.5s-.5-.7-.5-1.2v-5.7c0-.5.2-.9.5-1.2.3-.3.7-.5 1.2-.5h8.3l2.4 2.4c.7.7 1.5 1 2.4 1 .9 0 1.7-.3 2.4-1l2.4-2.4h8.3c.5 0 .9.2 1.2.5.4.3.6.7.6 1.2zm-5.8-10.2c.2.5.1.9-.3 1.3l-8 8c-.2.2-.5.3-.8.3-.3 0-.6-.1-.8-.3l-8-8c-.4-.3-.5-.8-.3-1.3S6.5 11 7 11h4.6V3c0-.3.1-.6.3-.8s.5-.3.8-.3h4.6c.3 0 .6.1.8.3s.3.5.3.8v8H23c.5 0 .8.2 1.1.7z"},null,-1),n=[t];function a(l,r){return c(),s("svg",o,[...n])}const h={render:a};export{h as default,a as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const s={xmlns:"http://www.w3.org/2000/svg",width:"448",height:"448",viewBox:"-136 0 448 448"},c=o("path",{d:"M128 312v56q0 6.5-4.75 11.25T112 384H48q-6.5 0-11.25-4.75T32 368v-56q0-6.5 4.75-11.25T48 296h64q6.5 0 11.25 4.75T128 312zm7.5-264-7 192q-.25 6.5-5.13 11.25T112 256H48q-6.5 0-11.38-4.75T31.5 240l-7-192q-.25-6.5 4.38-11.25T40 32h80q6.5 0 11.13 4.75T135.5 48z"},null,-1),n=[c];function a(r,h){return e(),t("svg",s,[...n])}const i={render:a};export{i as default,a as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const s={xmlns:"http://www.w3.org/2000/svg",width:"448",height:"448",viewBox:"-136 0 448 448"},c=o("path",{d:"M128 312v56q0 6.5-4.75 11.25T112 384H48q-6.5 0-11.25-4.75T32 368v-56q0-6.5 4.75-11.25T48 296h64q6.5 0 11.25 4.75T128 312zm7.5-264-7 192q-.25 6.5-5.13 11.25T112 256H48q-6.5 0-11.38-4.75T31.5 240l-7-192q-.25-6.5 4.38-11.25T40 32h80q6.5 0 11.13 4.75T135.5 48z"},null,-1),n=[c];function a(r,h){return e(),t("svg",s,[...n])}const i={render:a};export{i as default,a as render};
@@ -1 +1 @@
1
- import{o as e,c,a as s}from"./index-ba73bda8.js";const t={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -2 36 36"},o=s("path",{d:"M29.715 16c-1.696-2.625-4.018-4.875-6.804-6.304A7.938 7.938 0 0 1 24 13.714c0 4.411-3.589 8-8 8s-8-3.589-8-8c0-1.411.375-2.804 1.089-4.018C6.303 11.125 3.982 13.375 2.285 16c3.054 4.714 7.982 8 13.714 8s10.661-3.286 13.714-8zM16.858 9.143a.87.87 0 0 0-.857-.857c-2.982 0-5.429 2.446-5.429 5.429 0 .464.393.857.857.857s.857-.393.857-.857c0-2.036 1.679-3.714 3.714-3.714a.87.87 0 0 0 .857-.857zM32 16c0 .446-.143.857-.357 1.232-3.286 5.411-9.304 9.054-15.643 9.054S3.643 22.625.357 17.232C.143 16.857 0 16.446 0 16s.143-.857.357-1.232C3.643 9.375 9.661 5.714 16 5.714s12.357 3.661 15.643 9.054c.214.375.357.786.357 1.232z"},null,-1),a=[o];function n(r,d){return e(),c("svg",t,[...a])}const l={render:n};export{l as default,n as render};
1
+ import{o as e,c,a as s}from"./index-6716899e.js";const t={xmlns:"http://www.w3.org/2000/svg",viewBox:"-2 -2 36 36"},o=s("path",{d:"M29.715 16c-1.696-2.625-4.018-4.875-6.804-6.304A7.938 7.938 0 0 1 24 13.714c0 4.411-3.589 8-8 8s-8-3.589-8-8c0-1.411.375-2.804 1.089-4.018C6.303 11.125 3.982 13.375 2.285 16c3.054 4.714 7.982 8 13.714 8s10.661-3.286 13.714-8zM16.858 9.143a.87.87 0 0 0-.857-.857c-2.982 0-5.429 2.446-5.429 5.429 0 .464.393.857.857.857s.857-.393.857-.857c0-2.036 1.679-3.714 3.714-3.714a.87.87 0 0 0 .857-.857zM32 16c0 .446-.143.857-.357 1.232-3.286 5.411-9.304 9.054-15.643 9.054S3.643 22.625.357 17.232C.143 16.857 0 16.446 0 16s.143-.857.357-1.232C3.643 9.375 9.661 5.714 16 5.714s12.357 3.661 15.643 9.054c.214.375.357.786.357 1.232z"},null,-1),a=[o];function n(r,d){return e(),c("svg",t,[...a])}const l={render:n};export{l as default,n as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const c={xmlns:"http://www.w3.org/2000/svg",viewBox:"-12 -12 512 512"},s=o("path",{d:"M480 416 355.44 291.44C373.22 262.4 384 228.58 384 192 384 85.98 298 0 192 0 85.98 0 0 85.98 0 192c0 106 85.98 192 192 192 36.58 0 70.4-10.78 99.44-28.5L416 480c8.75 8.75 23.25 8.7 32 0l32-32a22.8 22.8 0 0 0 0-32zm-288-96c-70.7 0-128-57.3-128-128S121.3 64 192 64s128 57.3 128 128-57.3 128-128 128z"},null,-1),n=[s];function a(r,d){return e(),t("svg",c,[...n])}const _={render:a};export{_ as default,a as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const c={xmlns:"http://www.w3.org/2000/svg",viewBox:"-12 -12 512 512"},s=o("path",{d:"M480 416 355.44 291.44C373.22 262.4 384 228.58 384 192 384 85.98 298 0 192 0 85.98 0 0 85.98 0 192c0 106 85.98 192 192 192 36.58 0 70.4-10.78 99.44-28.5L416 480c8.75 8.75 23.25 8.7 32 0l32-32a22.8 22.8 0 0 0 0-32zm-288-96c-70.7 0-128-57.3-128-128S121.3 64 192 64s128 57.3 128 128-57.3 128-128 128z"},null,-1),n=[s];function a(r,d){return e(),t("svg",c,[...n])}const _={render:a};export{_ as default,a as render};
@@ -1 +1 @@
1
- import{o as e,c as t,a as o}from"./index-ba73bda8.js";const h={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},s=o("path",{d:"M18.7 6.7h6.6v6.6h-2.6v-4h-4V6.7zm4 16v-4h2.6v6.6h-6.6v-2.6h4zm-16-9.4V6.7h6.6v2.6h-4v4H6.7zm2.6 5.4v4h4v2.6H6.7v-6.6h2.6z"},null,-1),c=[s];function n(r,v){return e(),t("svg",h,[...c])}const l={render:n};export{l as default,n as render};
1
+ import{o as e,c as t,a as o}from"./index-6716899e.js";const h={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},s=o("path",{d:"M18.7 6.7h6.6v6.6h-2.6v-4h-4V6.7zm4 16v-4h2.6v6.6h-6.6v-2.6h4zm-16-9.4V6.7h6.6v2.6h-4v4H6.7zm2.6 5.4v4h4v2.6H6.7v-6.6h2.6z"},null,-1),c=[s];function n(r,v){return e(),t("svg",h,[...c])}const l={render:n};export{l as default,n as render};
@@ -1 +1 @@
1
- import{o as t,c as e,a as c}from"./index-ba73bda8.js";const o={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512"},s=c("path",{d:"M256 6.3C114.6 6.3 0 121 0 262.3c0 113 73.4 209 175 243 13 2.3 17.6-5.6 17.6-12.4l-.4-48C121 460.5 106 415 106 415c-11.7-29.5-28.5-37.4-28.5-37.4-23.2-16 1.8-15.6 1.8-15.6 25.7 1.8 39.2 26.4 39.2 26.4 23 39.2 60 27.8 74.5 21.3 2.3-16.5 9-27.8 16.3-34.2C152.3 369 92.6 347 92.6 249c0-28 10-50.8 26.4-68.8-2.6-6.4-11.4-32.5 2.5-67.7 0 0 21.5-7 70.4 26.2 20-5.6 42-8.5 64-8.6 21.3.7 43.2 3 64 9 49-33 70-26 70-26 14 35.3 5 61.4 2.4 67.8 16.3 18 26.2 40.8 26.2 68.7 0 98.4-60 120-117 126.4 9.2 8 17.4 23.4 17.4 47.3l-.2 70.2c0 6.6 4.7 14.6 17.7 12 101.7-34 175-129.7 175-243C512 121 397.5 6 256 6z"},null,-1),n=[s];function r(a,h){return t(),e("svg",o,[...n])}const l={render:r};export{l as default,r as render};
1
+ import{o as t,c as e,a as c}from"./index-6716899e.js";const o={xmlns:"http://www.w3.org/2000/svg",width:"512",height:"512"},s=c("path",{d:"M256 6.3C114.6 6.3 0 121 0 262.3c0 113 73.4 209 175 243 13 2.3 17.6-5.6 17.6-12.4l-.4-48C121 460.5 106 415 106 415c-11.7-29.5-28.5-37.4-28.5-37.4-23.2-16 1.8-15.6 1.8-15.6 25.7 1.8 39.2 26.4 39.2 26.4 23 39.2 60 27.8 74.5 21.3 2.3-16.5 9-27.8 16.3-34.2C152.3 369 92.6 347 92.6 249c0-28 10-50.8 26.4-68.8-2.6-6.4-11.4-32.5 2.5-67.7 0 0 21.5-7 70.4 26.2 20-5.6 42-8.5 64-8.6 21.3.7 43.2 3 64 9 49-33 70-26 70-26 14 35.3 5 61.4 2.4 67.8 16.3 18 26.2 40.8 26.2 68.7 0 98.4-60 120-117 126.4 9.2 8 17.4 23.4 17.4 47.3l-.2 70.2c0 6.6 4.7 14.6 17.7 12 101.7-34 175-129.7 175-243C512 121 397.5 6 256 6z"},null,-1),n=[s];function r(a,h){return t(),e("svg",o,[...n])}const l={render:r};export{l as default,r as render};