Compare commits
16 Commits
acfc3b44dd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9f05a6dbf | ||
|
|
0d93cfd874 | ||
|
|
20c1e9f733 | ||
|
|
f99cfb9a20 | ||
|
|
202688e786 | ||
|
|
a0c1cc3f71 | ||
|
|
55b496f585 | ||
|
|
fa139208a2 | ||
|
|
e28e885e66 | ||
|
|
27614f695f | ||
|
|
f80565f868 | ||
|
|
b503c0adfb | ||
|
|
f2f63d32e5 | ||
|
|
a508e3cefd | ||
| 3f79614850 | |||
| 4e9eafcec5 |
@@ -3,7 +3,7 @@
|
||||
[Website](https://gurted.com/) | [Docs](https://docs.gurted.com/) | [License](LICENSE) | [YouTube video](https://www.youtube.com)
|
||||
|
||||
Gurted is an ecosystem similar to the World Wide Web, it features:
|
||||
- ⚡ A custom protocol (TCP-based) named `GURT://` with mandatory TLS security with a [spec](docs.gurted.com)
|
||||
- ⚡ A custom protocol (TCP-based) named `lw://` with mandatory TLS security with a [spec](docs.gurted.com)
|
||||
- 🌐 A custom **wayfinder** (browser) written in Rust and GDScript with [Godot](https://godotengine.org/)
|
||||
- 📄 A custom engine for HTML, CSS, and ***Lua*** (no JavaScript)
|
||||
- 🏷️ A custom **DNS** that allows users to create domains with TLDs such as `.based`, `.aura`, `.twin`, and many more
|
||||
@@ -16,7 +16,7 @@ Gurted is an ecosystem similar to the World Wide Web, it features:
|
||||
# File structure
|
||||
- `/dns` - The **DNS** (Domain Name System)
|
||||
- `/docs` - The **documentation** at https://docs.gurted.com
|
||||
- `/flumi` - The **wayfinder** Flumi, used to view gurt:// sites
|
||||
- `/flumi` - The **wayfinder** Flumi, used to view lw:// sites
|
||||
- `/protocol` - All protocol related things
|
||||
- `/protocol/library` - The Rust protocol implementation (client + server)
|
||||
- `/protocol/gdextension` - The Godot extension for GURT protocol (uses Rust library, used in Flumi)
|
||||
|
||||
283
SETUP_GUIDE.md
Normal file
283
SETUP_GUIDE.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# Gurted生态系统搭建指南
|
||||
|
||||
本指南将帮助您完整搭建Gurted生态系统的所有组件,使其正常运行。
|
||||
|
||||
## 1. 环境准备
|
||||
|
||||
### 1.1 安装必要的工具和依赖
|
||||
|
||||
```bash
|
||||
# 安装Rust (如果尚未安装)
|
||||
choco install rustup
|
||||
rustup default stable
|
||||
|
||||
# 安装PostgreSQL (用于DNS和搜索引擎)
|
||||
choco install postgresql
|
||||
|
||||
# 安装mkcert (用于开发环境的TLS证书)
|
||||
choco install mkcert
|
||||
|
||||
# 安装Godot 4.x (用于运行和开发Flumi浏览器)
|
||||
# 访问 https://godotengine.org/download 下载并安装
|
||||
|
||||
# 安装Node.js和npm (用于前端开发)
|
||||
choco install nodejs
|
||||
```
|
||||
|
||||
### 1.2 安装本地CA证书 (仅开发环境)
|
||||
|
||||
```bash
|
||||
mkcert -install
|
||||
```
|
||||
|
||||
## 2. DNS系统搭建
|
||||
|
||||
### 2.1 配置PostgreSQL数据库
|
||||
|
||||
```bash
|
||||
# 启动PostgreSQL服务
|
||||
pg_ctl -D "C:\Program Files\PostgreSQL\版本\data" start
|
||||
|
||||
# 创建数据库和用户
|
||||
psql -U postgres
|
||||
CREATE DATABASE gurt_dns;
|
||||
CREATE USER gurt_user WITH PASSWORD 'your_password';
|
||||
GRANT ALL PRIVILEGES ON DATABASE gurt_dns TO gurt_user;
|
||||
\q
|
||||
```
|
||||
|
||||
### 2.2 配置DNS服务器
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\dns
|
||||
cp config.template.toml config.toml
|
||||
```
|
||||
|
||||
编辑`config.toml`文件,配置数据库连接等信息:
|
||||
|
||||
```toml
|
||||
[database]
|
||||
url = "postgres://gurt_user:your_password@localhost/gurt_dns"
|
||||
|
||||
[server]
|
||||
address = "127.0.0.1"
|
||||
port = 4877
|
||||
```
|
||||
|
||||
### 2.3 运行DNS服务器
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\dns
|
||||
cargo run
|
||||
```
|
||||
|
||||
DNS服务器现在应该运行在http://127.0.0.1:4877
|
||||
|
||||
## 3. GurtCA证书颁发机构搭建
|
||||
|
||||
### 3.1 编译GurtCA
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\gurtca
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
### 3.2 获取CA证书
|
||||
|
||||
要使用GurtCA,首先需要获取CA证书。注意:GurtCA工具需要使用lw://协议的URL:
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\gurtca\target\release
|
||||
# 使用默认的lw://dns.root CA URL
|
||||
./gurtca get-ca --output ./ca.crt
|
||||
|
||||
# 或者指定自定义的CA URL
|
||||
./gurtca get-ca --ca-url lw://your-ca-server --output ./ca.crt
|
||||
```
|
||||
|
||||
重要说明:
|
||||
- GurtCA工具需要使用lw://协议的URL(不支持http://或https://)
|
||||
- 默认CA URL是lw://dns.root
|
||||
- 如果连接失败,工具会尝试通过HTTP引导服务器(默认是http://10.0.0.138:8876)获取CA证书
|
||||
- 您可能需要确保本地运行的DNS服务器可以解析这些地址
|
||||
|
||||
### 3.3 请求域名证书
|
||||
|
||||
要为您的域名请求证书:
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\gurtca\target\release
|
||||
./gurtca request yourdomain.web --output ./certs
|
||||
```
|
||||
|
||||
按照提示完成DNS挑战验证。
|
||||
|
||||
## 4. GURT协议服务器设置
|
||||
|
||||
### 4.1 生成TLS证书
|
||||
|
||||
#### 开发环境:
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\cli
|
||||
mkcert localhost 127.0.0.1 ::1
|
||||
```
|
||||
|
||||
#### 生产环境:
|
||||
|
||||
使用GurtCA获取证书:
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\gurtca\target\release
|
||||
./gurtca request yourdomain.web --output ./certs
|
||||
```
|
||||
|
||||
按照提示完成DNS验证挑战。
|
||||
|
||||
### 4.2 配置Gurty CLI
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\cli
|
||||
cp gurty.template.toml gurty.toml
|
||||
```
|
||||
|
||||
编辑`gurty.toml`文件以适应您的环境。
|
||||
|
||||
### 4.3 启动GURT服务器
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\cli
|
||||
# 使用自签名证书(开发环境)
|
||||
gurty serve --cert localhost+2.pem --key localhost+2-key.pem --config gurty.toml
|
||||
|
||||
# 或使用CA颁发的证书(生产环境)
|
||||
gurty serve --cert ./certs/yourdomain.web.crt --key ./certs/yourdomain.web.key --config gurty.toml
|
||||
```
|
||||
|
||||
## 5. 搜索引擎搭建
|
||||
|
||||
### 5.1 配置搜索引擎数据库
|
||||
|
||||
```bash
|
||||
psql -U postgres
|
||||
CREATE DATABASE gurt_search;
|
||||
GRANT ALL PRIVILEGES ON DATABASE gurt_search TO gurt_user;
|
||||
\q
|
||||
```
|
||||
|
||||
### 5.2 配置搜索引擎
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\search-engine
|
||||
cp config.template.toml config.toml
|
||||
```
|
||||
|
||||
编辑`config.toml`文件,配置数据库连接和其他参数:
|
||||
|
||||
```toml
|
||||
[database]
|
||||
url = "postgres://gurt_user:your_password@localhost/gurt_search"
|
||||
|
||||
[server]
|
||||
address = "127.0.0.1"
|
||||
port = 4879
|
||||
cert_path = "certs/t.crt"
|
||||
key_path = "certs/t.key"
|
||||
```
|
||||
|
||||
### 5.3 运行搜索引擎
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\search-engine
|
||||
cargo run
|
||||
```
|
||||
|
||||
搜索引擎现在应该运行在lw://127.0.0.1:4879
|
||||
|
||||
## 6. Flumi浏览器设置
|
||||
|
||||
### 6.1 编译和运行Flumi
|
||||
|
||||
1. 启动Godot引擎
|
||||
2. 导入`d:\Projects\Rust\leonwww\flumi`项目
|
||||
3. 构建并运行项目
|
||||
|
||||
### 6.2 配置Flumi连接到本地服务器
|
||||
|
||||
在Flumi浏览器中,您可以访问以下地址测试各个组件:
|
||||
- DNS服务器: http://127.0.0.1:4877
|
||||
- GURT服务器: lw://localhost:4878
|
||||
- 搜索引擎: lw://127.0.0.1:4879
|
||||
|
||||
## 7. 开发流程
|
||||
|
||||
如果您修改了协议库或GDExtension,需要重新构建GDExtension:
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\protocol\gdextension
|
||||
./build.sh
|
||||
cp -r ./addon d:\Projects\Rust\leonwww\flumi\addons\gurt-protocol\
|
||||
```
|
||||
|
||||
## 8. 完整生态系统的组件关系
|
||||
|
||||
- **DNS系统**: 管理域名解析,允许用户注册自定义TLD域名
|
||||
- **GurtCA**: 颁发TLS证书,确保通信安全
|
||||
- **GURT协议库**: 提供协议实现,被CLI和浏览器使用
|
||||
- **Gurty CLI**: 用于设置和管理GURT服务器
|
||||
- **Flumi浏览器**: 访问GURT网络的客户端工具
|
||||
- **Ringle搜索引擎**: 索引和搜索GURT网络内容
|
||||
|
||||
## 9. 测试
|
||||
|
||||
使用`tests`目录中的示例文件来测试GURT协议的各种功能:
|
||||
|
||||
```bash
|
||||
# 在GURT服务器中提供测试文件
|
||||
cd d:\Projects\Rust\leonwww\protocol\cli
|
||||
gurty serve --root ../tests --cert localhost+2.pem --key localhost+2-key.pem
|
||||
```
|
||||
|
||||
然后在Flumi浏览器中访问:lw://localhost:4878/index.html
|
||||
|
||||
## 10. 部署建议
|
||||
|
||||
对于生产环境部署,建议使用Docker容器:
|
||||
|
||||
### DNS服务器部署
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\dns
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 搜索引擎部署
|
||||
|
||||
```bash
|
||||
cd d:\Projects\Rust\leonwww\search-engine
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 11. 常见问题解答
|
||||
|
||||
### 11.1 TLS证书问题
|
||||
|
||||
- 确保正确安装了CA证书
|
||||
- 检查证书路径是否正确配置
|
||||
- 验证证书是否在有效期内
|
||||
|
||||
### 11.2 数据库连接问题
|
||||
|
||||
- 确认PostgreSQL服务正在运行
|
||||
- 检查数据库连接字符串是否正确
|
||||
- 验证用户权限设置是否正确
|
||||
|
||||
### 11.3 网络连接问题
|
||||
|
||||
- 检查防火墙设置
|
||||
- 验证端口是否已正确配置
|
||||
- 确保所有组件使用相同的协议版本
|
||||
|
||||
---
|
||||
|
||||
按照本指南,您应该能够成功搭建完整的Gurted生态系统。如果遇到任何问题,请参考各组件的README文件获取更详细的信息。
|
||||
568
dns/Cargo.lock
generated
568
dns/Cargo.lock
generated
@@ -115,26 +115,6 @@ version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "2.0.0"
|
||||
@@ -225,7 +205,7 @@ version = "0.69.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
@@ -242,12 +222,6 @@ dependencies = [
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.2"
|
||||
@@ -282,12 +256,6 @@ version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
@@ -300,37 +268,6 @@ version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d07aa9a93b00c76f71bc35d598bed923f6d4f3a9ca5c24b7737ae1a292841c0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-platform"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.33"
|
||||
@@ -468,33 +405,12 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "command_attr"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fcc89439e1bb4e19050a9586a767781a3060000d2f3296fd2a40597ad9421c5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.10.1"
|
||||
@@ -535,24 +451,6 @@ version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
@@ -599,20 +497,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hashbrown",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.9.0"
|
||||
@@ -637,7 +521,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -738,15 +621,6 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "etcetera"
|
||||
version = "0.8.0"
|
||||
@@ -770,16 +644,6 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.11.1"
|
||||
@@ -927,15 +791,6 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -973,7 +828,7 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "gurtlib"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
@@ -984,7 +839,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"thiserror 1.0.61",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.2",
|
||||
"tokio-rustls",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
@@ -1180,20 +1035,6 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"hyper",
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.60"
|
||||
@@ -1246,12 +1087,6 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.12"
|
||||
@@ -1332,12 +1167,6 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "levenshtein"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
@@ -1366,7 +1195,7 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
@@ -1445,21 +1274,6 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mini-moka"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-utils",
|
||||
"dashmap",
|
||||
"skeptic",
|
||||
"smallvec",
|
||||
"tagptr",
|
||||
"triomphe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@@ -1608,7 +1422,7 @@ version = "0.10.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
@@ -1814,17 +1628,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
@@ -1870,7 +1673,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1913,50 +1716,6 @@ version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http 0.2.12",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"hyper-rustls",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls 0.21.12",
|
||||
"rustls-pemfile 1.0.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
"tokio-util",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"webpki-roots 0.25.4",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.8"
|
||||
@@ -2010,7 +1769,7 @@ version = "0.38.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
@@ -2023,26 +1782,11 @@ version = "0.21.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"rustls-webpki 0.101.7",
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki 0.102.8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.31"
|
||||
@@ -2107,17 +1851,6 @@ dependencies = [
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.4"
|
||||
@@ -2142,15 +1875,6 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.27"
|
||||
@@ -2182,24 +1906,14 @@ dependencies = [
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secrecy"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c"
|
||||
dependencies = [
|
||||
"bitflags 2.9.2",
|
||||
"core-foundation 0.10.1",
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
@@ -2215,15 +1929,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
@@ -2233,15 +1938,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_cow"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7bbbec7196bfde255ab54b65e34087c0849629280028238e67ee25d6a4b7da"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
@@ -2285,43 +1981,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serenity"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d72ec4323681bf9a3cabe40fd080abc2435859b502a1b5aa9bf693f125bfa76"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.9.2",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"command_attr",
|
||||
"dashmap",
|
||||
"flate2",
|
||||
"futures",
|
||||
"fxhash",
|
||||
"levenshtein",
|
||||
"mime_guess",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"reqwest",
|
||||
"secrecy",
|
||||
"serde",
|
||||
"serde_cow",
|
||||
"serde_json",
|
||||
"static_assertions",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tracing",
|
||||
"typemap_rev",
|
||||
"typesize",
|
||||
"url",
|
||||
"uwl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
@@ -2381,21 +2040,6 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skeptic"
|
||||
version = "0.13.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8"
|
||||
dependencies = [
|
||||
"bytecount",
|
||||
"cargo_metadata",
|
||||
"error-chain",
|
||||
"glob",
|
||||
"pulldown-cmark",
|
||||
"tempfile",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
@@ -2510,7 +2154,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
"webpki-roots 0.25.4",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2560,7 +2204,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
@@ -2604,7 +2248,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.9.2",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"crc",
|
||||
@@ -2661,12 +2305,6 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "stringprep"
|
||||
version = "0.1.5"
|
||||
@@ -2712,39 +2350,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation 0.9.4",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tagptr"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.12.0"
|
||||
@@ -2894,27 +2499,6 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||
dependencies = [
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
|
||||
dependencies = [
|
||||
"rustls 0.22.4",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.2"
|
||||
@@ -2944,12 +2528,8 @@ checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"rustls 0.22.4",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.25.0",
|
||||
"tungstenite",
|
||||
"webpki-roots 0.26.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3037,12 +2617,6 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triomphe"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85"
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.5"
|
||||
@@ -3062,55 +2636,18 @@ dependencies = [
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"rustls 0.22.4",
|
||||
"rustls-pki-types",
|
||||
"sha1",
|
||||
"thiserror 1.0.61",
|
||||
"url",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typemap_rev"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74b08b0c1257381af16a5c3605254d529d3e7e109f3c62befc5d168968192998"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "typesize"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da66c62c5b7017a2787e77373c03e6a5aafde77a73bff1ff96e91cd2e128179"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dashmap",
|
||||
"hashbrown",
|
||||
"mini-moka",
|
||||
"parking_lot",
|
||||
"secrecy",
|
||||
"serde_json",
|
||||
"time",
|
||||
"typesize-derive",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typesize-derive"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "536b6812192bda8551cfa0e52524e328c6a951b48e66529ee4522d6c721243d6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.8.1"
|
||||
@@ -3177,7 +2714,6 @@ dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3207,12 +2743,6 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uwl"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4bf03e0ca70d626ecc4ba6b0763b934b6f2976e8c744088bb3c1d646fbb1ad0"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
@@ -3225,16 +2755,6 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
@@ -3310,18 +2830,6 @@ dependencies = [
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.92"
|
||||
@@ -3351,53 +2859,12 @@ version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
|
||||
dependencies = [
|
||||
"webpki-roots 1.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webx_dns"
|
||||
version = "0.0.1"
|
||||
@@ -3421,7 +2888,6 @@ dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serenity",
|
||||
"sha2",
|
||||
"sqlx",
|
||||
"tokio",
|
||||
@@ -3649,16 +3115,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.34"
|
||||
|
||||
@@ -9,10 +9,9 @@ toml = "0.8.13"
|
||||
regex = "1.10.4"
|
||||
jsonwebtoken = "9.2"
|
||||
bcrypt = "0.15"
|
||||
serenity = { version = "0.12", features = ["client", "gateway", "rustls_backend", "model"] }
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
colored = "2.1.0"
|
||||
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid", "migrate", "json"] }
|
||||
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "mysql", "chrono", "uuid", "migrate", "json"] }
|
||||
anyhow = "1.0.86"
|
||||
futures = "0.3.30"
|
||||
macros-rs = "1.2.1"
|
||||
|
||||
8
dns/cleanup_migration.sql
Normal file
8
dns/cleanup_migration.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
-- 清理部分应用的迁移记录
|
||||
DELETE FROM _sqlx_migrations WHERE version = 1;
|
||||
|
||||
-- 可选:也可以删除所有迁移记录,从头开始
|
||||
-- TRUNCATE TABLE _sqlx_migrations;
|
||||
|
||||
-- 显示清理后的迁移表状态
|
||||
SELECT * FROM _sqlx_migrations;
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
[server]
|
||||
address = "127.0.0.1"
|
||||
port = 8080
|
||||
port = 8085
|
||||
|
||||
[server.database]
|
||||
url = "postgresql://username:password@localhost:5432/domains"
|
||||
url = "mysql://root:password@localhost:3306/dns"
|
||||
|
||||
# Maximum number of database connections
|
||||
max_connections = 10
|
||||
@@ -45,12 +45,7 @@ tld_list = [
|
||||
# Words that are not allowed in domain names
|
||||
offensive_words = []
|
||||
|
||||
[discord]
|
||||
# Discord bot token for domain approval notifications
|
||||
bot_token = "your-discord-bot-token-here"
|
||||
|
||||
# Channel ID where domain approval messages will be sent
|
||||
channel_id = 0
|
||||
# Discord bot configuration has been removed
|
||||
|
||||
[auth]
|
||||
# JWT secret key for authentication (change this!)
|
||||
|
||||
@@ -74,7 +74,7 @@ end
|
||||
|
||||
local function loadDomains()
|
||||
print('Loading domains...')
|
||||
local response = fetch('gurt://dns.web/auth/domains?page=1&limit=100', {
|
||||
local response = fetch('lw://dns.root/auth/domains?page=1&limit=100', {
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
}
|
||||
@@ -95,7 +95,7 @@ local function checkAuth()
|
||||
|
||||
if authToken then
|
||||
print('Found auth token, checking validity...')
|
||||
local response = fetch('gurt://dns.web/auth/me', {
|
||||
local response = fetch('lw://dns.root/auth/me', {
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ local renderRecords
|
||||
local function deleteRecord(recordId)
|
||||
print('Deleting DNS record: ' .. recordId)
|
||||
|
||||
local response = fetch('gurt://dns.web/domain/' .. domainName .. '/records/' .. recordId, {
|
||||
local response = fetch('lw://dns.root/domain/' .. domainName .. '/records/' .. recordId, {
|
||||
method = 'DELETE',
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
@@ -57,7 +57,7 @@ end
|
||||
-- Actual implementation
|
||||
loadRecords = function()
|
||||
print('Loading DNS records for: ' .. domainName)
|
||||
local response = fetch('gurt://dns.web/domain/' .. domainName .. '/records', {
|
||||
local response = fetch('lw://dns.root/domain/' .. domainName .. '/records', {
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
}
|
||||
@@ -175,7 +175,7 @@ end
|
||||
|
||||
local function loadDomain()
|
||||
print('Loading domain details for: ' .. domainName)
|
||||
local response = fetch('gurt://dns.web/domain/' .. domainName, {
|
||||
local response = fetch('lw://dns.root/domain/' .. domainName, {
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
}
|
||||
@@ -197,7 +197,7 @@ local function checkAuth()
|
||||
|
||||
if authToken then
|
||||
print('Found auth token, checking validity...')
|
||||
local response = fetch('gurt://dns.web/auth/me', {
|
||||
local response = fetch('lw://dns.root/auth/me', {
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
}
|
||||
@@ -228,7 +228,7 @@ end
|
||||
local function addRecord(type, name, value, ttl)
|
||||
hideError('record-error')
|
||||
|
||||
local response = fetch('gurt://dns.web/domain/' .. domainName .. '/records', {
|
||||
local response = fetch('lw://dns.root/domain/' .. domainName .. '/records', {
|
||||
method = 'POST',
|
||||
headers = {
|
||||
['Content-Type'] = 'application/json',
|
||||
|
||||
@@ -75,7 +75,7 @@ end
|
||||
|
||||
local function loadTLDs()
|
||||
print('Loading available TLDs...')
|
||||
local response = fetch('gurt://dns.web/tlds')
|
||||
local response = fetch('lw://dns.root/tlds')
|
||||
|
||||
if response:ok() then
|
||||
tlds = response:json()
|
||||
@@ -91,7 +91,7 @@ local function checkAuth()
|
||||
|
||||
if authToken then
|
||||
print('Found auth token, checking validity...')
|
||||
local response = fetch('gurt://dns.web/auth/me', {
|
||||
local response = fetch('lw://dns.root/auth/me', {
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
}
|
||||
@@ -127,7 +127,7 @@ local function submitDomain(name, tld)
|
||||
hideError('domain-error')
|
||||
print('Submitting domain: ' .. name .. '.' .. tld)
|
||||
|
||||
local response = fetch('gurt://dns.web/domain', {
|
||||
local response = fetch('lw://dns.root/domain', {
|
||||
method = 'POST',
|
||||
headers = {
|
||||
['Content-Type'] = 'application/json',
|
||||
@@ -157,7 +157,7 @@ end
|
||||
|
||||
local function createInvite()
|
||||
print('Creating invite code...')
|
||||
local response = fetch('gurt://dns.web/auth/invite', {
|
||||
local response = fetch('lw://dns.root/auth/invite', {
|
||||
method = 'POST',
|
||||
headers = {
|
||||
Authorization = 'Bearer ' .. authToken
|
||||
@@ -184,7 +184,7 @@ local function redeemInvite(code)
|
||||
hideError('redeem-error')
|
||||
print('Redeeming invite code: ' .. code)
|
||||
|
||||
local response = fetch('gurt://dns.web/auth/redeem-invite', {
|
||||
local response = fetch('lw://dns.root/auth/redeem-invite', {
|
||||
method = 'POST',
|
||||
headers = {
|
||||
['Content-Type'] = 'application/json',
|
||||
|
||||
@@ -21,7 +21,7 @@ submitBtn:on('submit', function(event)
|
||||
password = password
|
||||
})
|
||||
print(request_body)
|
||||
local url = 'gurt://dns.web/auth/login'
|
||||
local url = 'lw://dns.root/auth/login'
|
||||
local headers = {
|
||||
['Content-Type'] = 'application/json'
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ submitBtn:on('submit', function(event)
|
||||
password = password
|
||||
})
|
||||
|
||||
local url = 'gurt://dns.web/auth/register'
|
||||
local url = 'lw://dns.root/auth/register'
|
||||
local headers = {
|
||||
['Content-Type'] = 'application/json'
|
||||
}
|
||||
|
||||
@@ -1,64 +1,70 @@
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
registrations_remaining INTEGER DEFAULT 3,
|
||||
domain_invite_codes INTEGER DEFAULT 3,
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
||||
CREATE INDEX idx_users_username ON users(username);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS invite_codes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
code VARCHAR(32) UNIQUE NOT NULL,
|
||||
created_by INTEGER REFERENCES users(id),
|
||||
used_by INTEGER REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
used_at TIMESTAMPTZ
|
||||
created_by INTEGER,
|
||||
used_by INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
used_at TIMESTAMP,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id),
|
||||
FOREIGN KEY (used_by) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_invite_codes_code ON invite_codes(code);
|
||||
CREATE INDEX idx_invite_codes_code ON invite_codes(code);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS domain_invite_codes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
code VARCHAR(32) UNIQUE NOT NULL,
|
||||
created_by INTEGER REFERENCES users(id),
|
||||
used_by INTEGER REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
used_at TIMESTAMPTZ
|
||||
created_by INTEGER,
|
||||
used_by INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
used_at TIMESTAMP,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id),
|
||||
FOREIGN KEY (used_by) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_code ON domain_invite_codes(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_created_by ON domain_invite_codes(created_by);
|
||||
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_used_by ON domain_invite_codes(used_by);
|
||||
CREATE INDEX idx_domain_invite_codes_code ON domain_invite_codes(code);
|
||||
CREATE INDEX idx_domain_invite_codes_created_by ON domain_invite_codes(created_by);
|
||||
CREATE INDEX idx_domain_invite_codes_used_by ON domain_invite_codes(used_by);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS domains (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
tld VARCHAR(20) NOT NULL,
|
||||
ip VARCHAR(255) NOT NULL,
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
user_id INTEGER,
|
||||
status VARCHAR(20) DEFAULT 'pending',
|
||||
denial_reason TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(name, tld)
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(name, tld),
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_domains_name_tld ON domains(name, tld);
|
||||
CREATE INDEX IF NOT EXISTS idx_domains_user_id ON domains(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_domains_status ON domains(status);
|
||||
CREATE INDEX idx_domains_name_tld ON domains(name, tld);
|
||||
CREATE INDEX idx_domains_user_id ON domains(user_id);
|
||||
CREATE INDEX idx_domains_status ON domains(status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS dns_records (
|
||||
id SERIAL PRIMARY KEY,
|
||||
domain_id INTEGER NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
|
||||
record_type VARCHAR(10) NOT NULL CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT', 'MX', 'NS', 'SRV')),
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
domain_id INTEGER NOT NULL,
|
||||
record_type VARCHAR(10) NOT NULL,
|
||||
name VARCHAR(255) NOT NULL DEFAULT '@', -- @ for root, or subdomain name
|
||||
value VARCHAR(1000) NOT NULL,
|
||||
ttl INTEGER DEFAULT 3600,
|
||||
priority INTEGER, -- For MX records
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_dns_records_domain_type ON dns_records(domain_id, record_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_dns_records_name ON dns_records(name);
|
||||
CREATE INDEX idx_dns_records_domain_type ON dns_records(domain_id, record_type);
|
||||
CREATE INDEX idx_dns_records_name ON dns_records(name);
|
||||
@@ -1,7 +1,6 @@
|
||||
-- Make IP column optional for domains
|
||||
ALTER TABLE domains ALTER COLUMN ip DROP NOT NULL;
|
||||
ALTER TABLE domains MODIFY COLUMN ip VARCHAR(255) NULL;
|
||||
|
||||
-- Update DNS records constraint to only allow A, AAAA, CNAME, TXT
|
||||
ALTER TABLE dns_records DROP CONSTRAINT IF EXISTS dns_records_record_type_check;
|
||||
ALTER TABLE dns_records ADD CONSTRAINT dns_records_record_type_check
|
||||
CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT'));
|
||||
-- MySQL doesn't support DROP CONSTRAINT IF EXISTS
|
||||
-- MySQL 8.0+ supports CHECK constraints, but we'll use a trigger approach for compatibility
|
||||
@@ -1,10 +1,10 @@
|
||||
-- Re-add NS record support and extend record types
|
||||
ALTER TABLE dns_records DROP CONSTRAINT IF EXISTS dns_records_record_type_check;
|
||||
ALTER TABLE dns_records ADD CONSTRAINT dns_records_record_type_check
|
||||
CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT', 'NS', 'MX'));
|
||||
-- MySQL doesn't support direct DROP CONSTRAINT syntax
|
||||
-- MySQL 8.0+ supports CHECK constraints, but we'll skip adding for compatibility
|
||||
|
||||
-- Add index for efficient NS record lookups during delegation
|
||||
CREATE INDEX IF NOT EXISTS idx_dns_records_ns_lookup ON dns_records(record_type, name) WHERE record_type = 'NS';
|
||||
-- MySQL doesn't support WHERE clause in CREATE INDEX
|
||||
CREATE INDEX idx_dns_records_ns_lookup ON dns_records(record_type, name);
|
||||
|
||||
-- Add index for subdomain resolution optimization
|
||||
CREATE INDEX IF NOT EXISTS idx_dns_records_subdomain_lookup ON dns_records(domain_id, name, record_type);
|
||||
CREATE INDEX idx_dns_records_subdomain_lookup ON dns_records(domain_id, name, record_type);
|
||||
@@ -1,8 +1,9 @@
|
||||
-- Fix record types to remove MX and ensure NS is supported
|
||||
ALTER TABLE dns_records DROP CONSTRAINT IF EXISTS dns_records_record_type_check;
|
||||
ALTER TABLE dns_records ADD CONSTRAINT dns_records_record_type_check
|
||||
CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT', 'NS'));
|
||||
-- MySQL doesn't support DROP CONSTRAINT IF EXISTS syntax
|
||||
-- MySQL 8.0+ supports CHECK constraints, but we'll skip adding for compatibility
|
||||
|
||||
-- Add indexes for efficient DNS lookups if they don't exist
|
||||
CREATE INDEX IF NOT EXISTS idx_dns_records_ns_lookup ON dns_records(record_type, name) WHERE record_type = 'NS';
|
||||
CREATE INDEX IF NOT EXISTS idx_dns_records_subdomain_lookup ON dns_records(domain_id, name, record_type);
|
||||
-- Index already created in migration 003_add_ns_records.sql
|
||||
-- CREATE INDEX idx_dns_records_ns_lookup ON dns_records(record_type, name);
|
||||
-- Index already created in migration 003_add_ns_records.sql
|
||||
-- CREATE INDEX idx_dns_records_subdomain_lookup ON dns_records(domain_id, name, record_type);
|
||||
@@ -1,33 +1,34 @@
|
||||
-- Add certificate challenges table for CA functionality
|
||||
CREATE TABLE IF NOT EXISTS certificate_challenges (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
token VARCHAR(255) UNIQUE NOT NULL,
|
||||
domain VARCHAR(255) NOT NULL,
|
||||
challenge_type VARCHAR(20) NOT NULL CHECK (challenge_type IN ('dns')),
|
||||
challenge_type VARCHAR(20) NOT NULL,
|
||||
verification_data VARCHAR(500) NOT NULL,
|
||||
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'valid', 'invalid', 'expired')),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
expires_at TIMESTAMPTZ NOT NULL
|
||||
status VARCHAR(20) DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_certificate_challenges_token ON certificate_challenges(token);
|
||||
CREATE INDEX IF NOT EXISTS idx_certificate_challenges_domain ON certificate_challenges(domain);
|
||||
CREATE INDEX IF NOT EXISTS idx_certificate_challenges_expires_at ON certificate_challenges(expires_at);
|
||||
CREATE INDEX idx_certificate_challenges_token ON certificate_challenges(token);
|
||||
CREATE INDEX idx_certificate_challenges_domain ON certificate_challenges(domain);
|
||||
CREATE INDEX idx_certificate_challenges_expires_at ON certificate_challenges(expires_at);
|
||||
|
||||
-- Add table to store issued certificates
|
||||
CREATE TABLE IF NOT EXISTS issued_certificates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
domain VARCHAR(255) NOT NULL,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL,
|
||||
certificate_pem TEXT NOT NULL,
|
||||
private_key_pem TEXT NOT NULL,
|
||||
issued_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
serial_number VARCHAR(255) UNIQUE NOT NULL
|
||||
issued_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
revoked_at TIMESTAMP,
|
||||
serial_number VARCHAR(255) UNIQUE NOT NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_issued_certificates_domain ON issued_certificates(domain);
|
||||
CREATE INDEX IF NOT EXISTS idx_issued_certificates_user_id ON issued_certificates(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_issued_certificates_serial ON issued_certificates(serial_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_issued_certificates_expires_at ON issued_certificates(expires_at);
|
||||
CREATE INDEX idx_issued_certificates_domain ON issued_certificates(domain);
|
||||
CREATE INDEX idx_issued_certificates_user_id ON issued_certificates(user_id);
|
||||
CREATE INDEX idx_issued_certificates_serial ON issued_certificates(serial_number);
|
||||
CREATE INDEX idx_issued_certificates_expires_at ON issued_certificates(expires_at);
|
||||
@@ -2,6 +2,24 @@
|
||||
DELETE FROM dns_records WHERE record_type NOT IN ('A', 'AAAA', 'CNAME', 'TXT');
|
||||
|
||||
-- Now apply the constraint
|
||||
ALTER TABLE dns_records DROP CONSTRAINT IF EXISTS dns_records_record_type_check;
|
||||
ALTER TABLE dns_records ADD CONSTRAINT dns_records_record_type_check
|
||||
CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT'));
|
||||
-- MySQL doesn't support DROP CONSTRAINT syntax for CHECK constraints
|
||||
-- ALTER TABLE dns_records DROP CONSTRAINT dns_records_record_type_check;
|
||||
|
||||
-- MySQL doesn't support table-level CHECK constraints, using trigger instead
|
||||
-- Remove DELIMITER commands for compatibility with migration tools
|
||||
|
||||
-- Create trigger for insert without DELIMITER
|
||||
CREATE TRIGGER check_record_type_before_insert
|
||||
BEFORE INSERT ON dns_records
|
||||
FOR EACH ROW
|
||||
IF NEW.record_type NOT IN ('A', 'AAAA', 'CNAME', 'TXT') THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid record type';
|
||||
END IF;
|
||||
|
||||
-- Create trigger for update without DELIMITER
|
||||
CREATE TRIGGER check_record_type_before_update
|
||||
BEFORE UPDATE ON dns_records
|
||||
FOR EACH ROW
|
||||
IF NEW.record_type NOT IN ('A', 'AAAA', 'CNAME', 'TXT') THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid record type';
|
||||
END IF;
|
||||
@@ -1,8 +1,8 @@
|
||||
-- Add table to store CA certificate and key
|
||||
CREATE TABLE IF NOT EXISTS ca_certificates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
ca_cert_pem TEXT NOT NULL,
|
||||
ca_key_pem TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
is_active BOOLEAN DEFAULT TRUE
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
is_active TINYINT(1) DEFAULT 1
|
||||
);
|
||||
@@ -1,2 +1,2 @@
|
||||
-- Add CSR field to certificate challenges
|
||||
ALTER TABLE certificate_challenges ADD COLUMN IF NOT EXISTS csr_pem TEXT;
|
||||
ALTER TABLE certificate_challenges ADD COLUMN csr_pem TEXT;
|
||||
@@ -1,28 +1,21 @@
|
||||
-- Search engine domain crawl status tracking
|
||||
CREATE TABLE IF NOT EXISTS domain_crawl_status (
|
||||
domain_id INTEGER PRIMARY KEY REFERENCES domains(id) ON DELETE CASCADE,
|
||||
last_crawled_at TIMESTAMPTZ,
|
||||
next_crawl_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
crawl_status VARCHAR(20) DEFAULT 'pending' CHECK (crawl_status IN ('pending', 'crawling', 'completed', 'failed', 'disabled')),
|
||||
domain_id INT PRIMARY KEY,
|
||||
last_crawled_at TIMESTAMP,
|
||||
next_crawl_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
crawl_status VARCHAR(20) DEFAULT 'pending',
|
||||
error_message TEXT,
|
||||
pages_found INTEGER DEFAULT 0,
|
||||
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_domain_crawl_status_next_crawl ON domain_crawl_status(next_crawl_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_domain_crawl_status_status ON domain_crawl_status(crawl_status);
|
||||
CREATE INDEX idx_domain_crawl_status_next_crawl ON domain_crawl_status(next_crawl_at);
|
||||
CREATE INDEX idx_domain_crawl_status_status ON domain_crawl_status(crawl_status);
|
||||
|
||||
-- Function to update the updated_at column
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Trigger for updated_at
|
||||
DROP TRIGGER IF EXISTS update_domain_crawl_status_updated_at ON domain_crawl_status;
|
||||
-- MySQL trigger to update updated_at column - simplified without DELIMITER
|
||||
CREATE TRIGGER update_domain_crawl_status_updated_at
|
||||
BEFORE UPDATE ON domain_crawl_status
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
BEFORE UPDATE ON domain_crawl_status
|
||||
FOR EACH ROW
|
||||
SET NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
@@ -3,9 +3,9 @@ mod structs;
|
||||
|
||||
use colored::Colorize;
|
||||
use macros_rs::fmt::{crashln, string};
|
||||
use sqlx::{PgPool, Error};
|
||||
use sqlx::{MySqlPool, Error};
|
||||
use std::fs::write;
|
||||
use structs::{Auth, Database, Discord, Server, Settings};
|
||||
use structs::{Auth, Database, Server, Settings};
|
||||
|
||||
pub use structs::Config;
|
||||
|
||||
@@ -22,16 +22,13 @@ impl Config {
|
||||
address: "127.0.0.1".into(),
|
||||
port: 8080,
|
||||
database: Database {
|
||||
url: "postgresql://username:password@localhost/domains".into(),
|
||||
url: "mysql://root:password@localhost:3306/dns".into(),
|
||||
max_connections: 10,
|
||||
},
|
||||
cert_path: "localhost+2.pem".into(),
|
||||
key_path: "localhost+2-key.pem".into(),
|
||||
},
|
||||
discord: Discord {
|
||||
bot_token: "".into(),
|
||||
channel_id: 0,
|
||||
},
|
||||
// Discord configuration has been removed
|
||||
auth: Auth {
|
||||
jwt_secret: "your-secret-key-here".into(),
|
||||
},
|
||||
@@ -67,13 +64,13 @@ impl Config {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub async fn connect_to_db(&self) -> Result<PgPool, Error> {
|
||||
let pool = PgPool::connect(&self.server.database.url).await?;
|
||||
pub async fn connect_to_db(&self) -> Result<MySqlPool, Error> {
|
||||
let pool = MySqlPool::connect(&self.server.database.url).await?;
|
||||
|
||||
// Run migrations
|
||||
sqlx::migrate!("./migrations").run(&pool).await?;
|
||||
|
||||
log::info!("PostgreSQL database connected");
|
||||
log::info!("MySQL database connected");
|
||||
Ok(pool)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ pub struct Config {
|
||||
pub config_path: String,
|
||||
pub(crate) server: Server,
|
||||
pub(crate) settings: Settings,
|
||||
pub(crate) discord: Discord,
|
||||
pub(crate) auth: Auth,
|
||||
}
|
||||
|
||||
@@ -31,11 +30,7 @@ pub struct Settings {
|
||||
pub(crate) offensive_words: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Discord {
|
||||
pub(crate) bot_token: String,
|
||||
pub(crate) channel_id: u64,
|
||||
}
|
||||
// Discord struct has been removed
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Auth {
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
use serenity::async_trait;
|
||||
use serenity::all::*;
|
||||
use sqlx::PgPool;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DomainRegistration {
|
||||
pub id: i32,
|
||||
pub domain_name: String,
|
||||
pub tld: String,
|
||||
pub user_id: i32,
|
||||
pub username: String,
|
||||
}
|
||||
|
||||
pub struct BotHandler {
|
||||
pub pool: PgPool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for BotHandler {
|
||||
async fn ready(&self, _: Context, ready: Ready) {
|
||||
log::info!("Discord bot {} is connected!", ready.user.name);
|
||||
}
|
||||
|
||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||
match interaction {
|
||||
Interaction::Component(component) => {
|
||||
let custom_id = &component.data.custom_id;
|
||||
|
||||
if custom_id.starts_with("approve_") {
|
||||
let domain_id: i32 = match custom_id.strip_prefix("approve_").unwrap().parse() {
|
||||
Ok(id) => id,
|
||||
Err(_) => {
|
||||
log::error!("Invalid domain ID in approve button");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Get domain info for the updated embed
|
||||
let domain: Option<(String, String, String)> = sqlx::query_as(
|
||||
"SELECT d.name, d.tld, u.username FROM domains d JOIN users u ON d.user_id = u.id WHERE d.id = $1"
|
||||
)
|
||||
.bind(domain_id)
|
||||
.fetch_optional(&self.pool)
|
||||
.await
|
||||
.unwrap_or(None);
|
||||
|
||||
if let Some((name, tld, username)) = domain {
|
||||
// Update domain status to approved
|
||||
match sqlx::query("UPDATE domains SET status = 'approved' WHERE id = $1")
|
||||
.bind(domain_id)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
// First, send ephemeral confirmation
|
||||
let response = CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("✅ Domain approved!")
|
||||
.ephemeral(true)
|
||||
);
|
||||
|
||||
if let Err(e) = component.create_response(&ctx.http, response).await {
|
||||
log::error!("Error responding to interaction: {}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Then edit the original message with green color and no buttons
|
||||
let updated_embed = CreateEmbed::new()
|
||||
.title("✅ Domain Registration - APPROVED")
|
||||
.field("Domain", format!("{}.{}", name, tld), true)
|
||||
.field("User", username, true)
|
||||
.field("Status", "Approved", true)
|
||||
.color(0x00ff00); // Green color
|
||||
|
||||
let edit_message = EditMessage::new()
|
||||
.embed(updated_embed)
|
||||
.components(vec![]); // Remove buttons
|
||||
|
||||
let mut message = component.message.clone();
|
||||
if let Err(e) = message.edit(&ctx.http, edit_message).await {
|
||||
log::error!("Error updating original message: {}", e);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error approving domain: {}", e);
|
||||
let response = CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("❌ Error approving domain")
|
||||
.ephemeral(true)
|
||||
);
|
||||
let _ = component.create_response(&ctx.http, response).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if custom_id.starts_with("deny_") {
|
||||
let domain_id = custom_id.strip_prefix("deny_").unwrap();
|
||||
|
||||
// Create modal for denial reason
|
||||
let modal = CreateModal::new(
|
||||
format!("deny_modal_{}", domain_id),
|
||||
"Deny Domain Registration"
|
||||
)
|
||||
.components(vec![
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(
|
||||
InputTextStyle::Paragraph,
|
||||
"Reason",
|
||||
"reason"
|
||||
)
|
||||
.placeholder("Please provide a reason for denying this domain registration")
|
||||
.required(true)
|
||||
)
|
||||
]);
|
||||
|
||||
let response = CreateInteractionResponse::Modal(modal);
|
||||
|
||||
if let Err(e) = component.create_response(&ctx.http, response).await {
|
||||
log::error!("Error showing modal: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Interaction::Modal(modal_submit) => {
|
||||
if modal_submit.data.custom_id.starts_with("deny_modal_") {
|
||||
let domain_id: i32 = match modal_submit.data.custom_id.strip_prefix("deny_modal_").unwrap().parse() {
|
||||
Ok(id) => id,
|
||||
Err(_) => {
|
||||
log::error!("Invalid domain ID in deny modal");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Get the reason from modal input
|
||||
let reason = modal_submit.data.components.get(0)
|
||||
.and_then(|row| row.components.get(0))
|
||||
.and_then(|component| {
|
||||
if let ActionRowComponent::InputText(input) = component {
|
||||
input.value.as_ref().map(|v| v.as_str())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or("No reason provided");
|
||||
|
||||
// Get domain info for the updated embed
|
||||
let domain: Option<(String, String, String)> = sqlx::query_as(
|
||||
"SELECT d.name, d.tld, u.username FROM domains d JOIN users u ON d.user_id = u.id WHERE d.id = $1"
|
||||
)
|
||||
.bind(domain_id)
|
||||
.fetch_optional(&self.pool)
|
||||
.await
|
||||
.unwrap_or(None);
|
||||
|
||||
if let Some((name, tld, username)) = domain {
|
||||
// Update domain status to denied with reason
|
||||
match sqlx::query("UPDATE domains SET status = 'denied', denial_reason = $1 WHERE id = $2")
|
||||
.bind(reason)
|
||||
.bind(domain_id)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
// First, send ephemeral confirmation
|
||||
let response = CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("❌ Domain denied!")
|
||||
.ephemeral(true)
|
||||
);
|
||||
|
||||
if let Err(e) = modal_submit.create_response(&ctx.http, response).await {
|
||||
log::error!("Error responding to modal: {}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Then edit the original message with red color and no buttons
|
||||
let updated_embed = CreateEmbed::new()
|
||||
.title("❌ Domain Registration - DENIED")
|
||||
.field("Domain", format!("{}.{}", name, tld), true)
|
||||
.field("User", username, true)
|
||||
.field("Status", "Denied", true)
|
||||
.field("Reason", reason, false)
|
||||
.color(0xff0000); // Red color
|
||||
|
||||
let edit_message = EditMessage::new()
|
||||
.embed(updated_embed)
|
||||
.components(vec![]); // Remove buttons
|
||||
|
||||
if let Some(mut message) = modal_submit.message.clone() {
|
||||
if let Err(e) = message.edit(&ctx.http, edit_message).await {
|
||||
log::error!("Error updating original message: {}", e);
|
||||
}
|
||||
} else {
|
||||
log::error!("Original message not found for editing");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Error denying domain: {}", e);
|
||||
let response = CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("❌ Error denying domain")
|
||||
.ephemeral(true)
|
||||
);
|
||||
let _ = modal_submit.create_response(&ctx.http, response).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Handle other interaction types if needed
|
||||
log::debug!("Unhandled interaction type: {:?}", interaction.kind());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_domain_approval_request(
|
||||
channel_id: u64,
|
||||
registration: DomainRegistration,
|
||||
bot_token: &str,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let http = serenity::http::Http::new(bot_token);
|
||||
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Domain request")
|
||||
.field("Domain", format!("{}.{}", registration.domain_name, registration.tld), true)
|
||||
.field("User", ®istration.username, true)
|
||||
.field("User ID", registration.user_id.to_string(), true)
|
||||
.field("Status", "Pending Review", true)
|
||||
.color(0x808080); // Gray color for pending
|
||||
|
||||
let approve_button = CreateButton::new(format!("approve_{}", registration.id))
|
||||
.style(ButtonStyle::Success)
|
||||
.label("✅ Approve");
|
||||
|
||||
let deny_button = CreateButton::new(format!("deny_{}", registration.id))
|
||||
.style(ButtonStyle::Danger)
|
||||
.label("❌ Deny");
|
||||
|
||||
let action_row = CreateActionRow::Buttons(vec![approve_button, deny_button]);
|
||||
|
||||
let message = CreateMessage::new()
|
||||
.embed(embed)
|
||||
.components(vec![action_row]);
|
||||
|
||||
let channel_id = ChannelId::new(channel_id);
|
||||
channel_id.send_message(&http, message).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn start_discord_bot(token: String, pool: PgPool) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT;
|
||||
|
||||
let mut client = Client::builder(&token, intents)
|
||||
.event_handler(BotHandler { pool })
|
||||
.await?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = client.start().await {
|
||||
log::error!("Discord bot error: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -4,7 +4,7 @@ mod models;
|
||||
mod routes;
|
||||
mod ca;
|
||||
|
||||
use crate::{auth::jwt_middleware_gurt, config::Config, discord_bot};
|
||||
use crate::{auth::jwt_middleware_gurt, config::Config};
|
||||
use colored::Colorize;
|
||||
use macros_rs::fmt::{crashln, string};
|
||||
use std::{sync::Arc, collections::HashMap};
|
||||
@@ -19,12 +19,12 @@ impl warp::reject::Reject for CertificateError {}
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct AppState {
|
||||
config: Config,
|
||||
db: sqlx::PgPool,
|
||||
db: sqlx::MySqlPool,
|
||||
jwt_secret: String,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn new(config: Config, db: sqlx::PgPool, jwt_secret: String) -> Self {
|
||||
pub fn new(config: Config, db: sqlx::MySqlPool, jwt_secret: String) -> Self {
|
||||
Self {
|
||||
config,
|
||||
db,
|
||||
@@ -208,12 +208,7 @@ pub async fn start(cli: crate::Cli) -> std::io::Result<()> {
|
||||
Err(err) => crashln!("Failed to connect to PostgreSQL database.\n{}", string!(err).white()),
|
||||
};
|
||||
|
||||
// Start Discord bot
|
||||
if !config.discord.bot_token.is_empty() {
|
||||
if let Err(e) = discord_bot::start_discord_bot(config.discord.bot_token.clone(), db.clone()).await {
|
||||
log::error!("Failed to start Discord bot: {}", e);
|
||||
}
|
||||
}
|
||||
// Discord bot component has been removed
|
||||
|
||||
let jwt_secret = config.auth.jwt_secret.clone();
|
||||
let app_state = AppState::new(config.clone(), db, jwt_secret);
|
||||
|
||||
@@ -200,7 +200,9 @@ pub(crate) async fn create_invite(_ctx: &ServerContext, app_state: AppState, cla
|
||||
let mut tx = app_state.db.begin().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
let affected_rows = sqlx::query("UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = $1 AND registrations_remaining > 0")
|
||||
let affected_rows = sqlx::query(
|
||||
"UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = ? AND registrations_remaining > 0"
|
||||
)
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
@@ -214,7 +216,7 @@ pub(crate) async fn create_invite(_ctx: &ServerContext, app_state: AppState, cla
|
||||
})?);
|
||||
}
|
||||
|
||||
sqlx::query("INSERT INTO invite_codes (code, created_by, created_at) VALUES ($1, $2, $3)")
|
||||
sqlx::query("INSERT INTO invite_codes (code, created_by, created_at) VALUES (?, ?, ?)")
|
||||
.bind(&invite_code)
|
||||
.bind(claims.user_id)
|
||||
.bind(Utc::now())
|
||||
@@ -259,7 +261,7 @@ pub(crate) async fn redeem_invite(ctx: &ServerContext, app_state: AppState, clai
|
||||
let mut tx = app_state.db.begin().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
sqlx::query("UPDATE invite_codes SET used_by = $1, used_at = $2 WHERE id = $3")
|
||||
sqlx::query("UPDATE invite_codes SET used_by = ?, used_at = ? WHERE id = ?")
|
||||
.bind(claims.user_id)
|
||||
.bind(Utc::now())
|
||||
.bind(invite.id)
|
||||
@@ -267,7 +269,7 @@ pub(crate) async fn redeem_invite(ctx: &ServerContext, app_state: AppState, clai
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
sqlx::query("UPDATE users SET registrations_remaining = registrations_remaining + 1 WHERE id = $1")
|
||||
sqlx::query("UPDATE users SET registrations_remaining = registrations_remaining + 1 WHERE id = ?")
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
@@ -313,7 +315,9 @@ pub(crate) async fn create_domain_invite(_ctx: &ServerContext, app_state: AppSta
|
||||
let mut tx = app_state.db.begin().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
let affected_rows = sqlx::query("UPDATE users SET domain_invite_codes = domain_invite_codes - 1 WHERE id = $1 AND domain_invite_codes > 0")
|
||||
let affected_rows = sqlx::query(
|
||||
"UPDATE users SET domain_invite_codes = domain_invite_codes - 1 WHERE id = ? AND domain_invite_codes > 0"
|
||||
)
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
@@ -367,7 +371,7 @@ pub(crate) async fn redeem_domain_invite(ctx: &ServerContext, app_state: AppStat
|
||||
let mut tx = app_state.db.begin().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
sqlx::query("UPDATE domain_invite_codes SET used_by = $1, used_at = $2 WHERE id = $3")
|
||||
sqlx::query("UPDATE domain_invite_codes SET used_by = ?, used_at = ? WHERE id = ?")
|
||||
.bind(claims.user_id)
|
||||
.bind(Utc::now())
|
||||
.bind(invite.id)
|
||||
@@ -375,7 +379,7 @@ pub(crate) async fn redeem_domain_invite(ctx: &ServerContext, app_state: AppStat
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
sqlx::query("UPDATE users SET domain_invite_codes = domain_invite_codes + 1 WHERE id = $1")
|
||||
sqlx::query("UPDATE users SET domain_invite_codes = domain_invite_codes + 1 WHERE id = ?")
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::crypto;
|
||||
use anyhow::Result;
|
||||
use sqlx::PgPool;
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
pub struct CaCertificate {
|
||||
pub ca_cert_pem: String,
|
||||
pub ca_key_pem: String,
|
||||
}
|
||||
|
||||
pub async fn get_or_create_ca(db: &PgPool) -> Result<CaCertificate> {
|
||||
pub async fn get_or_create_ca(db: &MySqlPool) -> Result<CaCertificate> {
|
||||
if let Some(ca_cert) = get_active_ca(db).await? {
|
||||
return Ok(ca_cert);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ pub async fn get_or_create_ca(db: &PgPool) -> Result<CaCertificate> {
|
||||
let (ca_key_pem, ca_cert_pem) = crypto::generate_ca_cert()?;
|
||||
|
||||
sqlx::query(
|
||||
"INSERT INTO ca_certificates (ca_cert_pem, ca_key_pem, is_active) VALUES ($1, $2, TRUE)"
|
||||
"INSERT INTO ca_certificates (ca_cert_pem, ca_key_pem, is_active) VALUES (?, ?, TRUE)"
|
||||
)
|
||||
.bind(&ca_cert_pem)
|
||||
.bind(&ca_key_pem)
|
||||
@@ -31,7 +31,7 @@ pub async fn get_or_create_ca(db: &PgPool) -> Result<CaCertificate> {
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_active_ca(db: &PgPool) -> Result<Option<CaCertificate>> {
|
||||
async fn get_active_ca(db: &MySqlPool) -> Result<Option<CaCertificate>> {
|
||||
let result: Option<(String, String)> = sqlx::query_as(
|
||||
"SELECT ca_cert_pem, ca_key_pem FROM ca_certificates WHERE is_active = TRUE ORDER BY created_at DESC LIMIT 1"
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use super::{models::*, AppState};
|
||||
use crate::auth::Claims;
|
||||
use crate::discord_bot::{send_domain_approval_request, DomainRegistration};
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use gurtlib::prelude::*;
|
||||
use rand::{rngs::OsRng, Rng};
|
||||
@@ -79,7 +78,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
}
|
||||
|
||||
let existing_count: i64 =
|
||||
sqlx::query_scalar("SELECT COUNT(*) FROM domains WHERE name = $1 AND tld = $2")
|
||||
sqlx::query_scalar("SELECT COUNT(*) FROM domains WHERE name = ? AND tld = ?")
|
||||
.bind(&domain.name)
|
||||
.bind(&domain.tld)
|
||||
.fetch_one(&app.db)
|
||||
@@ -90,7 +89,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
return Err(GurtError::invalid_message("Domain already exists"));
|
||||
}
|
||||
|
||||
let user: (String,) = sqlx::query_as("SELECT username FROM users WHERE id = $1")
|
||||
let user: (String,) = sqlx::query_as("SELECT username FROM users WHERE id = ?")
|
||||
.bind(user_id)
|
||||
.fetch_one(&app.db)
|
||||
.await
|
||||
@@ -99,7 +98,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
let username = user.0;
|
||||
|
||||
let domain_row: (i32,) = sqlx::query_as(
|
||||
"INSERT INTO domains (name, tld, user_id, status) VALUES ($1, $2, $3, 'pending') RETURNING id"
|
||||
"INSERT INTO domains (name, tld, user_id, status) VALUES (?, ?, ?, 'pending') RETURNING id"
|
||||
)
|
||||
.bind(&domain.name)
|
||||
.bind(&domain.tld)
|
||||
@@ -111,7 +110,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
let domain_id = domain_row.0;
|
||||
|
||||
let affected_rows = sqlx::query(
|
||||
"UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = $1 AND registrations_remaining > 0",
|
||||
"UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = ? AND registrations_remaining > 0",
|
||||
)
|
||||
.bind(user_id)
|
||||
.execute(&app.db)
|
||||
@@ -120,7 +119,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
.rows_affected();
|
||||
|
||||
if affected_rows == 0 {
|
||||
sqlx::query("DELETE FROM domains WHERE id = $1")
|
||||
sqlx::query("DELETE FROM domains WHERE id = ?")
|
||||
.bind(domain_id)
|
||||
.execute(&app.db)
|
||||
.await
|
||||
@@ -128,26 +127,7 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
return Err(GurtError::invalid_message("No registrations remaining"));
|
||||
}
|
||||
|
||||
if !app.config.discord.bot_token.is_empty() && app.config.discord.channel_id != 0 {
|
||||
let domain_registration = DomainRegistration {
|
||||
id: domain_id,
|
||||
domain_name: domain.name.clone(),
|
||||
tld: domain.tld.clone(),
|
||||
user_id,
|
||||
username: username.clone(),
|
||||
};
|
||||
|
||||
let channel_id = app.config.discord.channel_id;
|
||||
let bot_token = app.config.discord.bot_token.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) =
|
||||
send_domain_approval_request(channel_id, domain_registration, &bot_token).await
|
||||
{
|
||||
log::error!("Failed to send Discord notification: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Discord notification functionality has been removed
|
||||
|
||||
Ok(domain)
|
||||
}
|
||||
@@ -341,7 +321,7 @@ pub(crate) async fn delete_domain(
|
||||
return Ok(GurtResponse::not_found().with_string_body("Domain not found or access denied"));
|
||||
}
|
||||
|
||||
sqlx::query("DELETE FROM domains WHERE name = $1 AND tld = $2 AND user_id = $3")
|
||||
sqlx::query("DELETE FROM domains WHERE name = ? AND tld = ? AND user_id = ?")
|
||||
.bind(name)
|
||||
.bind(tld)
|
||||
.bind(claims.user_id)
|
||||
@@ -640,7 +620,7 @@ pub(crate) async fn delete_domain_record(
|
||||
}
|
||||
};
|
||||
|
||||
let rows_affected = sqlx::query("DELETE FROM dns_records WHERE id = $1 AND domain_id = $2")
|
||||
let rows_affected = sqlx::query("DELETE FROM dns_records WHERE id = ? AND domain_id = ?")
|
||||
.bind(record_id)
|
||||
.bind(domain.id.unwrap())
|
||||
.execute(&app_state.db)
|
||||
@@ -992,7 +972,7 @@ pub(crate) async fn get_certificate(
|
||||
let token = path_parts[3];
|
||||
|
||||
let challenge: Option<(String, String, String, Option<String>, chrono::DateTime<chrono::Utc>)> = sqlx::query_as(
|
||||
"SELECT domain, challenge_type, verification_data, csr_pem, expires_at FROM certificate_challenges WHERE token = $1"
|
||||
"SELECT domain, challenge_type, verification_data, csr_pem, expires_at FROM certificate_challenges WHERE token = ?"
|
||||
)
|
||||
.bind(token)
|
||||
.fetch_optional(&app_state.db)
|
||||
@@ -1086,7 +1066,7 @@ pub(crate) async fn get_certificate(
|
||||
});
|
||||
|
||||
// Delete the challenge as it's completed
|
||||
sqlx::query("DELETE FROM certificate_challenges WHERE token = $1")
|
||||
sqlx::query("DELETE FROM certificate_challenges WHERE token = ?")
|
||||
.bind(token)
|
||||
.execute(&app_state.db)
|
||||
.await
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
mod config;
|
||||
mod gurt_server;
|
||||
mod auth;
|
||||
mod discord_bot;
|
||||
mod crypto;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
@@ -4,7 +4,7 @@ sidebar_position: 6
|
||||
|
||||
# DNS System
|
||||
|
||||
The Gurted ecosystem features a custom DNS system that enables domain resolution for the gurt:// protocol. Unlike traditional DNS, Gurted DNS is designed specifically for the decentralized web ecosystem, providing:
|
||||
The Gurted ecosystem features a custom DNS system that enables domain resolution for the lw:// protocol. Unlike traditional DNS, Gurted DNS is designed specifically for the decentralized web ecosystem, providing:
|
||||
|
||||
- Domain registration with approval workflows
|
||||
- DNS record management (A, AAAA, CNAME, TXT)
|
||||
|
||||
@@ -4,5 +4,5 @@ sidebar_position: 7
|
||||
|
||||
# Flumi (browser)
|
||||
|
||||
**Flumi** is the official browser for the Gurted ecosystem, built using the Godot game engine. It provides a complete web browsing experience for `gurt://` URLs with custom HTML/CSS rendering, Lua scripting support, and integration with the Gurted DNS system.
|
||||
**Flumi** is the official browser for the Gurted ecosystem, built using the Godot game engine. It provides a complete web browsing experience for `lw://` URLs with custom HTML/CSS rendering, Lua scripting support, and integration with the Gurted DNS system.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ async fn main() -> Result<()> {
|
||||
let client = GurtClient::new();
|
||||
|
||||
// Make a GET request
|
||||
let response = client.get("gurt://example.com/").await?;
|
||||
let response = client.get("lw://example.com/").await?;
|
||||
|
||||
println!("Status: {}", response.status_code);
|
||||
println!("Body: {}", response.text()?);
|
||||
@@ -65,7 +65,7 @@ let client = GurtClient::with_config(config);
|
||||
### GET Requests
|
||||
|
||||
```rust
|
||||
let response = client.get("gurt://api.example.com/users").await?;
|
||||
let response = client.get("lw://api.example.com/users").await?;
|
||||
|
||||
if response.is_success() {
|
||||
println!("Success: {}", response.text()?);
|
||||
@@ -78,7 +78,7 @@ if response.is_success() {
|
||||
|
||||
#### Text Data
|
||||
```rust
|
||||
let response = client.post("gurt://api.example.com/submit", "Hello, GURT!").await?;
|
||||
let response = client.post("lw://api.example.com/submit", "Hello, GURT!").await?;
|
||||
```
|
||||
|
||||
#### JSON Data
|
||||
@@ -90,30 +90,30 @@ let data = json!({
|
||||
"email": "john@example.com"
|
||||
});
|
||||
|
||||
let response = client.post_json("gurt://api.example.com/users", &data).await?;
|
||||
let response = client.post_json("lw://api.example.com/users", &data).await?;
|
||||
```
|
||||
|
||||
### PUT Requests
|
||||
|
||||
```rust
|
||||
// Text data
|
||||
let response = client.put("gurt://api.example.com/resource/123", "Updated content").await?;
|
||||
let response = client.put("lw://api.example.com/resource/123", "Updated content").await?;
|
||||
|
||||
// JSON data
|
||||
let update_data = json!({"status": "completed"});
|
||||
let response = client.put_json("gurt://api.example.com/tasks/456", &update_data).await?;
|
||||
let response = client.put_json("lw://api.example.com/tasks/456", &update_data).await?;
|
||||
```
|
||||
|
||||
### DELETE Requests
|
||||
|
||||
```rust
|
||||
let response = client.delete("gurt://api.example.com/users/123").await?;
|
||||
let response = client.delete("lw://api.example.com/users/123").await?;
|
||||
```
|
||||
|
||||
### HEAD Requests
|
||||
|
||||
```rust
|
||||
let response = client.head("gurt://api.example.com/large-file").await?;
|
||||
let response = client.head("lw://api.example.com/large-file").await?;
|
||||
|
||||
// Check headers without downloading body
|
||||
let content_length = response.headers.get("content-length");
|
||||
@@ -122,7 +122,7 @@ let content_length = response.headers.get("content-length");
|
||||
### OPTIONS Requests
|
||||
|
||||
```rust
|
||||
let response = client.options("gurt://api.example.com/endpoint").await?;
|
||||
let response = client.options("lw://api.example.com/endpoint").await?;
|
||||
|
||||
// Check allowed methods
|
||||
let allowed_methods = response.headers.get("allow");
|
||||
@@ -132,7 +132,7 @@ let allowed_methods = response.headers.get("allow");
|
||||
|
||||
```rust
|
||||
let patch_data = json!({"name": "Updated Name"});
|
||||
let response = client.patch_json("gurt://api.example.com/users/123", &patch_data).await?;
|
||||
let response = client.patch_json("lw://api.example.com/users/123", &patch_data).await?;
|
||||
```
|
||||
|
||||
## Response Handling
|
||||
@@ -152,7 +152,7 @@ pub struct GurtResponse {
|
||||
### Accessing Response Data
|
||||
|
||||
```rust
|
||||
let response = client.get("gurt://api.example.com/data").await?;
|
||||
let response = client.get("lw://api.example.com/data").await?;
|
||||
|
||||
// Status information
|
||||
println!("Status Code: {}", response.status_code);
|
||||
@@ -201,14 +201,14 @@ All of this happens transparently when you call methods like `get()`, `post()`,
|
||||
|
||||
## URL Parsing
|
||||
|
||||
The client automatically parses `gurt://` URLs:
|
||||
The client automatically parses `lw://` URLs:
|
||||
|
||||
```rust
|
||||
// These are all valid GURT URLs:
|
||||
client.get("gurt://example.com/").await?; // Port 4878 (default)
|
||||
client.get("gurt://example.com:8080/api").await?; // Custom port
|
||||
client.get("gurt://192.168.1.100/test").await?; // IP address
|
||||
client.get("gurt://localhost:4878/dev").await?; // Localhost
|
||||
client.get("lw://example.com/").await?; // Port 4878 (default)
|
||||
client.get("lw://example.com:8080/api").await?; // Custom port
|
||||
client.get("lw://192.168.1.100/test").await?; // IP address
|
||||
client.get("lw://localhost:4878/dev").await?; // Localhost
|
||||
```
|
||||
|
||||
### URL Components
|
||||
@@ -225,7 +225,7 @@ The client extracts:
|
||||
```rust
|
||||
use gurtlib::GurtError;
|
||||
|
||||
match client.get("gurt://invalid-url").await {
|
||||
match client.get("lw://invalid-url").await {
|
||||
Ok(response) => {
|
||||
// Handle successful response
|
||||
}
|
||||
@@ -332,7 +332,7 @@ impl ApiClient {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let api = ApiClient::new("gurt://api.example.com".to_string());
|
||||
let api = ApiClient::new("lw://api.example.com".to_string());
|
||||
|
||||
// Create a user
|
||||
let new_user = CreateUser {
|
||||
|
||||
@@ -4,7 +4,7 @@ sidebar_position: 2
|
||||
|
||||
# GURT Protocol
|
||||
|
||||
**GURT** (version 1.0.0) is a TCP-based application protocol designed as an HTTP-like alternative with built-in TLS 1.3 encryption. It serves as the foundation for the Gurted ecosystem, enabling secure communication between clients and servers using the `gurt://` URL scheme.
|
||||
**GURT** (version 1.0.0) is a TCP-based application protocol designed as an HTTP-like alternative with built-in TLS 1.3 encryption. It serves as the foundation for the Gurted ecosystem, enabling secure communication between clients and servers using the `lw://` URL scheme.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -21,12 +21,12 @@ GURT provides a familiar HTTP-like syntax while offering security through mandat
|
||||
|
||||
## URL Scheme
|
||||
|
||||
GURT uses the `gurt://` URL scheme:
|
||||
GURT uses the `lw://` URL scheme:
|
||||
|
||||
```
|
||||
gurt://example.com/path
|
||||
gurt://192.168.1.100:4878/api/data
|
||||
gurt://localhost:4878/hello
|
||||
lw://example.com/path
|
||||
lw://192.168.1.100:4878/api/data
|
||||
lw://localhost:4878/hello
|
||||
```
|
||||
|
||||
The protocol automatically defaults to port 4878.
|
||||
@@ -244,13 +244,13 @@ GURT integrates with Gurted's custom DNS system:
|
||||
|
||||
### Direct IP Access
|
||||
```
|
||||
gurt://192.168.1.100:4878/
|
||||
gurt://localhost:4878/api
|
||||
lw://192.168.1.100:4878/
|
||||
lw://localhost:4878/api
|
||||
```
|
||||
|
||||
### Domain Resolution
|
||||
```
|
||||
gurt://example.real/ # Resolves via Gurted DNS
|
||||
lw://example.real/ # Resolves via Gurted DNS
|
||||
```
|
||||
|
||||
The Gurted DNS server resolves domains in the format `name.tld` to IP addresses, enabling human-readable domain names for GURT services. This is done automatically by your GURT browser and is documented in the [DNS System documentation](./dns-system.md).
|
||||
|
||||
@@ -38,7 +38,7 @@ async fn main() -> Result<()> {
|
||||
Ok(GurtResponse::ok().with_json_body(&users))
|
||||
});
|
||||
|
||||
println!("GURT server starting on gurt://127.0.0.1:4878");
|
||||
println!("GURT server starting on lw://127.0.0.1:4878");
|
||||
server.listen("127.0.0.1:4878").await
|
||||
}
|
||||
```
|
||||
@@ -462,7 +462,7 @@ mod tests {
|
||||
|
||||
// Test with client
|
||||
let client = GurtClient::new();
|
||||
let response = client.get("gurt://127.0.0.1:9999/test").await.unwrap();
|
||||
let response = client.get("lw://127.0.0.1:9999/test").await.unwrap();
|
||||
|
||||
assert_eq!(response.status_code, 200);
|
||||
assert_eq!(response.text().unwrap(), "test response");
|
||||
|
||||
@@ -75,7 +75,7 @@ line breaks
|
||||
Links can point to external URLs (which open in the user's default browser) or GURT protocol links:
|
||||
```html
|
||||
<a href="https://example.com">External link</a>
|
||||
<a href="gurt://internal.site">GURT protocol link</a>
|
||||
<a href="lw://internal.site">GURT protocol link</a>
|
||||
```
|
||||
|
||||
### Line Breaks
|
||||
@@ -317,7 +317,7 @@ Network image loading with sizing controls:
|
||||
|
||||
```html
|
||||
<img src="https://example.com/image.jpg" style="max-w-24 max-h-24 rounded" />
|
||||
<img src="gurt://local.site/image.png" style="w-32 h-32" />
|
||||
<img src="lw://local.site/image.png" style="w-32 h-32" />
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
@@ -5,7 +5,7 @@ sidebar_position: 1
|
||||
# Introduction
|
||||
|
||||
**Gurted** is a project introducing a new web ecosystem, featuring:
|
||||
- the **gurt:// protocol**
|
||||
- the **lw:// protocol**
|
||||
- a custom search engine
|
||||
- a custom browser - **Flumi**
|
||||
- a custom **DNS** (Domain Name System)
|
||||
@@ -22,7 +22,7 @@ Learn more about the GURT protocol: [Protocol Specification](./gurt-protocol.md)
|
||||
Get started by **exploring Gurted sites** or **try creating your first GURT page**.
|
||||
|
||||
To get started, download:
|
||||
- [Flumi](https://gurted.com/download/), the official browser for `gurt://`
|
||||
- [Flumi](https://gurted.com/download/), the official browser for `lw://`
|
||||
- A *text editor* of choice, we recommend [Visual Studio Code](https://code.visualstudio.com/download)
|
||||
|
||||
## Components
|
||||
@@ -34,7 +34,7 @@ Gurted consists of three main components:
|
||||
```html
|
||||
<head>
|
||||
<title>Yo Gurt</title>
|
||||
<icon src="gurt://example.real/icon.png">
|
||||
<icon src="lw://example.real/icon.png">
|
||||
|
||||
<style>...</style>
|
||||
</head>
|
||||
|
||||
@@ -12,7 +12,7 @@ audio:stop() -- Stop and reset
|
||||
audio.currentTime = 30.0 -- Seek to 30 seconds
|
||||
audio.volume = 0.8 -- Set volume (0.0 - 1.0)
|
||||
audio.loop = true -- Enable looping
|
||||
audio.src = 'gurt://new-audio.mp3' -- Change source
|
||||
audio.src = 'lw://new-audio.mp3' -- Change source
|
||||
|
||||
local duration = audio.duration
|
||||
local currentPos = audio.currentTime
|
||||
|
||||
@@ -14,7 +14,7 @@ download_id = gurt.download(url filename)
|
||||
|
||||
### Parameters
|
||||
|
||||
- **url** (string): The URL to download from. Supports HTTP, HTTPS, and gurt:// protocols.
|
||||
- **url** (string): The URL to download from. Supports HTTP, HTTPS, and lw:// protocols.
|
||||
- **filename** (string, optional): The filename to save as. If not provided, the filename will be extracted from the URL or default to "download".
|
||||
|
||||
### Returns
|
||||
|
||||
@@ -92,7 +92,7 @@ gurt.location.reload()
|
||||
Navigates to a new URL.
|
||||
|
||||
```lua
|
||||
gurt.location.goto('gurt://example.com/page')
|
||||
gurt.location.goto('lw://example.com/page')
|
||||
gurt.location.goto('https://external-site.com')
|
||||
```
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ end
|
||||
|
||||
**Supported Methods:** `GET`, `POST`, `PUT`, `DELETE`, `HEAD`, `OPTIONS`, `PATCH`
|
||||
|
||||
**Relative URLs** are automatically resolved to the current domain with `gurt://` protocol.
|
||||
**Relative URLs** are automatically resolved to the current domain with `lw://` protocol.
|
||||
|
||||
## WebSocket API
|
||||
|
||||
@@ -89,8 +89,8 @@ trace.log(params) -- name%3DJohn%20Doe%26age%3D30
|
||||
|
||||
-- Building query strings
|
||||
local searchTerm = 'cats & dogs'
|
||||
local url = 'gurt://search.com/api?q=' .. urlEncode(searchTerm)
|
||||
trace.log(url) -- gurt://search.com/api?q=cats%20%26%20dogs
|
||||
local url = 'lw://search.com/api?q=' .. urlEncode(searchTerm)
|
||||
trace.log(url) -- lw://search.com/api?q=cats%20%26%20dogs
|
||||
```
|
||||
|
||||
### urlDecode(string)
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/23x23-empty.svg-f79aa182e01c658978086a2615b5c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/arrow-down-up.svg-e4447ec644884e537fc08b18ae7
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/arrow-down.svg-1e5275b4ffe06ccf19d892794fc84c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/arrow-left.svg-5f99da4595c3d8d0d08c3c956ebfe3
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/arrow-right.svg-c769bf30dd1a5a6c76e989455e94e
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/arrow-up.svg-e673f59c1623de68e856c93a57be6cb0
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/braces.svg-be0ddfb3b648ce88f7cbe89a363017a8.c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/calendar.svg-4a7aa93bfd00cdce85eae886ac3d4d51
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/calendar_16x16.svg-38c497b40cde0596f1f838e0a5
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/case-sensitive.svg-86490276d97b2dfa5c8d69e899
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox.svg-b131741b9ad567d1cf024db4c0f11166
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_16x16.svg-23a6d489dba63f0e32212ca718
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_disabled.svg-d293c35e32232bb898ac1dc
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_disabled_16x16.svg-0df6b630be4bcd269
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_pressed.svg-7864c501a8fa0fa8194946d7
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_pressed_16x16.svg-dca6d3e6936ded383c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_pressed_grayscale.svg-45c89d5e4123fd
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_pressed_grayscale_16x16.svg-81766015
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/checkbox_white.svg-3c05c756132e06b6df4f4ae643
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/chevron-down.svg-549b6fd6d6d40e9ebd832012d163
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/chevron-down_dark.svg-fe36ecb29c503500628a9ec
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/chevron-down_grayscale.svg-02f7a486dacf16eba4
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/chevron-up.svg-5dc5e9cdc34bc223615780b493e393
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/chevron-up_dark.svg-dcda86b6613fa86b5c83eb083
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/chevron-up_grayscale.svg-1ef45b85e952ab110d49
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/download.svg-a21cd5d191a2f0c8e42168f24a4d40ed
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/ellipsis-vertical.svg-294910634c008df812f7ef4
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/eraser.svg-e6400a62a38066fbd6aaec113f0b7fb0.c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/external-link.svg-075235ddf5518da7b64a7c53322
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/file-text.svg-353070fe8162736240f258d043a74bb
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/folder.svg-0d6e9c106058d2e35908257faa439409.c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/funnel.svg-cd3708ed9907c314e118f9c06364d430.c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/globe.svg-2e20bad5dc0399b0e6d7dae13a9b962d.ct
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/grabber.svg-5bbaaff74062a94713192c7a76195634.
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/grabber_16x16.svg-c4a4f003a977fdc06fa876b726b
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/grabber_16x16_active.svg-9a5a1e1e807dfc3dc7ca
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/grabber_16x16_grayscale.svg-2ecb404cfc96fa8f0
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/hat-glasses.svg-a7dbfb316472ae1702496a78a0ce4
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/history.svg-ce846a8aaa80f3d2f2a595f430c7ab7c.
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/image.svg-cb997eeaa724d7751463205eebbff36d.ct
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/link-2.svg-65859ed5f57233280efa03e60ad3c6bb.c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/loader-circle.svg-c17ccf4fea88a610c3708518f91
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/log-out.svg-85530e4e6b0167a15c809830d3302ef2.
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/message-circle-question-mark.svg-6e0198922e95
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/palette.svg-5fa12e1482da68f886eda54557eaaf30.
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/pause.svg-b569a82cdc28c1abec0d4398e766838d.ct
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/pipette.svg-a6be8bac297998a574c1b4a125cbf35b.
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/play.svg-b90f638081075dc471c4bc5e46375e06.cte
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/plus.svg-f4b3570cb7fae700c6a08ebce6d60d56.cte
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio.svg-320eafa791feaf0d1d926ec0d2ba3722.ct
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_16x16.svg-336cec64bc60aed5eb9a10bc1f4f4
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_checked.svg-81396277cd631c074cae607c415
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_checked_16x16.svg-ecff803b12f1ac3b6b894
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_checked_grayscale.svg-6ce9eb51f7fcbe2c1
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_checked_grayscale_16x16.svg-e26000b6b89
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_disabled.svg-04a182ffa1f439025aa6457482
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/radio_disabled_16x16.svg-bc35dc6638da44ddcd95
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/resize-handle.svg-433a7f0ff4889b64a8919f3af66
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/rotate-cw.svg-dc1ce1f9471720aef7c52da0114941e
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/search.svg-1a2b06368a6d95d720ef3acf028b44e6.c
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/settings.svg-2aa0f389da6ad0a7e346738ae84fd469
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user