updates to concierge bot to support adding services and routes

This commit is contained in:
JB
2026-02-12 19:25:01 -05:00
parent e9865d3ee8
commit abc8070835
86 changed files with 2396 additions and 723 deletions

View File

@@ -2,6 +2,7 @@
"recommendations": [ "recommendations": [
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"oven.bun-vscode", "oven.bun-vscode",
"yy0931.vscode-sqlite3-editor" "yy0931.vscode-sqlite3-editor",
"humao.rest-client"
] ]
} }

View File

@@ -42,12 +42,12 @@ https://discord.com/oauth2/authorize?client_id=<YOUR DISCORD CLIENT ID>
## 4. Installing the library ## 4. Installing the library
If you are creating your own bot outside this repository, install the `@star-kitten/lib` framework. If you are creating your own bot outside this repository, install the [@star-kitten/lib](https://git.f302.me/jb/-/packages/npm/@star-kitten%2Flib) package in your project.
This framework is publised to my private npm repository, so add the registry to your npm config This framework is publised to my private npm repository, so add the registry to your npm config
```sh ```sh
bun config set @star-kitten:registry https://git.f302.me/registry npm config set @star-kitten:registry=https://git.f302.me/api/packages/jb/npm/
``` ```
Then install the library Then install the library

View File

@@ -4,12 +4,8 @@
"workspaces": { "workspaces": {
"": { "": {
"name": "star-kitten", "name": "star-kitten",
"dependencies": {
"ghooks": "^2.0.4",
"node-cache": "^5.1.2",
},
"devDependencies": { "devDependencies": {
"@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev", "ghooks": "^2.0.4",
"typescript": "5.9.3", "typescript": "5.9.3",
}, },
}, },
@@ -31,7 +27,7 @@
}, },
"packages/lib": { "packages/lib": {
"name": "@star-kitten/lib", "name": "@star-kitten/lib",
"version": "0.0.0", "version": "0.0.1",
"dependencies": { "dependencies": {
"@orama/orama": "^3.1.13", "@orama/orama": "^3.1.13",
"@oslojs/encoding": "^1.1.0", "@oslojs/encoding": "^1.1.0",
@@ -67,6 +63,8 @@
"bumpp": "^10.1.0", "bumpp": "^10.1.0",
"drizzle-kit": "^0.31.4", "drizzle-kit": "^0.31.4",
"ghooks": "^2.0.4", "ghooks": "^2.0.4",
"openapi-fetch": "^0.15.0",
"openapi-typescript": "^7.10.1",
"prettier-plugin-multiline-arrays": "^4.0.3", "prettier-plugin-multiline-arrays": "^4.0.3",
"tsdown": "^0.14.2", "tsdown": "^0.14.2",
"typescript": "^5.9.2", "typescript": "^5.9.2",
@@ -77,13 +75,12 @@
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev", "@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev",
"@star-kitten/lib": "workspace:^0.0.0", "@star-kitten/lib": "workspace:*",
}, },
"devDependencies": { "devDependencies": {
"@dotenvx/dotenvx": "^1.49.0", "@dotenvx/dotenvx": "^1.49.0",
"@types/bun": "^1.2.21", "@types/bun": "^1.2.21",
"@types/node": "^24.3.1", "@types/node": "^24.3.1",
"ghooks": "^2.0.4",
"mkdirp": "^3.0.1", "mkdirp": "^3.0.1",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"typescript": "^5.9.2", "typescript": "^5.9.2",
@@ -99,6 +96,8 @@
"@augment-vir/core": ["@augment-vir/core@31.51.1", "", { "dependencies": { "@date-vir/duration": "^8.0.0", "browser-or-node": "^3.0.0", "diff": "^8.0.2", "json5": "^2.2.3", "type-fest": "^5.2.0" } }, "sha512-o/eQVXILuRit+tF/Ll0+xbef+jT9WnP84fTrVgO9iZ0GT3ngprM3gepxImrr0pI5vFidiLIhfTxhl+kHHtpYpg=="], "@augment-vir/core": ["@augment-vir/core@31.51.1", "", { "dependencies": { "@date-vir/duration": "^8.0.0", "browser-or-node": "^3.0.0", "diff": "^8.0.2", "json5": "^2.2.3", "type-fest": "^5.2.0" } }, "sha512-o/eQVXILuRit+tF/Ll0+xbef+jT9WnP84fTrVgO9iZ0GT3ngprM3gepxImrr0pI5vFidiLIhfTxhl+kHHtpYpg=="],
"@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="],
"@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="], "@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="],
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
@@ -219,6 +218,12 @@
"@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="],
"@redocly/ajv": ["@redocly/ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-EDtsGZS964mf9zAUXAl9Ew16eYbeyAFWhsPr0fX6oaJxgd8rApYlPBf0joyhnUHz88WxrigyFtTaqqzXNzPgqw=="],
"@redocly/config": ["@redocly/config@0.22.2", "", {}, "sha512-roRDai8/zr2S9YfmzUfNhKjOF0NdcOIqF7bhf4MVC5UxpjIysDjyudvlAiVbpPHp3eDRWbdzUgtkK1a7YiDNyQ=="],
"@redocly/openapi-core": ["@redocly/openapi-core@1.34.6", "", { "dependencies": { "@redocly/ajv": "^8.11.2", "@redocly/config": "^0.22.0", "colorette": "^1.2.0", "https-proxy-agent": "^7.0.5", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", "minimatch": "^5.0.1", "pluralize": "^8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-2+O+riuIUgVSuLl3Lyh5AplWZyVMNuG2F98/o6NrutKJfW4/GTZdPpZlIphS0HGgcOHgmWcCSHj+dWFlZaGSHw=="],
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.50", "", { "os": "android", "cpu": "arm64" }, "sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag=="], "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.50", "", { "os": "android", "cpu": "arm64" }, "sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag=="],
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.50", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w=="], "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.50", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w=="],
@@ -403,12 +408,18 @@
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
"ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="],
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"args-tokenizer": ["args-tokenizer@0.3.0", "", {}, "sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q=="], "args-tokenizer": ["args-tokenizer@0.3.0", "", {}, "sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q=="],
"asn1.js": ["asn1.js@5.4.1", "", { "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "safer-buffer": "^2.1.0" } }, "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA=="], "asn1.js": ["asn1.js@5.4.1", "", { "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "safer-buffer": "^2.1.0" } }, "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA=="],
@@ -447,6 +458,8 @@
"chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],
"change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="],
"check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="],
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
@@ -463,6 +476,8 @@
"color-string": ["color-string@2.1.3", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-r/wfcFshhORndnDjn3GtNVLA4QL4TAi0A/XIBNuWUIEAVyUBNWYLuckrDz/JM1aQlpIDzKuY5hAYdHcLYgwJsg=="], "color-string": ["color-string@2.1.3", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-r/wfcFshhORndnDjn3GtNVLA4QL4TAi0A/XIBNuWUIEAVyUBNWYLuckrDz/JM1aQlpIDzKuY5hAYdHcLYgwJsg=="],
"colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="],
"colors": ["colors@0.6.2", "", {}, "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw=="], "colors": ["colors@0.6.2", "", {}, "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw=="],
"commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
@@ -547,6 +562,10 @@
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="], "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="],
@@ -591,12 +610,16 @@
"htmlparser2": ["htmlparser2@10.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.1", "entities": "^6.0.0" } }, "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g=="], "htmlparser2": ["htmlparser2@10.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.1", "entities": "^6.0.0" } }, "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g=="],
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], "human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="],
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
@@ -617,10 +640,16 @@
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
"js-levenshtein": ["js-levenshtein@1.1.6", "", {}, "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="],
"js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="],
@@ -709,8 +738,14 @@
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
"openapi-fetch": ["openapi-fetch@0.15.0", "", { "dependencies": { "openapi-typescript-helpers": "^0.0.15" } }, "sha512-OjQUdi61WO4HYhr9+byCPMj0+bgste/LtSBEcV6FzDdONTs7x0fWn8/ndoYwzqCsKWIxEZwo4FN/TG1c1rI8IQ=="],
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
"openapi-typescript": ["openapi-typescript@7.10.1", "", { "dependencies": { "@redocly/openapi-core": "^1.34.5", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.3.0", "supports-color": "^10.2.2", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-rBcU8bjKGGZQT4K2ekSTY2Q5veOQbVG/lTKZ49DeCyT9z62hM2Vj/LLHjDHC9W7LJG8YMHcdXpRZDqC1ojB/lw=="],
"openapi-typescript-helpers": ["openapi-typescript-helpers@0.0.15", "", {}, "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw=="],
"opt-cli": ["opt-cli@1.5.1", "", { "dependencies": { "commander": "2.9.0", "lodash.clone": "4.3.2", "manage-path": "2.0.0", "spawn-command": "0.0.2-1" }, "bin": { "opt": "bin/index.js" } }, "sha512-iRFQBiQjXZ+LX/8pis04prUhS6FOYcJiZRouofN3rUJEB282b/e0s3jp9vT7aHgXY6TUpgPwu12f0i+qF40Kjw=="], "opt-cli": ["opt-cli@1.5.1", "", { "dependencies": { "commander": "2.9.0", "lodash.clone": "4.3.2", "manage-path": "2.0.0", "spawn-command": "0.0.2-1" }, "bin": { "opt": "bin/index.js" } }, "sha512-iRFQBiQjXZ+LX/8pis04prUhS6FOYcJiZRouofN3rUJEB282b/e0s3jp9vT7aHgXY6TUpgPwu12f0i+qF40Kjw=="],
"opusscript": ["opusscript@0.1.1", "", {}, "sha512-mL0fZZOUnXdZ78woRXp18lApwpp0lF5tozJOD1Wut0dgrA9WuQTgSels/CSmFleaAZrJi/nci5KOVtbuxeWoQA=="], "opusscript": ["opusscript@0.1.1", "", {}, "sha512-mL0fZZOUnXdZ78woRXp18lApwpp0lF5tozJOD1Wut0dgrA9WuQTgSels/CSmFleaAZrJi/nci5KOVtbuxeWoQA=="],
@@ -719,6 +754,8 @@
"package-manager-detector": ["package-manager-detector@1.5.0", "", {}, "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw=="], "package-manager-detector": ["package-manager-detector@1.5.0", "", {}, "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw=="],
"parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
"path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], "path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
@@ -737,6 +774,8 @@
"pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="],
"pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="],
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
@@ -753,6 +792,8 @@
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
"rolldown": ["rolldown@1.0.0-beta.50", "", { "dependencies": { "@oxc-project/types": "=0.97.0", "@rolldown/pluginutils": "1.0.0-beta.50" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-x64": "1.0.0-beta.50", "@rolldown/binding-freebsd-x64": "1.0.0-beta.50", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.50", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.50", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.50", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.50", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.50" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A=="], "rolldown": ["rolldown@1.0.0-beta.50", "", { "dependencies": { "@oxc-project/types": "=0.97.0", "@rolldown/pluginutils": "1.0.0-beta.50" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-x64": "1.0.0-beta.50", "@rolldown/binding-freebsd-x64": "1.0.0-beta.50", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.50", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.50", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.50", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.50", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.50" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A=="],
@@ -813,7 +854,7 @@
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="], "strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
@@ -843,7 +884,7 @@
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"type-fest": ["type-fest@5.2.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA=="], "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
"typed-event-target": ["typed-event-target@4.1.0", "", { "dependencies": { "@augment-vir/assert": "^31.19.1", "@augment-vir/common": "^31.19.1", "@augment-vir/core": "^31.19.1" } }, "sha512-fDFhZb7ofywLsVv8mYePD6ONfCpVHyM1t2dboEJx/XMsnflljnu3GQ5qH09hS1USuypGMR7wRbdWQPydgJ8nGQ=="], "typed-event-target": ["typed-event-target@4.1.0", "", { "dependencies": { "@augment-vir/assert": "^31.19.1", "@augment-vir/common": "^31.19.1", "@augment-vir/core": "^31.19.1" } }, "sha512-fDFhZb7ofywLsVv8mYePD6ONfCpVHyM1t2dboEJx/XMsnflljnu3GQ5qH09hS1USuypGMR7wRbdWQPydgJ8nGQ=="],
@@ -881,9 +922,23 @@
"yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="],
"yaml-ast-parser": ["yaml-ast-parser@0.0.43", "", {}, "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"@augment-vir/assert/type-fest": ["type-fest@5.2.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA=="],
"@augment-vir/common/type-fest": ["type-fest@5.2.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA=="],
"@augment-vir/core/type-fest": ["type-fest@5.2.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA=="],
"@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"@date-vir/duration/type-fest": ["type-fest@5.2.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA=="],
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
"@star-kitten/lib/@projectdysnomia/dysnomia": ["@projectdysnomia/dysnomia@github:projectdysnomia/dysnomia#ae81d0f", { "dependencies": { "ws": "^8.18.0" }, "optionalDependencies": { "@snazzah/davey": "^0.1.6", "@stablelib/xchacha20poly1305": "~1.0.1", "opusscript": "^0.1.1" }, "peerDependencies": { "@discordjs/opus": "^0.9.0", "erlpack": "github:discord/erlpack", "eventemitter3": "^5.0.1", "pako": "^2.1.0", "sodium-native": "^4.1.1", "zlib-sync": "^0.1.9" }, "optionalPeers": ["@discordjs/opus", "erlpack", "eventemitter3", "pako", "sodium-native", "zlib-sync"] }, "projectdysnomia-dysnomia-ae81d0f"], "@redocly/openapi-core/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
"@types/jsonwebtoken/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="], "@types/jsonwebtoken/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
@@ -893,6 +948,8 @@
"bun-types/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="], "bun-types/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
"concierge-bot/@projectdysnomia/dysnomia": ["@projectdysnomia/dysnomia@github:projectdysnomia/dysnomia#ae81d0f", { "dependencies": { "ws": "^8.18.0" }, "optionalDependencies": { "@snazzah/davey": "^0.1.6", "@stablelib/xchacha20poly1305": "~1.0.1", "opusscript": "^0.1.1" }, "peerDependencies": { "@discordjs/opus": "^0.9.0", "erlpack": "github:discord/erlpack", "eventemitter3": "^5.0.1", "pako": "^2.1.0", "sodium-native": "^4.1.1", "zlib-sync": "^0.1.9" }, "optionalPeers": ["@discordjs/opus", "erlpack", "eventemitter3", "pako", "sodium-native", "zlib-sync"] }, "projectdysnomia-dysnomia-ae81d0f"],
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
@@ -901,12 +958,16 @@
"foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
"istanbul-lib-report/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"opt-cli/commander": ["commander@2.9.0", "", { "dependencies": { "graceful-readlink": ">= 1.0.0" } }, "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A=="], "opt-cli/commander": ["commander@2.9.0", "", { "dependencies": { "graceful-readlink": ">= 1.0.0" } }, "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A=="],
"opt-cli/lodash.clone": ["lodash.clone@4.3.2", "", { "dependencies": { "lodash._baseclone": "~4.5.0" } }, "sha512-Yc/0UmZvWkFsbx7NB4feSX5bSX03SR0ft8CTkI8RCb3w/TzT71HXew2iNDm0aml93P49tIR/NJHOIoE+XEKz9A=="], "opt-cli/lodash.clone": ["lodash.clone@4.3.2", "", { "dependencies": { "lodash._baseclone": "~4.5.0" } }, "sha512-Yc/0UmZvWkFsbx7NB4feSX5bSX03SR0ft8CTkI8RCb3w/TzT71HXew2iNDm0aml93P49tIR/NJHOIoE+XEKz9A=="],
"opt-cli/spawn-command": ["spawn-command@0.0.2-1", "", {}, "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg=="], "opt-cli/spawn-command": ["spawn-command@0.0.2-1", "", {}, "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg=="],
"star-kitten/@projectdysnomia/dysnomia": ["@projectdysnomia/dysnomia@github:projectdysnomia/dysnomia#ae81d0f", { "dependencies": { "ws": "^8.18.0" }, "optionalDependencies": { "@snazzah/davey": "^0.1.6", "@stablelib/xchacha20poly1305": "~1.0.1", "opusscript": "^0.1.1" }, "peerDependencies": { "@discordjs/opus": "^0.9.0", "erlpack": "github:discord/erlpack", "eventemitter3": "^5.0.1", "pako": "^2.1.0", "sodium-native": "^4.1.1", "zlib-sync": "^0.1.9" }, "optionalPeers": ["@discordjs/opus", "erlpack", "eventemitter3", "pako", "sodium-native", "zlib-sync"] }, "projectdysnomia-dysnomia-ae81d0f"],
"star-kitten/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="], "star-kitten/@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
"stream-json/stream-chain": ["stream-chain@2.2.5", "", {}, "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA=="], "stream-json/stream-chain": ["stream-chain@2.2.5", "", {}, "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA=="],

View File

@@ -20,7 +20,7 @@
}, },
"config": { "config": {
"ghooks": { "ghooks": {
"pre-commit": "bun encrypt && git add **/.env*" "pre-commit": "bun run encrypt && git add **/.env*"
} }
} }
} }

View File

@@ -12,22 +12,19 @@ DOTENV_PUBLIC_KEY_DEVELOPMENT="02572da3d4f3a844588a944214c0e142a5a01deaa6551456a
DOTENV_PUBLIC_KEY="02292a330aa041b5f7efc51504e0c208accba67a6877a217ab43cbb59c3c0c3e66" DOTENV_PUBLIC_KEY="02292a330aa041b5f7efc51504e0c208accba67a6877a217ab43cbb59c3c0c3e66"
# .env # .env
DEBUG="encrypted:BMnswwe5JnAjCOEIHrmuuuOmcSKep3PBL9i1EPP+6/luAaY5Ad696SA6G1xvXV1xSf7CaIemi9y06hBVUD2mL0F1ZWYXB6LAtjQeGzG6/HnWdatUszmLg6eEkXQa5fHC+MkgnII=" DISCORD_BOT_TOKEN="MTQ2MTc3OTk5NjE1NzY3NzY5OQ.GZmKnU.IXzBntbckjKADq-v7Osy-SxaMWsgnCCjFRKm34"
PORT="encrypted:BJxm0HAN4oxgITjzqsung1vfXRfUaHOUac1NPGeQFoKpSrGPmbvfD4fkIREyO+qsD68f+Swp0yCYiB6Z7crRepAxn9qQLK0UGAuI+JHMhRP0PuK/a3FyCMe+9L+XIaMs82SnrFc=" DEBUG="true"
NODE_ENV="encrypted:BKJvsZtYfKMgKzFSA6vBXj2insCZcUZrFUIYdcfd4ze5nG4qpgiOKpiBQQ6EAsrda03/wqV8xfOGfHExVx68+35+tjazC+0Qr/+YBebBvn9MGruLDYB4BeOA8H8Cl1EwW7MCULLoMn1aaS8d" PORT="3002"
LOG_LEVEL="encrypted:BD5xrc2gWbqC7kLwh9Nu9AeJh0+23WMARX878CEpASauF4o4udsLS4qYT1y9ayVHPvWD5Nj+yWhXhDO7/LU+MmtFH9lNS9lnJrZJcMIkTTGh8l854PdXC91RXFHx9xRvVORRcLYt" NODE_ENV="development"
BASE_URL="encrypted:BMHCtunmFrbJgkqEHsYvbulEUkBFfB7HU1eL1Aldm4qKB7ao445FZ4v/tfwjh2P1lG+BLnJkYM3syubLmVwdtJO9JvGlYdQC+TFCtFYiQQAMjK+2pyQljt/NvhlVioHfe/k7jjSNR3IhWEeRmzyPrCHTcUo77tuLkHvGQXFbSQ==" LOG_LEVEL="debug"
EVE_CLIENT_ID="encrypted:BPZqIsv1pNA1W88QK+D4Tn2jJy6Ek/5YZT377LrG8R+zFUk/MIFQ9byCgDMIzsfjAyLwaHpiDggVKLYL7+REgsJ0+Qp8u9jWjOCFtP/Z+HqOnJi5H6ZtWCoWKVOHbMsYyjUD1u6w09hqkWDUSS859UWrno8SnA4O1gNThpawuiID" BASE_URL="https://conciergefreight.space"
EVE_CLIENT_SECRET="encrypted:BCPsdV2aOikGdRsIZrEm+wlYo5c5/XlpCNJYWXDy+I8jYgtHsgCFeRSe7cyjOnMMxs/Wnu54xcBIzu+eOekSe6vzFBTN4DmJKc4TAROmuppUxpyAlhi+ZH6QJXNCix4kHftXVhgolaf8EfpeQYfVSjJAmJVWCF0483KoDdtX0IU1zOkq7as1EzHA6QWP" EVE_CLIENT_ID="ec4eb1bbade045589ec32611f12919dd"
EVE_CALLBACK_URL="encrypted:BLWHVLxXGWYPmX/FAN0GBRq7mne/fjJRql8r0EZuHPrcNzOe9CxnplYlJrnUac6MpicWp81EDc5SKIfkKlDfMOAxQvHlAWQukEN7T4XMOr2LROdtoJPV/mg634foH670ZnIp0SoMrS2jziYCYIP15GjLlBc3uMD1G2lT/L+oYaI9chz4Gi7eJ8Uu04KMK5zTPw==" EVE_CLIENT_SECRET="eat_KF93HYNqLHk3CJ8KijYQJVCcjfjs8EnV_WGG9J"
ESI_USER_AGENT="encrypted:BDSR40896Vx8+5v1VLL+Y1g7AofntT3Hky13zAM/8bO5OizB17WuJS6AGK18FiTKs76ZT7FJd8IOf++OvcPuLLlHAcq4r8W69v1fgK74Y0cpMw3eGd9+iapHGZKQJnTfKWhW33HSl+J1GqNRXCgGfzGN2BdCjDn4t4l/l5C/oSJega3f0zwt5xcLU/cH4meXpHx6CJF4FP0r3QYYY5eWvIPe+kETA4PlSmKcXivnWQA3qLk4P51/q+w=" EVE_CALLBACK_URL="https://dev.conciergefreight.space/auth/callback"
DISCORD_APP_ID="encrypted:BO6M18yRDBLEnb9sVWZM4KJyI6HXPEt6h+g3eJhkAPAiiiZqtftXdJ5kRWH4tbZSnyREiTyKwCZmu/79UEuEKrNM/t0IvVGcYRevkmIkQbcv7pmNdFGULWIuDiXwp7DI65o1Y7Lc+SyTZtF0w6xPn6k+fg==" ESI_USER_AGENT="Concierge Freight DEV/0.0.1 (concierge-freight-dev@f302.me; +https://git.f302.me/jb/star-kitten)"
DISCORD_APP_SECRET="encrypted:BCECawQcSwdBhWZD7u7fTir3vnISlzboluoP7HM4vIcor8HLq5FniVSrrahEi6FQ9/D7GnE1accQFHw5v05DMYGDC6Pk8MteVvNDBsb26D+9ysW+lPMS475mRapiAX5uxsyful61ndlexcbqffYdCbQz3sCCZ0V9T1qL6OmfUDcZ" JANICE_KEY="DUyi5Q3Dod48IoswUBkEfNRs8Qf3cwNN"
DISCORD_PUBLIC_KEY="encrypted:BHiB0kNDdo7jkzGpLNLG7cZhM/x6kHR2xoo9Qq6/UptSCRdTbRIIreUh91nNzs34HKJHuIShS47F1gUF/4AgFawfvosNFWGLysQRw8/BO1jPQ7xkXkOPFvFRjtn8ofAKkLequwcq/tLTJdUnXk32pghLCnLFf+JLYkwZdIiqWNlPEm+DTa2d8GJe9j+ix6fOlI9FWsRo+cY0UPpDKXZ7KgU=" PERPLEXITY_API_KEY="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"
DISCORD_BOT_TOKEN="encrypted:BI+BUi9br2kQ3dkmpLA+ZJG6m0ggwWJuBfsSEFOcaXctqOV9h3obbjbFf37UrKMXk4DdGobFCHWFc2gwygKwIyYV9mt6TSTNT3R3RbxV0wVwJHn66Ln7+Of9RaXQSr3rmLwMrKm23RiBuILTeqNaYdgrj2BJfNvCH4ld73jjglbfM0nrnuNZV3bi3IOiEfDizsLTy9nnVGHyd5hjDoE+LBbN6HH7QxI=" STAR_KITTEN_KV_DB_PATH="data/dev-kv.db"
DISCORD_TEST_GUILD_ID="encrypted:BOtjgCwLkmVwj1T5nqFpiIuf5p4HdRxk0En8PyVPjPR4ICeUCD44brUtcOZveysfadU+UVH0TfWUNmdozmEl1XDs045jaJa4tcQodrEqvUUyW0P0ZvKoRNQsVV/ZnBYcxtSLqPB2OBGKZlQuDy2M50gSPw==" SCOPES=["esi-contracts.read_corporation_contracts.v1","publicData"]
JANICE_KEY="encrypted:BLHC4JqLJ3gjIXK7voNFQV89houZhR/d+3WT6hZZWaADlrTFTcmNl6bB0xd/yCjTUQ4w1SKl5IXptlidICaJpEHqc0vSTVZ7WHzI3QpZvTeUAYPQ6OF1yYKKv5ddwFDDDDTkQkAC+Kv3WMlEaHA05CVMybceQeqgCVal9/+xTTSG" CONCIERGE_DB_PATH="data/concierge-dev.db"
PERPLEXITY_API_KEY="encrypted:BHagAU/l8HMkXMvgQOaz76bIv+kjPBpseTbJf9mRBbJWfGmq5zvI0kQL5OciiCSOIC9E+INPpWC5TrtACTkthrBxwQtq27bEw3QumnvLNn2S9jK/Y50u3iy9j7YL3LcsDd2SmnWSklmADPZP55TbdGOxRJO8EsI4WxYoppL/XLtT6Lwp7FjHpYX8ge7z7ROGhGANB+zf" ADMIN_USER_ID="106614950662791168"
STAR_KITTEN_KV_DB_PATH="encrypted:BBCp6CWMlFZoHM6aWTTJxV8RFpOoSYSwzH7VkHllQgkarnr+pitwAshI4K8JvYGfGLZOmiZshMRrQ1QsK5AbN4tij+rTnRO3yuq1kX5Nbdu1/77FeBZpaA7TXVG1Bj2QovWzdgongEUlew4lJGbv"
SCOPES=encrypted:BDDahsMJtV00qzcrwCfdt4eaLikrMUQXzBU+n82EKWZDzvxPY7G6tifGQC9M3GEIpDCZQSBc5gkjiTspWg/taGRA4CxEAvmYVmiskGZ8t1ZE0RjQ24ulPzfg/R0aFfXZIsB4HTgk85PinRzT2RuxSwfzmz4bwQ1yGGVQRs46Oy5m5hS7LvnBV7jPuWIqixSkawL5n+5hrREFN3Lfpw==
CONCIERGE_DB_PATH="encrypted:BNRvsmopAUFW1qFGJr1UuV0A7+/tZeVD6jhxt2JzZsfkiB8YKFoEOJuJU6k+3NYzIzDMCKdwvTa611u4dEVlWbQQ8yyHTra1YtU5JgZYd+SsPFlA02APnPgy8NN8oMhiCFkdYb1JSq8jDjkLTYbvwwenwJP99Q=="

View File

@@ -5,19 +5,19 @@
DOTENV_PUBLIC_KEY_PRODUCTION="02f0469506f6722d8fcc179c199ff159ca32f082000c8e7a1465891adb50a4c031" DOTENV_PUBLIC_KEY_PRODUCTION="02f0469506f6722d8fcc179c199ff159ca32f082000c8e7a1465891adb50a4c031"
# .env.production # .env.production
DEBUG="encrypted:BJ05zNQ0KPsEKFER9ZlvQxEFJgc5rbw0k4j65AIPgyy/kZkV7prGEyaCtXZLmCUsqtM0NyMMEl7bbLcLeBmr2AbaR0+U7yBIqQnUi46uIV27vZO9fdfCC6Z4SiFaHUXfgl6s1S/Z" DEBUG="false"
PORT="encrypted:BLPq+hz1+WPsCKxKEKFsK+EBvlf4iBwxfsjPN+FFSV078Bk+p8ihS2i5GrXd5JTIW9NJBeT4ZhnL5GXbKY5/iwoj7MmQe9WIYJ+SKBeZXXUyxGGfsE+Hd9u5XWRdbfYJQ8QCnI4=" PORT="3000"
NODE_ENV="encrypted:BE+VACL1v6wLsm3Se5A+xajeH7a6LJ9gj1cdm5R+y6IlG92/p20XU9IBdWqJ00FnMB0cPZfPx2odnSq+TzcqOSYMCWFcgD4nC7suefU08EKa8A2YGxjO2WxkQo/EC7dQO+eIGlWzdimDS98=" NODE_ENV="production"
LOG_LEVEL="encrypted:BNXP0WNyTPrhszuDNaRsE9jFc51VtuUqfCs/EnCaP9iRvXmbekmsQzfbrNPSmHw9HBHWjPbzJUgFfebXgR2qd65L173luLUPOHu0wF5T0zaBc6zt9VdkQbJhdaDWN3FnHkWc4oM=" LOG_LEVEL="info"
BASE_URL="encrypted:BGY3awxPETBuzUz1uP+jJq4u9J9xumGjRGLtccdza6lDPCl7DNf3Tv/GjbfJPH1aXkqvOfGSs6Mj6X2Sv5cNfwJYpP67HoQuNn94g93JjkGesRpkgvLv8pOAB1RaS6F3SkGHosdGOex+wyYeVf5rNhY1vZA7B3SX" BASE_URL="https://starkitten.cafe"
DISCORD_APP_ID="encrypted:BBV+j87Z6p/suAQ4HRdC4VOGyGNUhltobM3yaRLOC7SF0/XBw4bMx/OOpXE5qqfQdeyAhTpkEEzwH1BzaIiAZFJouMSyKYN/Gw1rbkB9LEzN9Yz6SuCZaub4ftwzZW5pJ8adzSjfm9JLFegmMO8MzJkoZU4=" DISCORD_APP_ID="1288711114388930601"
DISCORD_APP_SECRET="encrypted:BLC+chabTKr/7iLjutqOlA8r9vAn3DkGN14fUxgjRGs7udyvXUKXDYsVd8SQPC5/iraYL23+Qw8PBTnTh2P8SRq4tQq/jO0H8KHrJY+DfgjJqt2f3KK19rFvDvvEBWtvFIXwF1PrWcCrIF0T3IYn1Nq9/KRED6pbjK/HERF+q4RC" DISCORD_APP_SECRET="HYK03ffTN3Cl7c0p4jqo2wl0y_AD4EQ-"
DISCORD_PUBLIC_KEY="encrypted:BAv92AM4VtQdyAqtLiCeFRuaMZ+6cazOMCNr6454p3PLIZDiMAbYEPzzIqyYZFWzMUJDTXx6c91I7dX33UZKG5vIB/tGiUrvHIRgnXXsbz4ZwXXYRZ0gDKzAFFyDaNk95RO8gZdvRdAAVUlTO/t2wlwEmGVj61jULNIdtuQBMa8tdl9XkhSAoq8O3oiHeKCPCCKU9QuiUJReU22KwZ0rPIk=" DISCORD_PUBLIC_KEY="447bb2c27ad4127eba078b74f84c058205787df36b90e63de8b19e045fb9307f"
DISCORD_BOT_TOKEN="encrypted:BOafG2kHKOp209oFlXUURj3yt7JLIOJbD9dChXFY1GKJMjV63LFBhyjZkpZsrXjcrc3r/FR026UlTiO1SIDxBLlHlla2yN3ip+jLl2wAD8jJWsch+HrQPH34G9C4Peo56wIptiUIr6ug9PqHqjAE5WClEJTFwSPPHgx1btHpoyxgWnqe7h0tbc2talmfOS/8xvJ+9TKRbL165MX/+HjPJI9+7kMqrHGNJA==" DISCORD_BOT_TOKEN="MTI4ODcxMTExNDM4ODkzMDYwMQ.GqwYGA.EzZZP7heEHTkH7jrxFTp7FhIlnXT06AUhYLKHE"
EVE_CLIENT_ID="encrypted:BPSEia/l0Aea+iX3Q5citAbtxkTBIFlBRwNhxoV4BVT4rbmGr0heJLb9ymS3srfHhlh6kra2oZzpH15UVyISL6lTxSi72CsvgsvX9cO8GdCUywSC94XBDLV5XjGMQ4vuL3ce3KDaWW+di28+7sxttAmU/b97F+547wpFkFnjb0ir" EVE_CLIENT_ID="3e12fdcfe611408d9cb499b0795b9fac"
EVE_CLIENT_SECRET="encrypted:BGru3muBXbNenhZ+e4259tQOqELbhogNa5x0Yxxw2gbj7uiMb/KzzeaJ8WTBNFrlhS4NLKRE+EwAZp1LRKZVXMVAgCoF465c5zDZrHKaBi5SEjDnffKZOLzcpOeZgTbPMfFexGZqWuFgTtP2Bn2bu0p1MxXX5uEj++ZK2IfEONbHXzUnWRQYUts=" EVE_CLIENT_SECRET="b7ex0i8ZOLFWEaRThSFVCXk5KV7Z16NEbhneCXRk"
EVE_CALLBACK_URL="encrypted:BCHObZ6cAfm/V79x2fhqnAAzinxyFpiRiQY/wojKQ5QJS8KEJ1FCc89Ee5tVBXDDxFRPaBwkj/g4blKpKWAWLl7s3LCZJCYpPoPIkrDOOMop1JFAMnVGrLbK6Ird2agVc+SkMbjUurffQ7pLrdhNQKK0y7vW5K6DzsoMu7klq7QiUFBbcfKMW5E5" EVE_CALLBACK_URL="https://starkitten.cafe/api/auth/callback"
ESI_USER_AGENT="encrypted:BC6tfyTm69Id4WT/csv81UxUUtmpZKoTwcV1HoZ1xSrx8+tJMIxnFVL4SxMcEa1pQXgpKgDDpSvoAaFZwndRHxSTZvfFvpoIZlUaljzzAdevUGh3+OhCFGvx9y8YwrlT4LB/L412sZD6NhgCX6rksU1iYREexj+7Kc54/sHsD7zYAIJ9y+PU+gvRDejx32oEhBEOdksnKplaTq2ApF3NCEBWt9eiB2rho6eltro=" ESI_USER_AGENT="Star Kitten/0.0.1 (star-kitten@f302.me; +https://git.f302.me/jb/star-kitten)"
AUTH_DB_PATH="encrypted:BO7oCtnSoclMPTL8j/8HqQe+6p5+u4xWtEuScqPV+u1Wr/bPls9rd8DSohIwe0Y00nnhi/oSqnExCB0ip3rmQ1YA62ZfFxvmOmHwgk1MNHfCG6bE3NurHR2NE4BdDCvh+yOQ8LcN04V+Ef+tkyjKBD241H3MYmdw" AUTH_DB_PATH="/var/lib/litefs/auth.db"
JANICE_KEY="encrypted:BO4yawcMyniT7HH8apRtRv8uwNBFuQPRz3o8FPu7viTO+uGNMVPmoRKwI+mDjFc9JHRiIsnyOvjiOzDuojdWvoyKuilNKwpyuzkTCqjd2G7YaaYnurOkLZSllb2US/BvhN4Put04aqyGwpXyq2Ns34z080TjE0Q3oIJwgI6fSfR6" JANICE_KEY="DUyi5Q3Dod48IoswUBkEfNRs8Qf3cwNN"
PERPLEXITY_API_KEY="encrypted:BCY8v0hPEk0n6VhTJuJZeff9XOZrwqqK77UqgF5PLTfwfiKUHLRUbj3e84FydRFGTRvRx3a0QqP2PAf0JgqCt5B9Xdop2curOTptmc2Z9wDoshMFl0X15xXQzFz4kMmeb3P1uJtB9RVsU1BMGMtX76wNcW9+vsNzu37PW+s0OrIJlXw3QicPYybzenQT6KUl9IMTkP+X" PERPLEXITY_API_KEY="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"

View File

@@ -14,7 +14,7 @@
}, },
"dependencies": { "dependencies": {
"@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev", "@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev",
"@star-kitten/lib": "workspace:^0.0.0" "@star-kitten/lib": "workspace:*"
}, },
"scripts": { "scripts": {
"dev": "bunx dotenvx run -f .env.development -- bun run --watch src/main.ts", "dev": "bunx dotenvx run -f .env.development -- bun run --watch src/main.ts",

View File

@@ -0,0 +1,126 @@
import { getDB } from '@/lib/db';
import { Constants } from '@projectdysnomia/dysnomia';
import {
createChatCommand,
integerOption,
stringOption,
subCommandGroupOption,
subCommandRouter,
type CommandContext,
type ExecutableInteraction,
} from '@star-kitten/lib/discord';
import { numberOption, subCommandOption } from '@star-kitten/lib/discord';
export default createChatCommand(
{
name: 'route',
description: 'Routes',
defaultMemberPermissions: Constants.Permissions.administrator,
options: [
subCommandGroupOption({
name: 'group',
description: 'a group',
options: [
subCommandOption({
name: 'add',
description: 'add a route',
options: [
stringOption({
name: 'start',
description: 'starting location',
autocomplete: true,
required: true,
}),
stringOption({
name: 'end',
description: 'end location',
autocomplete: true,
required: true,
}),
integerOption({
name: 'isk-per-m3',
description: 'ISK per m3',
required: true,
}),
numberOption({
name: 'collateral-percent',
description: 'percentage of collateral to add onto the cost.',
required: true,
}),
integerOption({
name: 'max-volume',
description: 'Maximum volume allowed for this route',
required: true,
}),
integerOption({
name: 'min-reward',
description: 'Minimum required reward for this route',
required: true,
}),
integerOption({
name: 'expiration',
description: 'Expiration the client should set on the contract',
required: true,
}),
integerOption({
name: 'completion',
description: 'Days to complete time the client should set on the contract',
required: true,
}),
integerOption({
name: 'max-collateral',
description: 'Maximum collateral allowed for this route',
}),
],
}),
subCommandOption({
name: 'remove',
description: 'remove a route',
options: [
integerOption({
name: 'id',
description: 'ID of the route to remove',
required: true,
}),
],
}),
],
}),
],
},
subCommandRouter({
group: {
add: async (interaction, ctx, data) => {
console.log(`in add`);
if (interaction.isAutocomplete()) {
const focused = data.options?.find((opt) => opt.focused);
console.log(`focused`, focused);
if (focused) {
switch (focused.name) {
case 'start': {
const locations = getDB().getAllLocations();
console.log(JSON.stringify(locations.length));
return await interaction.result(
locations.map((l) => ({ name: l.short_name, value: String(l.location_id) })),
);
}
case 'end': {
const locations = getDB().getAllLocations();
console.log(JSON.stringify(locations.length));
return await interaction.result(
locations.map((l) => ({ name: l.short_name, value: String(l.location_id) })),
);
}
}
}
}
},
remove: (interaction, ctx) => {
console.log('remove handler');
if (interaction.isApplicationCommand()) {
interaction.createMessage(`Thanks`);
}
},
},
}),
);

View File

@@ -0,0 +1,4 @@
import './locations/command';
import './quoute.command';
import './time.command';
import './create-route.command';

View File

@@ -1,220 +0,0 @@
import { componentHasIdPrefix, isModalLabel, text } from '@star-kitten/lib/discord/components';
import { createChatCommand, type CommandContext, type ExecutableInteraction } from '@star-kitten/lib/discord';
import { PageType, usePages } from '@star-kitten/lib/discord/pages';
import { StructureType, type Location } from '@/lib/db/location';
import { getDB } from '@/lib/db';
import { Constants, type ComponentInteractionSelectMenuData } from '@projectdysnomia/dysnomia';
interface LocationsState {
selected?: Location;
}
export default createChatCommand(
{
name: 'locations',
description: 'location management',
},
async (interaction: ExecutableInteraction, commandCtx: CommandContext) => {
await usePages<LocationsState>(
{
pages: {
main: {
key: 'main',
type: PageType.MESSAGE,
render: async (pageCtx) => {
const locations = getDB().getAllLocations();
console.log('Rendering locations page with locations:', locations);
const renderLocations = () => {
if (locations.length === 0) {
return 'No locations added yet.';
}
return locations
.map(
(loc) =>
`${loc.location_id}\t${loc.short_name}\t${loc.can_jf ? 'JF' : ''}${loc.can_dst ? ' DST' : ''}${loc.can_br ? ' BR' : ''}${loc.can_smb ? ' SMB' : ''}${loc.can_bridge ? ' BRIDGE' : ''}`,
)
.join('\n');
};
return (
<container accent={0x11cc33}>
<text>{`# Locations\n${renderLocations()}`}</text>
<actionRow>
<stringSelect
customId="edit-services"
placeholder="Select Location to Edit Services"
minValues={1}
maxValues={1}
>
{locations.map((loc) => (
<option label={loc.short_name} value={loc.location_id.toString()} />
))}
</stringSelect>
</actionRow>
<actionRow>
<button customId="add-location" label="Add Location" style={Constants.ButtonStyles.PRIMARY} />
</actionRow>
</container>
);
},
},
'add-location': {
key: 'add-location',
type: PageType.MODAL,
render: async (ctx) => {
return (
<modal title="Add Location" customId="add-location-modal">
<label label="Location Name">
<textInput customId="location-name" placeholder="Enter the location name" />
</label>
<label label="Location Short Name">
<textInput customId="location-short-name" placeholder="Enter the location short name" />
</label>
<label label="Structure Type">
<stringSelect
customId="structure-type"
placeholder="Select Structure Type"
minValues={1}
maxValues={1}
>
{Object.values(StructureType).map((type) => (
<option label={type} value={type} />
))}
</stringSelect>
</label>
</modal>
);
},
},
'edit-services': {
key: 'edit-services',
type: PageType.MODAL,
render: async (ctx) => {
return (
<modal
title={`Edit Location Services at ${ctx.state.data.selected?.short_name || ''}:`}
customId="edit-services-modal"
>
<label label="Can JF">
<stringSelect customId="can-jf" placeholder="Can JF" minValues={1} maxValues={1}>
<option label="Yes" value="yes" />
<option label="No" value="no" />
</stringSelect>
</label>
<label label="Can DST">
<stringSelect customId="can-dst" placeholder="Can DST" minValues={1} maxValues={1}>
<option label="Yes" value="yes" />
<option label="No" value="no" />
</stringSelect>
</label>
<label label="Can BR">
<stringSelect customId="can-br" placeholder="Can BR" minValues={1} maxValues={1}>
<option label="Yes" value="yes" />
<option label="No" value="no" />
</stringSelect>
</label>
<label label="Can SMB">
<stringSelect customId="can-smb" placeholder="Can SMB" minValues={1} maxValues={1}>
<option label="Yes" value="yes" />
<option label="No" value="no" />
</stringSelect>
</label>
<label label="Can Bridge">
<stringSelect customId="can-bridge" placeholder="Can Bridge" minValues={1} maxValues={1}>
<option label="Yes" value="yes" />
<option label="No" value="no" />
</stringSelect>
</label>
</modal>
);
},
},
},
router: (ctx) => {
if (ctx.custom_id === 'add-location-modal') {
// Handle modal submission
if (!interaction.isModalSubmit()) {
throw new Error('Expected a modal submit interaction for add-location-modal');
}
let locationName = ctx.interaction.data.components.find(
(comp) => isModalLabel(comp) && componentHasIdPrefix(comp.component, 'location-name'),
)?.component.value;
let locationShortName = ctx.interaction.data.components.find(
(comp) => isModalLabel(comp) && componentHasIdPrefix(comp.component, 'location-short-name'),
)?.component.value;
let structureTypeValue = ctx.interaction.data.components.find(
(comp) => isModalLabel(comp) && componentHasIdPrefix(comp.component, 'structure-type'),
)?.component as ComponentInteractionSelectMenuData;
let structureType = structureTypeValue ? (structureTypeValue.values[0] as StructureType) : undefined;
if (locationName && locationShortName && structureType) {
getDB().addLocation({
name: locationName,
short_name: locationShortName,
structure_type: structureType,
});
}
return 'main';
}
if (ctx.custom_id === 'add-location') {
ctx.state.data.selected = getDB().getLocationById(ctx.interaction.data.values[0]);
return 'add-location';
}
if (ctx.custom_id === 'edit-services') {
if (!ctx.interaction.isMessageComponent()) {
throw new Error('Expected a message component interaction for edit-services');
}
const data = ctx.interaction.data as ComponentInteractionSelectMenuData;
const locationId = Number.parseInt(data.values[0]);
const location = getDB().getLocationById(locationId);
if (location) {
ctx.state.data.selected = location;
return 'edit-services';
}
}
if (ctx.custom_id === 'edit-services-modal') {
// Handle modal submission
if (!interaction.isModalSubmit()) {
throw new Error('Expected a modal submit interaction for edit-services-modal');
}
const location = ctx.state.data.selected;
if (!location) {
return 'main';
}
const getServiceValue = (serviceId: string) => {
const comp = ctx.interaction.data.components.find(
(c) => isModalLabel(c) && componentHasIdPrefix(c.component, serviceId),
)?.component as ComponentInteractionSelectMenuData;
return comp ? comp.values[0] === 'yes' : false;
};
const can_jf = getServiceValue('can-jf');
const can_dst = getServiceValue('can-dst');
const can_br = getServiceValue('can-br');
const can_smb = getServiceValue('can-smb');
const can_bridge = getServiceValue('can-bridge');
getDB().updateLocation({
...location,
can_jf,
can_dst,
can_br,
can_smb,
can_bridge,
});
}
return 'main';
},
initialPage: 'main',
ephemeral: true,
},
interaction,
commandCtx,
);
},
);

View File

@@ -0,0 +1,48 @@
import type { PageContext } from '@star-kitten/lib/discord';
import type { LocationsState } from './state';
import { Page } from './router';
import { StructureType } from '@/lib/db/types/routes';
export default async function (ctx: PageContext<LocationsState>) {
const isAdd = ctx.custom_id === Page.addLocationModal;
const location = ctx.state.data.selected;
return (
<modal
title={`${isAdd ? 'Add Location' : 'Edit: ' + ctx.state.data.selected?.short_name || ''}`}
customId={isAdd ? Page.addLocationModalSubmit : Page.editLocationModalSubmit}
>
{isAdd && (
<label label="Location ID">
<textInput customId="loc-id" placeholder="Enter the structure id" required />
</label>
)}
<label label="Location Name">
<textInput customId="loc-name" placeholder="Enter the location name" required value={location?.name} />
</label>
<label label="Location Short Name">
<textInput
customId="loc-short-name"
placeholder="Enter the location short name"
required
value={location?.short_name}
/>
</label>
<label label="System">
<textInput customId="loc-system" placeholder="Enter the system (e.g. Jita)" required value={location?.system} />
</label>
<label label="Structure Type">
<stringSelect
customId="loc-structure-type"
placeholder="Select Structure Type"
minValues={1}
maxValues={1}
required
>
{Object.values(StructureType).map((type) => (
<option label={type} value={type} default={location?.structure_type === type} />
))}
</stringSelect>
</label>
</modal>
);
}

View File

@@ -0,0 +1,62 @@
import {
createChatCommand,
type CommandContext,
type ExecutableInteraction,
PageType,
usePages,
hasUserId,
PermissionType,
} from '@star-kitten/lib/discord';
import mainPage from './main.page';
import addLocationModal from './add-location.modal';
import editServicesModal from './edit-services.modal';
import removeLocationModal from './remove-location.modal';
import type { LocationsState } from './state';
import router, { Page } from './router';
import { Constants } from '@projectdysnomia/dysnomia';
export default createChatCommand(
{
name: 'locations',
description: 'location management',
defaultMemberPermissions: Constants.Permissions.administrator,
},
async (interaction: ExecutableInteraction, commandCtx: CommandContext) => {
await usePages<LocationsState>(
{
pages: {
[Page.main]: {
key: Page.main,
type: PageType.MESSAGE,
render: mainPage,
},
[Page.addLocationModal]: {
key: Page.addLocationModal,
type: PageType.MODAL,
render: addLocationModal,
},
[Page.editLocationModal]: {
key: Page.editLocationModal,
type: PageType.MODAL,
render: addLocationModal,
},
[Page.editServicesModal]: {
key: Page.editServicesModal,
type: PageType.MODAL,
render: editServicesModal,
},
[Page.removeLocationModal]: {
key: Page.removeLocationModal,
type: PageType.MODAL,
render: removeLocationModal,
},
},
router,
initialPage: Page.main,
ephemeral: true,
},
interaction,
commandCtx,
);
},
);

View File

@@ -0,0 +1,46 @@
import type { PageContext } from '@star-kitten/lib/discord';
import type { LocationsState } from './state';
import { Page } from './router';
import { locationSupportsType, RouteType } from '@/lib/db/types/routes';
export default function (ctx: PageContext<LocationsState>) {
const location = ctx.state.data.selected!;
return (
<modal title={`Services: ${ctx.state.data.selected?.short_name || ''}`} customId={Page.editServicesModalSubmit}>
<label label="Can JF">
<stringSelect customId="can-jf" placeholder="Can JF" minValues={1} maxValues={1}>
<option label="Yes" value={RouteType.JF + ''} default={locationSupportsType(location, RouteType.JF)} />
<option label="No" value="0" default={!locationSupportsType(location, RouteType.JF)} />
</stringSelect>
</label>
<label label="Can DST">
<stringSelect customId="can-dst" placeholder="Can DST" minValues={1} maxValues={1}>
<option label="Yes" value={RouteType.DST + ''} default={locationSupportsType(location, RouteType.DST)} />
<option label="No" value="0" default={!locationSupportsType(location, RouteType.DST)} />
</stringSelect>
</label>
<label label="Can BR">
<stringSelect customId="can-br" placeholder="Can BR" minValues={1} maxValues={1}>
<option label="Yes" value={RouteType.BR + ''} default={locationSupportsType(location, RouteType.BR)} />
<option label="No" value="0" default={!locationSupportsType(location, RouteType.BR)} />
</stringSelect>
</label>
<label label="Can SMB">
<stringSelect customId="can-smb" placeholder="Can SMB" minValues={1} maxValues={1}>
<option label="Yes" value={RouteType.SMB + ''} default={locationSupportsType(location, RouteType.SMB)} />
<option label="No" value="0" default={!locationSupportsType(location, RouteType.SMB)} />
</stringSelect>
</label>
<label label="Can Bridge">
<stringSelect customId="can-bridge" placeholder="Can Bridge" minValues={1} maxValues={1}>
<option
label="Yes"
value={RouteType.BRIDGE + ''}
default={locationSupportsType(location, RouteType.BRIDGE)}
/>
<option label="No" value="0" default={!locationSupportsType(location, RouteType.BRIDGE)} />
</stringSelect>
</label>
</modal>
);
}

View File

@@ -0,0 +1,78 @@
import { ButtonStyle, type PageContext } from '@star-kitten/lib/discord';
import type { LocationsState } from './state';
import { getDB } from '@/lib/db';
import { Page } from './router';
import { locationSupportsType, RouteType } from '@/lib/db/types/routes';
export default function (ctx: PageContext<LocationsState>) {
const locations = getDB().getAllLocations();
const hasLocations = locations.length > 0;
const renderLocations = () => {
if (locations.length === 0) {
return 'No locations added yet.';
}
return locations
.map(
(loc) =>
`${loc.location_id}\t|\t${loc.short_name}\t|\t${locationSupportsType(loc, RouteType.JF) ? 'JF' : ''}${locationSupportsType(loc, RouteType.DST) ? ', DST' : ''}${locationSupportsType(loc, RouteType.BR) ? ', BR' : ''}${locationSupportsType(loc, RouteType.SMB) ? ', SMB' : ''}${locationSupportsType(loc, RouteType.BRIDGE) ? ', BRIDGE' : ''}`,
)
.join('\n');
};
if (!hasLocations) {
return (
<container accent={0x11cc33}>
<text>{`# Locations\nNo locations added yet.`}</text>
<actionRow>
<button customId={Page.addLocationModal} label="Add Location" style={ButtonStyle.PRIMARY} />
</actionRow>
</container>
);
}
const locationOptions = locations.map((loc) => <option label={loc.short_name} value={loc.location_id.toString()} />);
return (
<container accent={0x11cc33}>
<text>{`# Locations\n${renderLocations()}`}</text>
<actionRow>
<button customId={Page.addLocationModal} label="Add Location" style={ButtonStyle.PRIMARY} />
</actionRow>
<text>{`## Edit services at`}</text>
<actionRow>
<stringSelect
customId={Page.editServicesModal}
placeholder="Select location to edit services"
minValues={1}
maxValues={1}
>
{locationOptions}
</stringSelect>
</actionRow>
<text>{`## Edit location details`}</text>
<actionRow>
<stringSelect
customId={Page.editLocationModal}
placeholder="Select location to edit"
minValues={1}
maxValues={1}
>
{locationOptions}
</stringSelect>
</actionRow>
<text>{`## Remove location`}</text>
<actionRow>
<stringSelect
customId={Page.removeLocationModal}
placeholder="Select location to remove"
minValues={1}
maxValues={1}
>
{locationOptions}
</stringSelect>
</actionRow>
</container>
);
}

View File

@@ -0,0 +1,11 @@
import type { PageContext } from '@star-kitten/lib/discord';
import type { LocationsState } from './state';
import { Page } from './router';
export default function (ctx: PageContext<LocationsState>) {
return (
<modal title={`Remove ${ctx.state.data.selected?.short_name || ''}?`} customId={Page.removeLocationModalSubmit}>
<text>{`# Are you sure?\n\nConfrim that you want remove **${ctx.state.data.selected.name}**.\n\n*This action cannot be undone. Click submit to confirm.*`}</text>
</modal>
);
}

View File

@@ -0,0 +1,140 @@
import * as StarKitten from '@star-kitten/lib/discord';
import type { LocationsState } from './state';
import { getDB } from '@/lib/db';
import type { StructureType } from '@/lib/db/types/routes';
export enum Page {
main = 'main',
addLocationModal = 'add-location-modal',
addLocationModalSubmit = 'add-location-modal-submit',
editLocationModal = 'edit-location-modal',
editLocationModalSubmit = 'edit-location-modal-submit',
editServicesModal = 'edit-services-modal',
editServicesModalSubmit = 'edit-services-modal-submit',
removeLocationModal = 'remove-location-modal',
removeLocationModalSubmit = 'remove-location-modal-submit',
}
export default function (ctx: StarKitten.PageContext<LocationsState>): Page {
switch (ctx.custom_id) {
case Page.addLocationModal:
ctx.state.data.selected = undefined;
return Page.addLocationModal;
case Page.editLocationModalSubmit:
case Page.addLocationModalSubmit: {
if (!ctx.interaction.isModalSubmit()) {
throw new Error('Expected a modal submit interaction.');
}
const location: any = {};
for (const component of ctx.interaction.data.components) {
if (StarKitten.isModalLabel(component)) {
if (StarKitten.isModalTextInput(component.component)) {
if (StarKitten.componentHasIdPrefix(component.component, 'loc-id')) {
location.location_id = component.component.value.trim();
} else if (StarKitten.componentHasIdPrefix(component.component, 'loc-name')) {
location.name = component.component.value.trim();
} else if (StarKitten.componentHasIdPrefix(component.component, 'loc-short-name')) {
location.short_name = component.component.value.trim();
} else if (StarKitten.componentHasIdPrefix(component.component, 'loc-system')) {
location.system = component.component.value.trim();
}
} else if (
StarKitten.isStringSelectMenu(component.component) &&
StarKitten.componentHasIdPrefix(component.component, 'loc-structure-type')
) {
location.structure_type = component.component.values[0] as StructureType;
}
}
}
ctx.custom_id === Page.addLocationModalSubmit ? getDB().addLocation(location) : getDB().updateLocation(location);
ctx.state.data.selected = undefined;
return Page.main;
}
case Page.editLocationModal: {
if (!ctx.interaction.isSelectMenu()) {
console.error('Expected a message component interaction.');
return Page.main;
}
const data = ctx.interaction.data;
const locationId = Number.parseInt(data.values[0]);
const location = getDB().getLocationById(locationId);
if (location) {
ctx.state.data.selected = location;
return Page.editLocationModal;
}
return Page.main;
}
case Page.editServicesModal: {
if (!ctx.interaction.isSelectMenu()) {
console.error('Expected a message component interaction.');
return Page.main;
}
const data = ctx.interaction.data;
const locationId = Number.parseInt(data.values[0]);
const location = getDB().getLocationById(locationId);
if (location) {
ctx.state.data.selected = location;
return Page.editServicesModal;
}
return Page.main;
}
case Page.editServicesModalSubmit: {
if (ctx.interaction.isModalSubmit()) {
const location = ctx.state.data.selected;
if (!location) {
return Page.main;
}
let supported_route_types = 0;
for (const component of ctx.interaction.data.components) {
if (StarKitten.isModalLabel(component) && StarKitten.isStringSelectMenu(component.component)) {
supported_route_types = supported_route_types | parseInt(component.component.values[0]);
}
}
getDB().updateLocation({
...location,
supported_route_types,
});
}
ctx.state.data.selected = undefined;
return Page.main;
}
case Page.removeLocationModal: {
if (!ctx.interaction.isSelectMenu()) {
console.error('Expected a message component interaction.');
return Page.main;
}
const data = ctx.interaction.data;
const locationId = Number.parseInt(data.values[0]);
const location = getDB().getLocationById(locationId);
if (location) {
ctx.state.data.selected = location;
return Page.removeLocationModal;
}
return Page.main;
}
case Page.removeLocationModalSubmit: {
if (ctx.interaction.isModalSubmit()) {
const location = ctx.state.data.selected;
if (!location) {
return Page.main;
}
getDB().removeLocation(location.location_id);
}
ctx.state.data.selected = undefined;
return Page.main;
}
default:
return Page.main;
}
}

View File

@@ -0,0 +1,5 @@
import type { Location } from '@/lib/db';
export interface LocationsState {
selected?: Location;
}

View File

@@ -4,15 +4,9 @@ import {
type ComponentInteractionSelectMenuData, type ComponentInteractionSelectMenuData,
} from '@projectdysnomia/dysnomia'; } from '@projectdysnomia/dysnomia';
import { appraiseItems, type Appraisal } from '@star-kitten/lib/eve/third-party/janice.js'; import { appraiseItems, type Appraisal } from '@star-kitten/lib/eve/third-party/janice.js';
import { import { componentHasIdPrefix, isModalLabel, isModalTextInput } from '@star-kitten/lib/discord';
componentHasIdPrefix, import { createChatCommand, type CommandContext, type ExecutableInteraction } from '@star-kitten/lib/discord';
isModalLabel,
isModalSelect,
isModalTextInput,
} from '@star-kitten/lib/discord/components';
import type { CommandContext, ExecutableInteraction } from '@star-kitten/lib/discord';
import { PageType, usePages } from '@star-kitten/lib/discord/pages'; import { PageType, usePages } from '@star-kitten/lib/discord/pages';
import { serve } from 'bun';
// import { renderAppraisal } from './renderAppraisal'; // import { renderAppraisal } from './renderAppraisal';
// import { renderAppraisalModal } from './renderAppraisalModal'; // import { renderAppraisalModal } from './renderAppraisalModal';
@@ -131,7 +125,7 @@ function uniqueDestinationForOriginAndType(typeId: number, originId?: number) {
} }
async function execute(interaction: ExecutableInteraction, ctx: CommandContext) { async function execute(interaction: ExecutableInteraction, ctx: CommandContext) {
return await usePages<QuouteState>( await usePages<QuouteState>(
{ {
pages: { pages: {
main: { main: {
@@ -242,7 +236,4 @@ Mexallon 2444`}
); );
} }
export default { export default createChatCommand(definition, execute);
definition,
execute,
};

View File

@@ -1,11 +1,19 @@
import { import { type ExecutableInteraction, type CommandContext, Locale, createChatCommand } from '@star-kitten/lib/discord';
type ExecutableInteraction,
type CommandContext,
Locale,
type ChatCommandDefinition,
} from '@star-kitten/lib/discord';
const definition: ChatCommandDefinition = { const eveTimeText = {
[Locale.EN_US]: 'EVE Time',
[Locale.EN_GB]: 'EVE Time',
[Locale.DE]: 'EVE-Zeit',
[Locale.ES_ES]: 'Hora EVE',
[Locale.FR]: "Heure d'EVE",
[Locale.JA]: 'EVE時間',
[Locale.KO]: 'EVE 시간',
[Locale.RU]: 'Время EVE',
[Locale.ZH_CN]: 'EVE时间',
};
export default createChatCommand(
{
name: 'time', name: 'time',
nameLocalizations: { nameLocalizations: {
[Locale.DE]: 'zeit', [Locale.DE]: 'zeit',
@@ -26,28 +34,8 @@ const definition: ChatCommandDefinition = {
[Locale.RU]: 'Получите текущее время EVE', [Locale.RU]: 'Получите текущее время EVE',
[Locale.ZH_CN]: '获取当前的EVE时间', [Locale.ZH_CN]: '获取当前的EVE时间',
}, },
}; },
(interaction: ExecutableInteraction, ctx: CommandContext) => {
const eveTimeText = {
[Locale.EN_US]: 'EVE Time',
[Locale.EN_GB]: 'EVE Time',
[Locale.DE]: 'EVE-Zeit',
[Locale.ES_ES]: 'Hora EVE',
[Locale.FR]: "Heure d'EVE",
[Locale.JA]: 'EVE時間',
[Locale.KO]: 'EVE 시간',
[Locale.RU]: 'Время EVE',
[Locale.ZH_CN]: 'EVE时间',
};
function jsx(component: any) {
return {
flags: 2,
components: [component],
};
}
async function execute(interaction: ExecutableInteraction, ctx: CommandContext) {
if (!interaction.isApplicationCommand()) return; if (!interaction.isApplicationCommand()) return;
const now = new Date(); const now = new Date();
@@ -69,9 +57,5 @@ ${eveDate}`}
</text> </text>
</container>, </container>,
); );
} },
);
export default {
definition,
execute,
};

View File

@@ -1,5 +1,6 @@
import { Database } from 'bun:sqlite'; import { Database } from 'bun:sqlite';
import locationTables, * as locationQueries from './location'; import locationTables, * as locationQueries from './location';
export * from './location';
let db: Database = undefined; let db: Database = undefined;
const queries = { const queries = {

View File

@@ -1,44 +1,19 @@
import type { Database } from 'bun:sqlite'; import type { Database } from 'bun:sqlite';
import { dynamicInsert, dynamicUpdate, remove, select, type QueryOptions } from '@star-kitten/lib/util/sqlite.js';
import type { Location } from './types/routes';
const TABLE_NAME = 'locations'; const TABLE_NAME = 'locations';
export enum StructureType {
NPC = 'NPC',
Keepstar = 'Keepstar',
Fortizar = 'Fortizar',
Astrahus = 'Astrahus',
Sotiyo = 'Sotiyo',
Azbel = 'Azbel',
Raitaru = 'Raitaru',
Athanor = 'Athanor',
Tatara = 'Tatara',
}
export interface Location {
location_id: number;
name: string;
short_name: string;
structure_type: StructureType;
can_jf?: boolean;
can_dst?: boolean;
can_br?: boolean;
can_smb?: boolean;
can_bridge?: boolean;
}
export default { export default {
createTable: (db: Database) => { createTable: (db: Database) => {
db.run( db.run(
`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( `CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
location_id INTEGER PRIMARY KEY AUTOINCREMENT, location_id INTEGER PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
short_name TEXT NOT NULL, short_name TEXT NOT NULL,
structure_type TEXT NOT NULL, structure_type TEXT NOT NULL,
can_jf BOOLEAN NOT NULL DEFAULT 0, system TEXT NOT NULL,
can_dst BOOLEAN NOT NULL DEFAULT 0, supported_route_types INT NOT NULL DEFAULT 0
can_br BOOLEAN NOT NULL DEFAULT 0,
can_smb BOOLEAN NOT NULL DEFAULT 0,
can_bridge BOOLEAN NOT NULL DEFAULT 0
)`, )`,
); );
}, },
@@ -48,56 +23,24 @@ export default {
}, },
}; };
export function addLocation(db: Database, location: Omit<Location, 'location_id'>) { export function addLocation(db: Database, location: Location) {
const stmt = db.prepare( return dynamicInsert(db, TABLE_NAME, location);
`INSERT INTO ${TABLE_NAME} (name, short_name, structure_type, can_jf, can_dst, can_br, can_smb, can_bridge)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
);
const result = stmt.run(
location.name,
location.short_name,
location.structure_type,
location.can_jf ? 1 : 0,
location.can_dst ? 1 : 0,
location.can_br ? 1 : 0,
location.can_smb ? 1 : 0,
location.can_bridge ? 1 : 0,
);
return result.lastInsertRowid as number;
} }
export function updateLocation(db: Database, location: Location) { export function updateLocation(db: Database, location: Location) {
const stmt = db.prepare( const id = location.location_id;
`UPDATE ${TABLE_NAME} delete location.location_id;
SET name = ?, short_name = ?, structure_type = ?, can_jf = ?, can_dst = ?, can_br = ?, can_smb = ?, can_bridge = ? return dynamicUpdate(db, TABLE_NAME, location, 'location_id', id);
WHERE location_id = ?`,
);
stmt.run(
location.name,
location.short_name,
location.structure_type,
location.can_jf ? 1 : 0,
location.can_dst ? 1 : 0,
location.can_br ? 1 : 0,
location.can_smb ? 1 : 0,
location.can_bridge ? 1 : 0,
location.location_id,
);
} }
export function getLocationById(db: Database, locationId: number): Location | null { export function getLocationById(db: Database, location_id: number) {
const stmt = db.prepare(`SELECT * FROM ${TABLE_NAME} WHERE location_id = ?`); return select<Location>(db, TABLE_NAME, {}, '*', { location_id })?.[0];
const row = stmt.get(locationId) as Location | undefined;
return row || null;
} }
export function getAllLocations(db: Database): Location[] { export function getAllLocations(db: Database, options?: QueryOptions<Location>): Location[] {
const stmt = db.prepare(`SELECT * FROM ${TABLE_NAME}`); return select<Location>(db, TABLE_NAME, options);
const rows = stmt.all() as Location[];
return rows;
} }
export function deleteLocation(db: Database, locationId: number) { export function removeLocation(db: Database, location_id: number) {
const stmt = db.prepare(`DELETE FROM ${TABLE_NAME} WHERE location_id = ?`); return remove<Location>(db, TABLE_NAME, { location_id });
stmt.run(locationId);
} }

View File

@@ -0,0 +1,51 @@
import type { Database } from 'bun:sqlite';
import { dynamicInsert, dynamicUpdate, remove, select, type QueryOptions } from '@star-kitten/lib/util/sqlite.js';
import type { Route } from './types/routes';
const TABLE_NAME = 'routes';
export default {
createTable: (db: Database) => {
db.run(
`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
route_id INTEGER PRIMARY KEY AUTOINCREMENT,
start_location_id INTEGER NOT NULL,
end_location_id INTEGER NOT NULL,
isk_per_m3 INTEGER NOT NULL,
collat_pct REAL NOT NULL,
max_volume INTEGER NOT NULL,
min_reward INTEGER NOT NULL,
expiration INTEGER NOT NULL,
completion INTEGER NOT NULL,
max_collateral INTEGER
)
`,
);
},
dropTable: (db: Database) => {
db.run(`DROP TABLE IF EXISTS ${TABLE_NAME}`);
},
};
export function addRoute(db: Database, route: Omit<Route, 'route_id'>) {
return dynamicInsert(db, TABLE_NAME, route);
}
export function updateLocation(db: Database, location: Route) {
const id = location.route_id;
delete location.route_id;
return dynamicUpdate(db, TABLE_NAME, location, 'route_id', id);
}
export function getRoutes(db: Database, options?: QueryOptions<Route>) {
return select<Route>(db, TABLE_NAME, options);
}
export function getRoute(db: Database, route_id: number) {
return select<Route>(db, TABLE_NAME, {}, '*', { route_id })?.[0];
}
export function removeRoute(db: Database, route_id: number) {
return remove<Route>(db, TABLE_NAME, { route_id });
}

View File

@@ -0,0 +1,10 @@
import type { ContractStatus } from '@star-kitten/lib/eve';
export interface CourierContract {
concierge_id: number; // internal id to track this db record
contract_id: number; // id of the contract for this courier
assigned_to: number;
received: string;
last_updated: string;
status: ContractStatus;
}

View File

@@ -0,0 +1,45 @@
export enum RouteType {
JF = 1 << 0,
DST = 1 << 1,
BR = 1 << 2,
SMB = 1 << 3,
BRIDGE = 1 << 4,
}
export enum StructureType {
NPC = 'NPC',
Keepstar = 'Keepstar',
Fortizar = 'Fortizar',
Astrahus = 'Astrahus',
Sotiyo = 'Sotiyo',
Azbel = 'Azbel',
Raitaru = 'Raitaru',
Athanor = 'Athanor',
Tatara = 'Tatara',
}
export interface Location {
location_id: number;
name: string;
short_name: string;
structure_type: StructureType;
system: string;
supported_route_types: number;
}
export interface Route {
route_id: number;
start_location_id: number;
end_location_id: number;
isk_per_m3: number;
collat_pct: number; // collateral percent as a float, 1.5 = 1.5%
max_volume: number;
min_reward: number;
expiration: number;
completion: number;
max_collateral: number;
}
export function locationSupportsType(loc: Location, rt: RouteType) {
return (loc.supported_route_types & rt) !== 0;
}

View File

@@ -1,3 +1,4 @@
import { startBot } from "@star-kitten/lib/discord"; import { startBot } from '@star-kitten/lib/discord';
import './commands';
startBot(); startBot();

View File

@@ -1,6 +1,6 @@
{ {
"name": "@star-kitten/lib", "name": "@star-kitten/lib",
"version": "0.0.0", "version": "0.0.1",
"description": "Star Kitten Library.", "description": "Star Kitten Library.",
"type": "module", "type": "module",
"license": "MIT", "license": "MIT",
@@ -24,87 +24,81 @@
"require": "./dist/index.js", "require": "./dist/index.js",
"types": "./dist/index*.d.ts" "types": "./dist/index*.d.ts"
}, },
"./package.json": "./package.json",
"./util": { "./util": {
"types": "./src/util/index.d.ts", "types": "./dist/util/index.d.ts",
"require": "./src/util/index.js", "require": "./dist/util/index.js",
"import": "./dist/util/index.js" "import": "./dist/util/index.js"
}, },
"./util/*": { "./util/*": {
"types": "./src/util/**/*.d.ts", "types": "./dist/util/*",
"require": "./src/util/*", "require": "./dist/util/*",
"import": "./dist/util/*" "import": "./dist/util/*"
}, },
"./eve": { "./eve": {
"types": "./src/eve/index.d.ts", "types": "./dist/eve/index*.d.ts",
"require": "./src/eve/index.js", "require": "./dist/eve/index.js",
"import": "./dist/eve/index.js" "import": "./dist/eve/index.js"
}, },
"./eve/*": {
"types": "./src/eve/**/*.d.ts",
"require": "./src/eve/*",
"import": "./dist/eve/*"
},
"./eve/esi": { "./eve/esi": {
"import": "./dist/eve/esi/index.js", "import": "./dist/eve/esi/index.js",
"types": "./src/eve/esi/index*.d.ts", "types": "./dist/eve/esi/index*.d.ts",
"require": "./src/eve/esi/index.js" "require": "./dist/eve/esi/index.js"
}, },
"./eve/db": { "./eve/db": {
"import": "./dist/eve/db/index.js", "import": "./dist/eve/db/index.js",
"types": "./src/eve/db/index*.d.ts", "types": "./dist/eve/db/index*.d.ts",
"require": "./src/eve/db/index.js" "require": "./dist/eve/db/index.js"
}, },
"./eve/ref": { "./eve/ref": {
"import": "./dist/eve/ref/index.js", "import": "./dist/eve/ref/index.js",
"types": "./src/eve/ref/index*.d.ts", "types": "./dist/eve/ref/index*.d.ts",
"require": "./src/eve/ref/index.js" "require": "./dist/eve/ref/index.js"
}, },
"./eve/third-party/janice.js": { "./eve/third-party/janice.js": {
"import": "./dist/eve/third-party/janice.js", "import": "./dist/eve/third-party/janice.js",
"types": "./dist/types/eve/third-party/janice.d.ts", "types": "./dist/types/eve/third-party/janice.d.ts",
"require": "./src/eve/third-party/janice.js" "require": "./dist/eve/third-party/janice.js"
}, },
"./eve/models": { "./eve/models": {
"import": "./dist/eve/models/index.js", "import": "./dist/eve/models/index.js",
"types": "./src/eve/models/index*.d.ts", "types": "./dist/eve/models/index*.d.ts",
"require": "./src/eve/models/index.js" "require": "./dist/eve/models/index.js"
}, },
"./eve/data/*": "./data/*", "./eve/data/*": "./data/*",
"./discord": { "./discord": {
"import": "./dist/discord/index.js", "import": "./dist/discord/index.js",
"require": "./src/discord/index.js", "require": "./dist/discord/index.js",
"types": "./dist/types/discord/index.d.ts" "types": "./dist/types/discord/index.d.ts"
}, },
"./discord/commands": { "./discord/commands": {
"require": "./src/discord/commands/index.js", "require": "./dist/discord/commands/index.js",
"import": "./dist/discord/commands/index.js", "import": "./dist/discord/commands/index.js",
"types": "./dist/types/discord/commands/index.d.ts" "types": "./dist/types/discord/commands/index.d.ts"
}, },
"./discord/components": { "./discord/components": {
"types": "./dist/types/discord/components/index.d.ts", "types": "./dist/types/discord/components/index.d.ts",
"require": "./src/discord/components/index.js", "require": "./dist/discord/components/index.js",
"import": "./dist/discord/components/index.js" "import": "./dist/discord/components/index.js"
}, },
"./discord/pages": { "./discord/pages": {
"require": "./src/discord/pages/index.js", "require": "./dist/discord/pages/index.js",
"import": "./dist/discord/pages/index.js", "import": "./dist/discord/pages/index.js",
"types": "./dist/types/discord/pages/index.d.ts" "types": "./dist/types/discord/pages/index.d.ts"
}, },
"./discord/common": { "./discord/common": {
"require": "./src/discord/common/index.js", "require": "./dist/discord/common/index.js",
"import": "./dist/discord/common/index.js" "import": "./dist/discord/common/index.js"
}, },
"./discord/jsx": { "./discord/jsx": {
"types": "./src/discord/jsx/types.d.ts", "types": "./dist/discord/jsx/types.d.ts",
"import": "./dist/discord/jsx/index.js" "import": "./dist/discord/jsx/index.js"
}, },
"./discord/jsx-runtime": { "./discord/jsx-runtime": {
"types": "./src/discord/jsx/types.d.ts", "types": "./dist/discord/jsx/types.d.ts",
"default": "./dist/discord/jsx/jsx-runtime.js" "default": "./dist/discord/jsx/jsx-runtime.js"
}, },
"./discord/jsx-dev-runtime": { "./discord/jsx-dev-runtime": {
"types": "./src/discord/jsx/types.d.ts", "types": "./dist/discord/jsx/types.d.ts",
"default": "./dist/discord/jsx/jsx-dev-runtime.js" "default": "./dist/discord/jsx/jsx-dev-runtime.js"
} }
}, },
@@ -124,6 +118,8 @@
"bumpp": "^10.1.0", "bumpp": "^10.1.0",
"drizzle-kit": "^0.31.4", "drizzle-kit": "^0.31.4",
"ghooks": "^2.0.4", "ghooks": "^2.0.4",
"openapi-fetch": "^0.15.0",
"openapi-typescript": "^7.10.1",
"prettier-plugin-multiline-arrays": "^4.0.3", "prettier-plugin-multiline-arrays": "^4.0.3",
"tsdown": "^0.14.2", "tsdown": "^0.14.2",
"typescript": "^5.9.2" "typescript": "^5.9.2"
@@ -158,10 +154,11 @@
"release": "bumpp && npm publish", "release": "bumpp && npm publish",
"generate-migrations": "bunx drizzle-kit generate --dialect sqlite --schema ./src/db/schema.ts", "generate-migrations": "bunx drizzle-kit generate --dialect sqlite --schema ./src/db/schema.ts",
"migrate": "bun run ./src/db/migrate.ts", "migrate": "bun run ./src/db/migrate.ts",
"postinstall": "bun get-data", "postinstall": "bun run get-data",
"get-data": "bun refresh:reference-data && bun refresh:hoboleaks", "everef-api": "bunx openapi-typescript https://raw.githubusercontent.com/autonomouslogic/eve-ref/refs/heads/main/spec/eve-ref-api.yaml -o src/eve/everef/schema.d.ts",
"refresh:reference-data": "bun scripts/download-and-extract.ts https://data.everef.net/reference-data/reference-data-latest.tar.xz ./data/reference-data", "get-data": "bun run refresh:reference-data && bun run refresh:hoboleaks",
"refresh:hoboleaks": "bun scripts/download-and-extract.ts https://data.everef.net/hoboleaks-sde/hoboleaks-sde-latest.tar.xz ./data/hoboleaks", "refresh:reference-data": "bun run scripts/download-and-extract.ts https://data.everef.net/reference-data/reference-data-latest.tar.xz ./data/reference-data",
"static-export": "bun scripts/export-solar-systems.ts" "refresh:hoboleaks": "bun run scripts/download-and-extract.ts https://data.everef.net/hoboleaks-sde/hoboleaks-sde-latest.tar.xz ./data/hoboleaks",
"static-export": "bun run scripts/export-solar-systems.ts"
} }
} }

View File

@@ -1,15 +0,0 @@
import { type ChatInputApplicationCommandStructure } from '@projectdysnomia/dysnomia';
import type { ExecutableInteraction } from '../types/interaction.type';
import type { ChatCommandDefinition, CommandContext, CommandHandler } from '../types';
export function createChatCommand(
definition: ChatCommandDefinition,
execute: (interaction: ExecutableInteraction, ctx: CommandContext) => Promise<void>,
): CommandHandler<ChatInputApplicationCommandStructure> {
const def = definition as ChatInputApplicationCommandStructure;
def.type = 1; // CHAT_INPUT
return {
definition: def,
execute,
};
}

View File

@@ -7,6 +7,8 @@ import type {
ComponentInteraction, ComponentInteraction,
ModalSubmitInteraction, ModalSubmitInteraction,
PingInteraction, PingInteraction,
SelectMenuInteraction,
ButtonInteraction,
} from '../types'; } from '../types';
export function isApplicationCommand(interaction: Interaction): interaction is CommandInteraction { export function isApplicationCommand(interaction: Interaction): interaction is CommandInteraction {
@@ -39,6 +41,7 @@ export function commandHasIdPrefix(interaction: Interaction, prefix: string): bo
export function getCommandName(interaction: ExecutableInteraction): string | undefined { export function getCommandName(interaction: ExecutableInteraction): string | undefined {
if (isApplicationCommand(interaction) || isAutocomplete(interaction)) { if (isApplicationCommand(interaction) || isAutocomplete(interaction)) {
console.log(`command name: ${interaction.data.name}`);
return interaction.data.name; return interaction.data.name;
} }
return undefined; return undefined;
@@ -54,6 +57,12 @@ export function augmentInteraction(interaction: Interaction): Interaction {
interaction.isMessageComponent = function (): this is ComponentInteraction { interaction.isMessageComponent = function (): this is ComponentInteraction {
return interaction.type === Constants.InteractionTypes.MESSAGE_COMPONENT; return interaction.type === Constants.InteractionTypes.MESSAGE_COMPONENT;
}; };
interaction.isSelectMenu = function (): this is SelectMenuInteraction {
return interaction.isMessageComponent() && interaction.data.component_type in [3, 5, 6, 7, 8];
};
interaction.isButton = function (): this is ButtonInteraction {
return interaction.isMessageComponent() && interaction.data.component_type === Constants.ComponentTypes.BUTTON;
};
interaction.isAutocomplete = function (): this is AutocompleteInteraction { interaction.isAutocomplete = function (): this is AutocompleteInteraction {
return interaction.type === Constants.InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE; return interaction.type === Constants.InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE;
}; };

View File

@@ -1,6 +1,5 @@
import { type InteractionModalContent, type Component, Constants } from '@projectdysnomia/dysnomia'; import { type InteractionModalContent, type Component, Constants } from '@projectdysnomia/dysnomia';
import type { CommandContext, PartialContext, ExecutableInteraction } from '../types'; import type { CommandContext, PartialContext, ExecutableInteraction } from '../types';
import { int } from 'drizzle-orm/mysql-core';
import _ from 'lodash'; import _ from 'lodash';
export function injectInteraction(interaction: ExecutableInteraction, ctx: PartialContext): [ExecutableInteraction, CommandContext] { export function injectInteraction(interaction: ExecutableInteraction, ctx: PartialContext): [ExecutableInteraction, CommandContext] {

View File

@@ -0,0 +1,134 @@
import {
Constants,
type AutocompleteInteractionData,
type ChatInputApplicationCommandStructure,
type CommandInteractionData,
type InteractionDataOption,
type InteractionDataOptions,
type MessageApplicationCommandStructure,
type PrimaryEntryPointApplicationCommandStructure,
type UserApplicationCommandStructure,
} from '@projectdysnomia/dysnomia';
import type { ExecutableInteraction } from '../types/interaction.type';
import type { AuthorizedFn, ChatCommandDefinition, CommandContext, CommandOptions, ExecuteFn } from '../types';
import { addCommand } from './handle-commands';
export function createChatCommand(def: ChatCommandDefinition, execute: ExecuteFn, options: Partial<CommandOptions> = {}) {
const definition = def as ChatInputApplicationCommandStructure;
definition.type = Constants.ApplicationCommandTypes.CHAT_INPUT;
const command = {
definition,
execute,
options,
};
addCommand(command);
return command;
}
export function createUserAppCommand(
def: Omit<UserApplicationCommandStructure, 'type'>,
execute: ExecuteFn,
options: Partial<CommandOptions> = {},
) {
const definition = def as UserApplicationCommandStructure;
definition.type = Constants.ApplicationCommandTypes.USER;
const command = {
definition,
execute,
options,
};
addCommand(command);
return command;
}
export function createPrimaryEntryCommand(
def: Omit<PrimaryEntryPointApplicationCommandStructure, 'type'>,
execute: ExecuteFn,
options: Partial<CommandOptions> = {},
) {
const definition = def as PrimaryEntryPointApplicationCommandStructure;
definition.type = Constants.ApplicationCommandTypes.PRIMARY_ENTRY_POINT;
const command = {
definition,
execute,
options,
};
addCommand(command);
return command;
}
export function createMessageCommand(
def: Omit<MessageApplicationCommandStructure, 'type'>,
execute: ExecuteFn,
options: Partial<CommandOptions> = {},
) {
const definition = def as MessageApplicationCommandStructure;
definition.type = Constants.ApplicationCommandTypes.MESSAGE;
const command = {
definition,
execute,
options,
};
addCommand(command);
return command;
}
export function hasAnyRole(roleIds: string[]): AuthorizedFn {
return (interaction: ExecutableInteraction, ctx: CommandContext) => {
const member = interaction.member;
if (!member) return false;
for (let i = 0; i < roleIds.length; ++i) {
if (member.roles.indexOf(roleIds[i]) !== -1) {
return true;
}
}
return false;
};
}
export const Permissions = Constants.Permissions;
export function hasPermissions(permissions: bigint): AuthorizedFn {
return (interaction: ExecutableInteraction, ctx: CommandContext) => {
const member = interaction.member;
if (!member) return false;
return (member.permissions.allow & permissions) !== 0n;
};
}
export function hasUserId(userIds: string[]): AuthorizedFn {
return (interaction: ExecutableInteraction, ctx: CommandContext) => {
return userIds.indexOf(interaction.user?.id) !== -1;
};
}
export function isAdministrator(): AuthorizedFn {
return (interaction: ExecutableInteraction, ctx: CommandContext) => {
const member = interaction.member;
if (!member) return false;
return (member.permissions.allow & Permissions.administrator) !== 0n;
};
}
type SubCommandRouter = Record<string, SubCommandExecuteFn>;
type SubCommandExecuteFn = (
interaction: ExecutableInteraction,
ctx: CommandContext,
data: CommandInteractionData | AutocompleteInteractionData,
) => any | Promise<any>;
export function subCommandRouter(handlers: Record<string, SubCommandExecuteFn | SubCommandRouter>) {
return (interaction: ExecutableInteraction, ctx: CommandContext) => {
// console.log(JSON.stringify(interaction));
if (interaction.isMessageComponent() || interaction.isModalSubmit()) return;
const name = interaction.data.options[0].name;
if (handlers[name]) {
if (typeof handlers[name] === 'function') {
return handlers[name](interaction, ctx, interaction.data.options[0] as any);
} else {
const subName = (interaction.data.options[0] as any).options[0].name;
return handlers[name][subName](interaction, ctx, interaction.data.options[0].options[0]);
}
}
};
}

View File

@@ -3,14 +3,14 @@ import { handleCommands } from './handle-commands';
import { CommandInteraction, Constants, ModalSubmitInteraction, type ApplicationCommandStructure } from '@projectdysnomia/dysnomia'; import { CommandInteraction, Constants, ModalSubmitInteraction, type ApplicationCommandStructure } from '@projectdysnomia/dysnomia';
import { CommandHandler } from '../types'; import { CommandHandler } from '../types';
let commands: Record<string, CommandHandler<ApplicationCommandStructure>>; let commands: Map<string, CommandHandler<ApplicationCommandStructure>>;
beforeEach(() => { beforeEach(() => {
commands = {}; commands = new Map();
}); });
afterEach(() => { afterEach(() => {
commands = {}; commands = new Map();
}); });
mock.module('./command-helpers', () => ({ mock.module('./command-helpers', () => ({
@@ -20,7 +20,7 @@ mock.module('./command-helpers', () => ({
test('handleCommands executes command when interaction is CommandInteraction and command exists', async () => { test('handleCommands executes command when interaction is CommandInteraction and command exists', async () => {
const mockExecute = mock(() => Promise.resolve()); const mockExecute = mock(() => Promise.resolve());
const mockCommand = { definition: { name: 'testCommand' } as any, execute: mockExecute }; const mockCommand = { definition: { name: 'testCommand' } as any, execute: mockExecute };
commands['testCommand'] = mockCommand; commands.set('testCommand', mockCommand);
const mockInteraction = { const mockInteraction = {
type: Constants.InteractionTypes.APPLICATION_COMMAND, type: Constants.InteractionTypes.APPLICATION_COMMAND,
@@ -36,7 +36,7 @@ test('handleCommands executes command when interaction is CommandInteraction and
test('handleCommands executes command when interaction is CommandInteraction and command exists', async () => { test('handleCommands executes command when interaction is CommandInteraction and command exists', async () => {
const mockExecute = mock(() => Promise.resolve()); const mockExecute = mock(() => Promise.resolve());
const mockCommand = { definition: { name: 'testCommand' } as any, execute: mockExecute }; const mockCommand = { definition: { name: 'testCommand' } as any, execute: mockExecute };
commands['testCommand'] = mockCommand; commands.set('testCommand', mockCommand);
const mockInteraction = { const mockInteraction = {
type: Constants.InteractionTypes.MODAL_SUBMIT, type: Constants.InteractionTypes.MODAL_SUBMIT,

View File

@@ -1,47 +1,54 @@
import { type ApplicationCommandStructure } from '@projectdysnomia/dysnomia'; import { Constants, type ApplicationCommandStructure } from '@projectdysnomia/dysnomia';
import { augmentInteraction, getCommandName } from './command-helpers';
import { injectInteraction } from './command-injection'; import { injectInteraction } from './command-injection';
import { getCommandState } from './command-state'; import { getCommandState } from './command-state';
import { type ExecutableInteraction } from '../types/interaction.type'; import { type ExecutableInteraction } from '../types/interaction.type';
import type { CommandHandler, PartialContext } from '../types'; import type { CommandContext, CommandHandler, CommandOptions, PartialContext } from '../types';
import { augmentInteraction, getCommandName } from './command-helpers';
import { awaitMaybePromise } from '@/util/promise';
export async function handleCommands( export async function handleCommands(
interaction: ExecutableInteraction, interaction: ExecutableInteraction,
commands: Record<string, CommandHandler<ApplicationCommandStructure>>, commands: Map<string, CommandHandler<ApplicationCommandStructure>>,
ctx: PartialContext, ctx: PartialContext,
) { ) {
ctx.state = await getCommandState(interaction, ctx); let commandContext = ctx as CommandContext;
if (!ctx.state.name) { commandContext.state = await getCommandState(interaction, commandContext);
ctx.state.name = getCommandName(interaction); if (!commandContext.state.name) {
commandContext.state.name = getCommandName(interaction);
} }
if (interaction.isAutocomplete() && ctx.state.name) { if (interaction.isAutocomplete() && commandContext.state.name) {
const acCommand = commands[ctx.state.name]; const acCommand = commands.get(commandContext.state.name);
return acCommand.execute(interaction, ctx as any); if (acCommand.options?.authorize && !(await awaitMaybePromise(acCommand.options.authorize(interaction, commandContext)))) {
return;
}
return acCommand.execute(interaction, commandContext as any);
} }
if (!ctx.state.id) { if (!commandContext.state.id) {
console.error(`No command ID found for interaction ${interaction.id}`); console.error(`No command ID found for interaction ${interaction.id}`);
return; return;
} }
const command = commands[ctx.state.name || '']; const command = commands.get(commandContext.state.name || '');
if (!command) { if (!command) {
console.warn(`No command found for interaction: ${JSON.stringify(interaction, undefined, 2)}`); console.warn(`No command found for interaction: ${JSON.stringify(interaction, undefined, 2)}`);
return; return;
} }
cleanInteractionCustomIds(interaction, ctx.state.id);
const [injectedInteraction, fullContext] = await injectInteraction(interaction, ctx);
return command.execute(injectedInteraction, fullContext);
}
export function initializeCommandHandling(commands: Record<string, CommandHandler<ApplicationCommandStructure>>, ctx: PartialContext) { if (command.options?.authorize && !(await awaitMaybePromise(command.options.authorize(interaction, commandContext)))) {
ctx.client.on('interactionCreate', async (_interaction) => { if (interaction.isApplicationCommand()) {
const interaction = augmentInteraction(_interaction as any); interaction.createMessage({
if (interaction.isExecutable()) { flags: Constants.MessageFlags.EPHEMERAL,
handleCommands(interaction, commands, ctx); content: `You are not authorized to execute the \`${command.definition.name}\` command.`,
}
}); });
}
return;
}
cleanInteractionCustomIds(interaction, commandContext.state.id);
const [injectedInteraction, fullContext] = await injectInteraction(interaction, commandContext);
return command.execute(injectedInteraction, fullContext);
} }
function cleanInteractionCustomIds(interaction: ExecutableInteraction, id: string) { function cleanInteractionCustomIds(interaction: ExecutableInteraction, id: string) {
@@ -72,3 +79,68 @@ function removeCommandIdFromComponentCustomIds(components: { custom_id?: string;
} }
}); });
} }
const commandRegistry = new Map<string, Map<string, CommandHandler>>();
export async function registerCommands(ctx: PartialContext) {
if (!ctx.client) throw new Error('Client not initialized');
if (!(await ctx.client.getCommands()).length || process.env.RESET_COMMANDS === 'true' || process.env.NODE_ENV === 'development') {
console.debug('Registering commands...');
const registry = commandRegistry.get(ctx.client.commandKey);
const defs: Map<string, ApplicationCommandStructure[]> = new Map();
for (const cmd of registry.values().toArray()) {
if (cmd.options?.guilds) {
for (const guildId of cmd.options.guilds) {
if (defs.get(guildId)) {
defs.get(guildId).push(cmd.definition);
} else {
defs.set(guildId, [cmd.definition]);
}
}
} else {
if (defs.get('global')) {
defs.get('global').push(cmd.definition);
} else {
defs.set('global', [cmd.definition]);
}
}
}
for (const guildId of defs.keys().toArray()) {
if (guildId === 'global') {
const response = await ctx.client.bulkEditCommands(defs.get(guildId));
console.debug(`Registered ${response.length} global commands`);
} else {
const response = await ctx.client.bulkEditGuildCommands(guildId, defs.get(guildId));
console.debug(`Registered ${response.length} guild commands on ${guildId}`);
for (const cmdResponse of response) {
const cmd = registry.get(cmdResponse.name);
if (cmd.options.guildPermissions && cmd.options.guildPermissions[guildId]) {
console.debug(`Editing permissions for command on ${guildId}`);
const response = await ctx.client.editCommandPermissions(guildId, cmdResponse.id, cmd.options.guildPermissions[guildId]);
console.debug(`Edited permissions for command on ${guildId}`);
}
}
}
}
}
ctx.client.on('interactionCreate', async (_interaction) => {
const interaction = augmentInteraction(_interaction as any);
if (interaction.isExecutable()) {
const registry = commandRegistry.get(ctx.client.commandKey);
handleCommands(interaction, registry, ctx);
}
});
return commandRegistry.values().toArray();
}
export function addCommand(command: CommandHandler) {
const commandKey = command.options.commandKey || 'default';
if (!commandRegistry.get(commandKey)) {
commandRegistry.set(commandKey, new Map());
}
const registry = commandRegistry.get(commandKey);
registry.set(command.definition.name, command);
}

View File

@@ -1,7 +1,3 @@
export * from './command-handler'; // Exports that will be made publicly available outside this library
export * from './import-commands'; export * from './create';
export * from './handle-commands';
export * from './command-helpers';
export * from './register-commands';
export * from './command-state';
export * from './option-builders'; export * from './option-builders';

View File

@@ -1,11 +0,0 @@
import type { ApplicationCommandStructure, Client } from '@projectdysnomia/dysnomia';
export async function registerCommands(client: Client, commands: ApplicationCommandStructure[]) {
if (!client) throw new Error('Client not initialized');
if (!(await client.getCommands()).length || process.env.RESET_COMMANDS === 'true' || process.env.NODE_ENV === 'development') {
console.debug('Registering commands...');
const response = await client.bulkEditCommands(commands);
console.debug(`Registered ${response.length} commands.`);
}
return commands;
}

View File

@@ -4,6 +4,7 @@ import {
type ModalSubmitInteractionDataLabelComponent, type ModalSubmitInteractionDataLabelComponent,
type ModalSubmitInteractionDataSelectComponent, type ModalSubmitInteractionDataSelectComponent,
type ModalSubmitInteractionDataTextInputComponent, type ModalSubmitInteractionDataTextInputComponent,
type StringSelectMenu,
} from '@projectdysnomia/dysnomia'; } from '@projectdysnomia/dysnomia';
export function isModalLabel(component: ComponentBase): component is ModalSubmitInteractionDataLabelComponent { export function isModalLabel(component: ComponentBase): component is ModalSubmitInteractionDataLabelComponent {
@@ -21,3 +22,7 @@ export function isModalSelect(component: ComponentBase): component is ModalSubmi
export function componentHasIdPrefix(component: ComponentBase, prefix: string): boolean { export function componentHasIdPrefix(component: ComponentBase, prefix: string): boolean {
return (isModalTextInput(component) || isModalSelect(component)) && component.custom_id.startsWith(prefix); return (isModalTextInput(component) || isModalSelect(component)) && component.custom_id.startsWith(prefix);
} }
export function isStringSelectMenu(component: ComponentBase): component is StringSelectMenu {
return component.type === Constants.ComponentTypes.STRING_SELECT;
}

View File

@@ -1,14 +1,14 @@
import { importCommands, initializeCommandHandling, registerCommands } from '../commands'; import { Client as DJSClient } from '@projectdysnomia/dysnomia';
import { Client } from '@projectdysnomia/dysnomia';
import kv, { asyncKV } from '@/util/kv.js'; import kv, { asyncKV } from '@/util/kv.js';
import type { KVStore } from './kv-store.type.ts.ts'; import type { KVStore } from './kv-store.type.ts.ts';
import type { Cache } from './cache.type.ts'; import type { Cache } from './cache.type.ts';
import { registerCommands } from '../commands/handle-commands.ts';
import type { Client } from './client.ts';
export interface DiscordBotOptions { export interface DiscordBotOptions {
token?: string; token?: string;
intents?: number[]; intents?: number[];
commandPattern?: string; commandKey?: string;
commandBaseDir?: string;
keyStore?: KVStore; keyStore?: KVStore;
cache?: Cache; cache?: Cache;
onError?: (error: Error) => void; onError?: (error: Error) => void;
@@ -18,28 +18,23 @@ export interface DiscordBotOptions {
export function startBot({ export function startBot({
token = process.env.DISCORD_BOT_TOKEN || '', token = process.env.DISCORD_BOT_TOKEN || '',
intents = [], intents = [],
commandPattern = '**/*.command.{js,ts,jsx,tsx}', commandKey = 'default',
commandBaseDir = 'src',
keyStore = asyncKV, keyStore = asyncKV,
cache = kv, cache = kv,
onError, onError,
onReady, onReady,
}: DiscordBotOptions = {}): Client { }: DiscordBotOptions = {}): Client {
const client = new Client(`Bot ${token}`, { const client = new DJSClient(`Bot ${token}`, {
gateway: { gateway: {
intents, intents,
}, },
}); }) as Client;
client.commandKey = commandKey;
client.on('ready', async () => { client.on('ready', async () => {
console.debug(`Logged in as ${client.user?.username}#${client.user?.discriminator}`); console.debug(`Logged in as ${client.user?.username}#${client.user?.discriminator}`);
onReady?.(); onReady?.();
const commands = await importCommands(commandPattern, commandBaseDir); await registerCommands({ client, cache, kv: keyStore });
await registerCommands(
client,
Object.values(commands).map((cmd) => cmd.definition),
);
initializeCommandHandling(commands, { client, cache, kv: keyStore });
console.debug('Bot is ready and command handling is initialized.'); console.debug('Bot is ready and command handling is initialized.');
}); });

View File

@@ -0,0 +1,5 @@
import { Client as DJSClient } from '@projectdysnomia/dysnomia';
export interface Client extends DJSClient {
commandKey: string;
}

View File

@@ -1,4 +1,4 @@
import type { ActionRowItem, ContainerItems, MediaItem, Padding } from '@/discord/components'; import type { ActionRowItem, ButtonStyle, ContainerItems, MediaItem, Padding } from '@/discord/components';
import type { import type {
ActionRow, ActionRow,
Button, Button,
@@ -68,7 +68,7 @@ export interface ButtonElement {
props: { props: {
label: string; label: string;
customId: string; customId: string;
style: number; style: ButtonStyle;
emoji?: PartialEmoji; emoji?: PartialEmoji;
disabled?: boolean; disabled?: boolean;
}; };

View File

@@ -86,7 +86,7 @@ export interface StarKittenIntrinsicElements {
premiumButton: PremiumButtonElement['props']; premiumButton: PremiumButtonElement['props'];
modal: ModalElement['props'] & { children: StarKittenElement | StarKittenElement[] }; modal: ModalElement['props'] & { children: StarKittenElement | StarKittenElement[] };
label: LabelElement['props'] & { children: StarKittenElement | StarKittenElement[] }; label: LabelElement['props'] & { children: StarKittenElement | StarKittenElement[] };
stringSelect: StringSelectElement['props'] & { children: StringSelectElement['children'] }; stringSelect: StringSelectElement['props'] & { children: StarKittenElement | StarKittenElement[] };
option: OptionElement['props']; option: OptionElement['props'];
textInput: TextInputElement['props']; textInput: TextInputElement['props'];
text: TextElement['props']; text: TextElement['props'];

View File

@@ -1,5 +1,6 @@
import { Constants, type InteractionContentEdit, type InteractionModalContent } from '@projectdysnomia/dysnomia'; import { Constants, type InteractionContentEdit, type InteractionModalContent } from '@projectdysnomia/dysnomia';
import type { CommandContext, ExecutableInteraction } from '../types'; import type { CommandContext, ExecutableInteraction } from '../types';
import type { StarKittenElement } from '../jsx';
export enum PageType { export enum PageType {
MODAL = 'modal', MODAL = 'modal',
@@ -13,7 +14,9 @@ export interface Page<T> {
followUpFlags?: number; followUpFlags?: number;
render: ( render: (
ctx: PageContext<T>, ctx: PageContext<T>,
) => (InteractionModalContent | InteractionContentEdit) | Promise<InteractionModalContent | InteractionContentEdit>; ) =>
| (InteractionModalContent | InteractionContentEdit | StarKittenElement)
| Promise<InteractionModalContent | InteractionContentEdit | StarKittenElement>;
} }
export interface PagesOptions<T> { export interface PagesOptions<T> {

View File

@@ -2,7 +2,7 @@ import type { ChatInputApplicationCommandStructure, ApplicationCommandStructure
import type { ExecutableInteraction } from './interaction.type'; import type { ExecutableInteraction } from './interaction.type';
import type { Cache } from '@/discord/core/cache.type'; import type { Cache } from '@/discord/core/cache.type';
import type { KVStore } from '@/discord/core/kv-store.type.ts'; import type { KVStore } from '@/discord/core/kv-store.type.ts';
import type { Client } from '@projectdysnomia/dysnomia'; import type { Client } from '@/discord/core/client';
export interface CommandState<T = any> { export interface CommandState<T = any> {
id: string; // unique id for this command instance id: string; // unique id for this command instance
@@ -18,11 +18,33 @@ export interface PartialContext<T = any> {
state?: CommandState<T>; // state associated with this command instance state?: CommandState<T>; // state associated with this command instance
} }
export enum PermissionType {
ROLE = 1,
USER = 2,
CHANNEL = 3,
}
export interface CommandPermission {
id: string;
permission: boolean;
type: PermissionType;
}
export interface CommandOptions {
commandKey: string;
authorize: AuthorizedFn;
guilds: string[]; // make this a guild command
guildPermissions: Record<string, CommandPermission[]>; // only works if a guild command
}
export type CommandContext<T = any> = Required<PartialContext<T>>; export type CommandContext<T = any> = Required<PartialContext<T>>;
export type ChatCommandDefinition = Omit<ChatInputApplicationCommandStructure, 'type'>; export type ChatCommandDefinition = Omit<ChatInputApplicationCommandStructure, 'type'>;
export type ExecuteFn = (interaction: ExecutableInteraction, ctx: CommandContext) => any | Promise<any>;
export type AuthorizedFn = (interaction: ExecutableInteraction, ctx: CommandContext) => boolean | Promise<boolean>;
export interface CommandHandler<T extends ApplicationCommandStructure> { export interface CommandHandler<T extends ApplicationCommandStructure = ApplicationCommandStructure> {
definition: T; definition: T;
execute: (interaction: ExecutableInteraction, ctx: CommandContext) => Promise<void>; execute: ExecuteFn;
options?: Partial<CommandOptions>;
} }

View File

@@ -9,6 +9,8 @@ export interface InteractionAugments {
isApplicationCommand: () => this is Dysnomia.CommandInteraction; isApplicationCommand: () => this is Dysnomia.CommandInteraction;
isModalSubmit: () => this is Dysnomia.ModalSubmitInteraction; isModalSubmit: () => this is Dysnomia.ModalSubmitInteraction;
isMessageComponent: () => this is Dysnomia.ComponentInteraction; isMessageComponent: () => this is Dysnomia.ComponentInteraction;
isSelectMenu: () => this is SelectMenuInteraction;
isButton: () => this is ButtonInteraction;
isAutocomplete: () => this is Dysnomia.AutocompleteInteraction; isAutocomplete: () => this is Dysnomia.AutocompleteInteraction;
isPing: () => this is Dysnomia.PingInteraction; isPing: () => this is Dysnomia.PingInteraction;
isExecutable: () => this is ExecutableInteraction; isExecutable: () => this is ExecutableInteraction;
@@ -23,3 +25,11 @@ export type ModalSubmitInteraction = Dysnomia.ModalSubmitInteraction & Interacti
export type ComponentInteraction = Dysnomia.ComponentInteraction & InteractionAugments; export type ComponentInteraction = Dysnomia.ComponentInteraction & InteractionAugments;
export type AutocompleteInteraction = Dysnomia.AutocompleteInteraction & InteractionAugments; export type AutocompleteInteraction = Dysnomia.AutocompleteInteraction & InteractionAugments;
export type PingInteraction = Dysnomia.PingInteraction & InteractionAugments; export type PingInteraction = Dysnomia.PingInteraction & InteractionAugments;
export interface SelectMenuInteraction extends ComponentInteraction {
data: Dysnomia.ComponentInteractionSelectMenuData;
}
export interface ButtonInteraction extends ComponentInteraction {
data: Dysnomia.ComponentInteractionButtonData;
}

View File

@@ -9,7 +9,7 @@ import { esiFetch, type PublicEsiOptions } from './util/fetch';
* - This route is cached for an hour * - This route is cached for an hour
* @returns {number[]} - An array of all active player alliance ids * @returns {number[]} - An array of all active player alliance ids
*/ */
export async function listAlliances(options?: PublicEsiOptions) { export async function listAlliances(options?: PublicEsiOptions): Promise<number[]> {
return await esiFetch<number[]>('/alliances/', options); return await esiFetch<number[]>('/alliances/', options);
} }
@@ -29,7 +29,7 @@ interface AllianceInfo {
* @param alliance_id Alliance id * @param alliance_id Alliance id
* @returns {AllianceInfo} * @returns {AllianceInfo}
*/ */
export async function getAllianceInformation(alliance_id: number, options?: PublicEsiOptions) { export async function getAllianceInformation(alliance_id: number, options?: PublicEsiOptions): Promise<Partial<AllianceInfo>> {
return await esiFetch<Partial<AllianceInfo>>(`/alliances/${alliance_id}/`, options); return await esiFetch<Partial<AllianceInfo>>(`/alliances/${alliance_id}/`, options);
} }
@@ -39,7 +39,7 @@ export async function getAllianceInformation(alliance_id: number, options?: Publ
* @param alliance_id Alliance id * @param alliance_id Alliance id
* @returns {number[]} - Array of corporation ids * @returns {number[]} - Array of corporation ids
*/ */
export async function listAllianceCorporations(alliance_id: number, options?: PublicEsiOptions) { export async function listAllianceCorporations(alliance_id: number, options?: PublicEsiOptions): Promise<number[]> {
return await esiFetch<number[]>(`/alliances/${alliance_id}/corporations/`, options); return await esiFetch<number[]>(`/alliances/${alliance_id}/corporations/`, options);
} }
@@ -54,6 +54,6 @@ interface AllianceIcon {
* @param alliance_id Alliance id * @param alliance_id Alliance id
* @returns {AllianceIcon} * @returns {AllianceIcon}
*/ */
export async function getAllianceIcon(alliance_id: number, options?: PublicEsiOptions) { export async function getAllianceIcon(alliance_id: number, options?: PublicEsiOptions): Promise<Partial<AllianceIcon>> {
return await esiFetch<Partial<AllianceIcon>>(`/alliances/${alliance_id}/icons/`, options); return await esiFetch<Partial<AllianceIcon>>(`/alliances/${alliance_id}/icons/`, options);
} }

View File

@@ -25,7 +25,7 @@ export interface Asset {
type_id: number; type_id: number;
} }
export function getCharacterAssets(options: EsiOptions, page: number = 1) { export function getCharacterAssets(options: EsiOptions, page: number = 1): Promise<Partial<Asset>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_assets.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_assets.v1']);
return esiFetch<Partial<Asset>[]>(`/characters/${character_id}/assets/?page=${page}`, { return esiFetch<Partial<Asset>[]>(`/characters/${character_id}/assets/?page=${page}`, {
...options, ...options,
@@ -42,7 +42,7 @@ export interface AssetLocation {
}; };
} }
export function getCharacterAssetLocations(options: EsiOptions, ids: number[]) { export function getCharacterAssetLocations(options: EsiOptions, ids: number[]): any[] | Promise<Partial<AssetLocation>[]> {
if (ids.length === 0) return []; if (ids.length === 0) return [];
if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once'; if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once';
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_assets.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_assets.v1']);
@@ -59,7 +59,7 @@ export interface AssetNames {
name: string; name: string;
} }
export function getCharacterAssetNames(options: EsiOptions, ids: number[]) { export function getCharacterAssetNames(options: EsiOptions, ids: number[]): any[] | Promise<Partial<AssetNames>[]> {
if (ids.length === 0) return []; if (ids.length === 0) return [];
if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once'; if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once';
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_assets.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_assets.v1']);
@@ -82,7 +82,7 @@ export interface CorpAsset {
type_id: number; type_id: number;
} }
export async function getCorporationAssets(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationAssets(options: EsiOptions, corporation_id: number, page: number = 1): Promise<Partial<CorpAsset>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_corporation_assets.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_corporation_assets.v1']);
return await esiFetch<Partial<CorpAsset>[]>(`/corporations/${corporation_id}/assets/?page=${page}`, { return await esiFetch<Partial<CorpAsset>[]>(`/corporations/${corporation_id}/assets/?page=${page}`, {
...options, ...options,
@@ -99,7 +99,11 @@ export interface AssetLocation {
}; };
} }
export async function getCorporationAssetLocations(options: EsiOptions, corporation_id: number, ids: number[]) { export async function getCorporationAssetLocations(
options: EsiOptions,
corporation_id: number,
ids: number[],
): Promise<Partial<AssetLocation>[]> {
if (ids.length === 0) return []; if (ids.length === 0) return [];
if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once'; if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once';
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_corporation_assets.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_corporation_assets.v1']);
@@ -115,7 +119,7 @@ export interface AssetNames {
name: string; name: string;
} }
export async function getCorporationAssetNames(options: EsiOptions, id: number, ids: number[]) { export async function getCorporationAssetNames(options: EsiOptions, id: number, ids: number[]): Promise<Partial<AssetNames>[]> {
if (ids.length === 0) return []; if (ids.length === 0) return [];
if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once'; if (ids.length > 1000) throw 'Maximum of 1000 IDs can be requested at once';
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_corporation_assets.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-assets.read_corporation_assets.v1']);

View File

@@ -31,7 +31,7 @@ export interface CalendarEvent {
* @param from_event Event from which to get the next 50 chronological event summaries * @param from_event Event from which to get the next 50 chronological event summaries
* @returns {Partial<CalendarEvent>[]} * @returns {Partial<CalendarEvent>[]}
*/ */
export async function listCalendarEventSummaries(options: EsiOptions, from_event?: number) { export async function listCalendarEventSummaries(options: EsiOptions, from_event?: number): Promise<Partial<CalendarEvent>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.read_calendar_events.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.read_calendar_events.v1']);
return await esiFetch<Partial<CalendarEvent>[]>(`/characters/${character_id}/calendar/${from_event ?? '?from_event=' + from_event}`, { return await esiFetch<Partial<CalendarEvent>[]>(`/characters/${character_id}/calendar/${from_event ?? '?from_event=' + from_event}`, {
...options, ...options,
@@ -62,7 +62,7 @@ export interface CalendarEventDetails {
* @param event_id Event Id * @param event_id Event Id
* @returns {Partial<CalendarEventDetails>} * @returns {Partial<CalendarEventDetails>}
*/ */
export async function getEventDetails(options: EsiOptions, event_id: number) { export async function getEventDetails(options: EsiOptions, event_id: number): Promise<Partial<CalendarEventDetails>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.read_calendar_events.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.read_calendar_events.v1']);
return await esiFetch<Partial<CalendarEventDetails>>(`/characters/${character_id}/calendar/${event_id}/`, { return await esiFetch<Partial<CalendarEventDetails>>(`/characters/${character_id}/calendar/${event_id}/`, {
...options, ...options,
@@ -79,7 +79,11 @@ export async function getEventDetails(options: EsiOptions, event_id: number) {
* @param event_id Event Id * @param event_id Event Id
* @param response Response: 'accepted' | 'declined' | 'tentative' * @param response Response: 'accepted' | 'declined' | 'tentative'
*/ */
export async function respondToEvent(options: EsiOptions, event_id: number, response: 'accepted' | 'declined' | 'tentative') { export async function respondToEvent(
options: EsiOptions,
event_id: number,
response: 'accepted' | 'declined' | 'tentative',
): Promise<void> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.respond_calendar_events.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.respond_calendar_events.v1']);
return await esiFetch<void>(`/characters/${character_id}/calendar/${event_id}/`, { return await esiFetch<void>(`/characters/${character_id}/calendar/${event_id}/`, {
...options, ...options,
@@ -104,7 +108,7 @@ export interface CalendarEventAttendee {
* @param event_id Event Id * @param event_id Event Id
* @returns {Partial<CalendarEventAttendee>[]} * @returns {Partial<CalendarEventAttendee>[]}
*/ */
export async function getEventAttendees(options: EsiOptions, event_id: number) { export async function getEventAttendees(options: EsiOptions, event_id: number): Promise<Partial<CalendarEventAttendee>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.read_calendar_events.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-calendar.read_calendar_events.v1']);
return await esiFetch<Partial<CalendarEventAttendee>[]>(`/characters/${character_id}/calendar/${event_id}/attendees/`, { return await esiFetch<Partial<CalendarEventAttendee>[]>(`/characters/${character_id}/calendar/${event_id}/attendees/`, {
...options, ...options,

View File

@@ -9,7 +9,10 @@ export interface CharacterAffiliations {
alliance_id?: number; alliance_id?: number;
faction_id?: number; faction_id?: number;
} }
export function getCharacterAffiliations(character_ids: number[], options?: PublicEsiOptions) { export function getCharacterAffiliations(
character_ids: number[],
options?: PublicEsiOptions,
): any[] | Promise<Partial<CharacterAffiliations>[]> {
if (character_ids.length === 0) return []; if (character_ids.length === 0) return [];
if (character_ids.length > 1000) throw 'Maximum of 1000 character IDs can be requested at once'; if (character_ids.length > 1000) throw 'Maximum of 1000 character IDs can be requested at once';
return esiFetch<Partial<CharacterAffiliations>[]>(`/characters/affiliation/`, { return esiFetch<Partial<CharacterAffiliations>[]>(`/characters/affiliation/`, {
@@ -33,7 +36,7 @@ export interface CharacterData {
title: string; title: string;
} }
export function getCharacterPublicData(id: number, options?: PublicEsiOptions) { export function getCharacterPublicData(id: number, options?: PublicEsiOptions): Promise<Partial<CharacterData>> {
return esiFetch<Partial<CharacterData>>(`/characters/${id}/`, options); return esiFetch<Partial<CharacterData>>(`/characters/${id}/`, options);
} }
@@ -46,7 +49,7 @@ export interface AgentResearch {
} }
// required scope: esi-characters.read_agents_research.v1 // required scope: esi-characters.read_agents_research.v1
export function getCharacterAgentResearch(options: EsiOptions) { export function getCharacterAgentResearch(options: EsiOptions): Promise<Partial<AgentResearch>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_agents_research.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_agents_research.v1']);
return esiFetch<Partial<AgentResearch>[]>(`/characters/${character_id}/agents_research/`, { return esiFetch<Partial<AgentResearch>[]>(`/characters/${character_id}/agents_research/`, {
...options, ...options,
@@ -55,7 +58,7 @@ export function getCharacterAgentResearch(options: EsiOptions) {
} }
// required scope: esi-characters.read_blueprints.v1 // required scope: esi-characters.read_blueprints.v1
export function getCharacterBlueprints(options: EsiOptions, page: number = 1) { export function getCharacterBlueprints(options: EsiOptions, page: number = 1): Promise<Partial<Blueprint>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_blueprints.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_blueprints.v1']);
return esiFetch<Partial<Blueprint>[]>(`/characters/${character_id}/blueprints/?page=${page}`, { return esiFetch<Partial<Blueprint>[]>(`/characters/${character_id}/blueprints/?page=${page}`, {
...options, ...options,
@@ -70,12 +73,12 @@ export interface CharacterCorporationHistory {
start_date: string; start_date: string;
} }
export function getCharacterCorporationHistory(options: EsiOptions) { export function getCharacterCorporationHistory(options: EsiOptions): Promise<Partial<CharacterCorporationHistory>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_corporation_roles.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_corporation_roles.v1']);
return esiFetch<Partial<CharacterCorporationHistory>[]>(`/characters/${character_id}/corporationhistory/`, options); return esiFetch<Partial<CharacterCorporationHistory>[]>(`/characters/${character_id}/corporationhistory/`, options);
} }
export function calculateCSPAChargeCost(options: EsiOptions, target_character_ids: number[]) { export function calculateCSPAChargeCost(options: EsiOptions, target_character_ids: number[]): Promise<number[]> {
if (target_character_ids.length === 0) return null; if (target_character_ids.length === 0) return null;
if (target_character_ids.length > 100) throw 'Maximum of 100 target character IDs can be requested at once'; if (target_character_ids.length > 100) throw 'Maximum of 100 target character IDs can be requested at once';
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_cspa.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_cspa.v1']);
@@ -93,7 +96,7 @@ export interface JumpFatigue {
last_update_date: string; last_update_date: string;
} }
export function getCharacterJumpFatigue(options: EsiOptions) { export function getCharacterJumpFatigue(options: EsiOptions): Promise<Partial<JumpFatigue>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_fatigue.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_fatigue.v1']);
return esiFetch<Partial<JumpFatigue>>(`/characters/${character_id}/fatigue/`, { return esiFetch<Partial<JumpFatigue>>(`/characters/${character_id}/fatigue/`, {
...options, ...options,
@@ -118,7 +121,7 @@ export interface Medals {
title: string; title: string;
} }
export function getCharacterMedals(options: EsiOptions) { export function getCharacterMedals(options: EsiOptions): Promise<Partial<Medals>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_medals.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_medals.v1']);
return esiFetch<Partial<Medals>[]>(`/characters/${character_id}/medals/`, { return esiFetch<Partial<Medals>[]>(`/characters/${character_id}/medals/`, {
...options, ...options,
@@ -136,7 +139,7 @@ export interface Notification {
type: NotificationType; type: NotificationType;
} }
export function getCharacterNotifications(options: EsiOptions) { export function getCharacterNotifications(options: EsiOptions): Promise<Partial<Notification>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_notifications.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_notifications.v1']);
return esiFetch<Partial<Notification>[]>(`/characters/${character_id}/notifications/`, { return esiFetch<Partial<Notification>[]>(`/characters/${character_id}/notifications/`, {
...options, ...options,
@@ -152,7 +155,7 @@ export interface ContactNotification {
standing_level: -10 | -5 | 0 | 5 | 10; standing_level: -10 | -5 | 0 | 5 | 10;
} }
export function getCharacterContactNotifications(options: EsiOptions) { export function getCharacterContactNotifications(options: EsiOptions): Promise<Partial<ContactNotification>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_notifications.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_notifications.v1']);
return esiFetch<Partial<ContactNotification>[]>(`/characters/${character_id}/notifications/contacts`, { return esiFetch<Partial<ContactNotification>[]>(`/characters/${character_id}/notifications/contacts`, {
...options, ...options,
@@ -167,7 +170,7 @@ export interface CharacterPortraits {
px64x64: string; px64x64: string;
} }
export function getCharacterPortraits(character_id: number, options?: PublicEsiOptions) { export function getCharacterPortraits(character_id: number, options?: PublicEsiOptions): Promise<Partial<CharacterPortraits>> {
return esiFetch<Partial<CharacterPortraits>>(`/characters/${character_id}/portrait/`, options); return esiFetch<Partial<CharacterPortraits>>(`/characters/${character_id}/portrait/`, options);
} }
@@ -182,7 +185,7 @@ export interface CharacterCorporationRoles {
roles_at_other: string[]; roles_at_other: string[];
} }
export function getCharacterCorporationRoles(options: EsiOptions) { export function getCharacterCorporationRoles(options: EsiOptions): Promise<Partial<CharacterCorporationRoles>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_corporation_roles.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_corporation_roles.v1']);
return esiFetch<Partial<CharacterCorporationRoles>>(`/characters/${character_id}/roles`, { return esiFetch<Partial<CharacterCorporationRoles>>(`/characters/${character_id}/roles`, {
...options, ...options,
@@ -196,7 +199,7 @@ export interface CharacterStandings {
standing: number; standing: number;
} }
export function getCharacterStandings(options: EsiOptions) { export function getCharacterStandings(options: EsiOptions): Promise<Partial<CharacterStandings>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_standings.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_standings.v1']);
return esiFetch<Partial<CharacterStandings>[]>(`/characters/${character_id}/standings`, { return esiFetch<Partial<CharacterStandings>[]>(`/characters/${character_id}/standings`, {
...options, ...options,
@@ -211,7 +214,7 @@ export interface CharacterTitles {
}[]; }[];
} }
export function getCharacterTitles(options: EsiOptions) { export function getCharacterTitles(options: EsiOptions): Promise<Partial<CharacterTitles>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_titles.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_titles.v1']);
return esiFetch<Partial<CharacterTitles>>(`/characters/${character_id}/titles`, { return esiFetch<Partial<CharacterTitles>>(`/characters/${character_id}/titles`, {
...options, ...options,

View File

@@ -18,7 +18,7 @@ export interface CharacterClones {
last_station_change_date: string; last_station_change_date: string;
} }
export function getCharacterClones(options: EsiOptions) { export function getCharacterClones(options: EsiOptions): Promise<Partial<CharacterClones>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-clones.read_clones.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-clones.read_clones.v1']);
return esiFetch<Partial<CharacterClones>>(`/characters/${character_id}/clones`, { return esiFetch<Partial<CharacterClones>>(`/characters/${character_id}/clones`, {
...options, ...options,
@@ -26,7 +26,7 @@ export function getCharacterClones(options: EsiOptions) {
}); });
} }
export function getCharacterActiveImplants(options: EsiOptions) { export function getCharacterActiveImplants(options: EsiOptions): Promise<number[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-clones.read_implants.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-clones.read_implants.v1']);
return esiFetch<number[]>(`/characters/${character_id}/implants`, { return esiFetch<number[]>(`/characters/${character_id}/implants`, {
...options, ...options,

View File

@@ -10,7 +10,7 @@ export interface Contact {
standing: STANDING; standing: STANDING;
} }
export function getAllianceContacts(options: EsiOptions, alliance_id: number, page: number = 1) { export function getAllianceContacts(options: EsiOptions, alliance_id: number, page: number = 1): Promise<Contact[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-alliances.read_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-alliances.read_contacts.v1']);
return esiFetch<Contact[]>(`/alliances/${alliance_id}/contacts/?page=${page}`, { return esiFetch<Contact[]>(`/alliances/${alliance_id}/contacts/?page=${page}`, {
...options, ...options,
@@ -23,7 +23,7 @@ export interface ContactLabel {
name: string; name: string;
} }
export function getAllianceContactLabels(options: EsiOptions, alliance_id: number) { export function getAllianceContactLabels(options: EsiOptions, alliance_id: number): Promise<ContactLabel[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-alliances.read_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-alliances.read_contacts.v1']);
return esiFetch<ContactLabel[]>(`/alliances/${alliance_id}/contacts/labels/`, { return esiFetch<ContactLabel[]>(`/alliances/${alliance_id}/contacts/labels/`, {
...options, ...options,
@@ -31,7 +31,7 @@ export function getAllianceContactLabels(options: EsiOptions, alliance_id: numbe
}); });
} }
export function deleteCharacterContacts(options: EsiOptions, character_ids: number[]) { export function deleteCharacterContacts(options: EsiOptions, character_ids: number[]): Promise<void> {
if (character_ids.length === 0) return; if (character_ids.length === 0) return;
if (character_ids.length > 20) throw 'Maximum of 20 IDs can be deleted at once'; if (character_ids.length > 20) throw 'Maximum of 20 IDs can be deleted at once';
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.write_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.write_contacts.v1']);
@@ -48,7 +48,7 @@ export interface CharacterContact extends Contact {
is_watched?: boolean; is_watched?: boolean;
} }
export function getCharacterContacts(options: EsiOptions, page: number = 1) { export function getCharacterContacts(options: EsiOptions, page: number = 1): Promise<CharacterContact[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_contacts.v1']);
return esiFetch<CharacterContact[]>(`/characters/${character_id}/contacts/?page=${page}`, { return esiFetch<CharacterContact[]>(`/characters/${character_id}/contacts/?page=${page}`, {
...options, ...options,
@@ -62,7 +62,7 @@ export function addCharacterContacts(
standing: STANDING, standing: STANDING,
label_ids?: number[], label_ids?: number[],
watched?: boolean, watched?: boolean,
) { ): Promise<void> {
if (character_ids.length === 0) return; if (character_ids.length === 0) return;
if (character_ids.length > 100) throw 'Maximum of 100 IDs can be added at once'; if (character_ids.length > 100) throw 'Maximum of 100 IDs can be added at once';
if (label_ids && label_ids.length > 63) throw 'Maximum of 63 label IDs can be assigned at once'; if (label_ids && label_ids.length > 63) throw 'Maximum of 63 label IDs can be assigned at once';
@@ -86,7 +86,7 @@ export function editCharacterContacts(
standing: STANDING, standing: STANDING,
label_ids?: number[], label_ids?: number[],
watched?: boolean, watched?: boolean,
) { ): Promise<void> {
if (character_ids.length === 0) return; if (character_ids.length === 0) return;
if (character_ids.length > 100) throw 'Maximum of 100 IDs can be edited at once'; if (character_ids.length > 100) throw 'Maximum of 100 IDs can be edited at once';
if (label_ids && label_ids.length > 63) throw 'Maximum of 63 label IDs can be assigned at once'; if (label_ids && label_ids.length > 63) throw 'Maximum of 63 label IDs can be assigned at once';
@@ -104,7 +104,7 @@ export function editCharacterContacts(
); );
} }
export function getCharacterContactLabels(options: EsiOptions) { export function getCharacterContactLabels(options: EsiOptions): Promise<Partial<ContactLabel>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-characters.read_contacts.v1']);
return esiFetch<Partial<ContactLabel>[]>(`/characters/${character_id}/contacts/labels/`, { return esiFetch<Partial<ContactLabel>[]>(`/characters/${character_id}/contacts/labels/`, {
...options, ...options,
@@ -116,7 +116,7 @@ export interface CorporationContact extends Contact {
is_watched?: boolean; is_watched?: boolean;
} }
export function getCorporationContacts(options: EsiOptions, corporation_id: number, page: number = 1) { export function getCorporationContacts(options: EsiOptions, corporation_id: number, page: number = 1): Promise<CorporationContact[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_contacts.v1']);
return esiFetch<CorporationContact[]>(`/corporations/${corporation_id}/contacts/?page=${page}`, { return esiFetch<CorporationContact[]>(`/corporations/${corporation_id}/contacts/?page=${page}`, {
...options, ...options,
@@ -124,7 +124,7 @@ export function getCorporationContacts(options: EsiOptions, corporation_id: numb
}); });
} }
export function getCorporationContactLabels(options: EsiOptions, corporation_id: number) { export function getCorporationContactLabels(options: EsiOptions, corporation_id: number): Promise<ContactLabel[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_contacts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_contacts.v1']);
return esiFetch<ContactLabel[]>(`/corporations/${corporation_id}/contacts/labels/`, { return esiFetch<ContactLabel[]>(`/corporations/${corporation_id}/contacts/labels/`, {
...options, ...options,

View File

@@ -2,6 +2,13 @@ import { ESI_SCOPE } from '../oauth/auth.types';
import { ESI_RATE_LIMIT_GROUP } from './util/rate-limits'; import { ESI_RATE_LIMIT_GROUP } from './util/rate-limits';
import { checkScopesAndGetCharacterId, esiFetch, type EsiOptions, type PublicEsiOptions } from './util/fetch'; import { checkScopesAndGetCharacterId, esiFetch, type EsiOptions, type PublicEsiOptions } from './util/fetch';
export enum ContractType {
ITEM_EXCHANGE = 'item_exchange',
AUCTION = 'auction',
COURIER = 'courier',
LOAN = 'loan',
}
export interface PublicContract { export interface PublicContract {
buyout?: number; buyout?: number;
collateral?: number; collateral?: number;
@@ -21,10 +28,29 @@ export interface PublicContract {
volume?: number; volume?: number;
} }
export enum ContractAvailability {
PUBLIC = 'public',
PERSONAL = 'personal',
CORPORATION = 'corporation',
ALLIANCE = 'alliance',
}
export enum ContractStatus {
OUTSTANDING = 'outstanding',
IN_PROGRESS = 'in_progress',
FINISHED_ISSUER = 'finished_issuer',
FINISHED_CONTRACTOR = 'finished_contractor',
CANCELLED = 'cancelled',
REJECTED = 'rejected',
FAILED = 'failed',
DELETED = 'deleted',
REVERSED = 'reversed',
}
export interface Contract extends PublicContract { export interface Contract extends PublicContract {
acceptor_id: number; acceptor_id: number;
assignee_id: number; assignee_id: number;
availability: 'public' | 'personal' | 'corporation' | 'alliance'; availability: ContractAvailability;
date_accepted?: string; date_accepted?: string;
date_completed?: string; date_completed?: string;
status: status:
@@ -43,7 +69,7 @@ export interface Contract extends PublicContract {
* Returns contracts available to a character, only if the character is issuer, acceptor or assignee. * Returns contracts available to a character, only if the character is issuer, acceptor or assignee.
* Only returns contracts no older than 30 days, or if the status is "in_progress". * Only returns contracts no older than 30 days, or if the status is "in_progress".
*/ */
export function getCharacterContracts(options: EsiOptions, page: number = 1) { export function getCharacterContracts(options: EsiOptions, page: number = 1): Promise<Contract[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_character_contracts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_character_contracts.v1']);
return esiFetch<Contract[]>(`/characters/${character_id}/contracts/?page=${page}`, { return esiFetch<Contract[]>(`/characters/${character_id}/contracts/?page=${page}`, {
...options, ...options,
@@ -61,7 +87,7 @@ export interface ContractBid extends PublicContractBid {
bidder_id: number; bidder_id: number;
} }
export function getContractBids(options: EsiOptions, contract_id: number) { export function getContractBids(options: EsiOptions, contract_id: number): Promise<ContractBid[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_character_contracts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_character_contracts.v1']);
return esiFetch<ContractBid[]>(`/characters/${character_id}/contracts/${contract_id}/bids/`, { return esiFetch<ContractBid[]>(`/characters/${character_id}/contracts/${contract_id}/bids/`, {
...options, ...options,
@@ -78,7 +104,7 @@ export interface ContractItem {
type_id: number; // type ID of the item type_id: number; // type ID of the item
} }
export function getContractItems(options: EsiOptions, contract_id: number) { export function getContractItems(options: EsiOptions, contract_id: number): Promise<ContractItem[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_character_contracts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_character_contracts.v1']);
return esiFetch<ContractItem[]>(`/characters/${character_id}/contracts/${contract_id}/items/`, { return esiFetch<ContractItem[]>(`/characters/${character_id}/contracts/${contract_id}/items/`, {
...options, ...options,
@@ -86,7 +112,7 @@ export function getContractItems(options: EsiOptions, contract_id: number) {
}); });
} }
export function getPublicContractBids(contract_id: number, page: number = 1, options?: PublicEsiOptions) { export function getPublicContractBids(contract_id: number, page: number = 1, options?: PublicEsiOptions): Promise<PublicContractBid[]> {
return esiFetch<PublicContractBid[]>(`/contracts/public/bids/${contract_id}?page=${page}`, options); return esiFetch<PublicContractBid[]>(`/contracts/public/bids/${contract_id}?page=${page}`, options);
} }
@@ -102,15 +128,15 @@ export interface PublicContractItem {
type_id: number; // type ID of the item type_id: number; // type ID of the item
} }
export function getPublicContractItems(contract_id: number, page: number = 1, options?: PublicEsiOptions) { export function getPublicContractItems(contract_id: number, page: number = 1, options?: PublicEsiOptions): Promise<PublicContractItem[]> {
return esiFetch<PublicContractItem[]>(`/contracts/public/items/${contract_id}?page=${page}`, options); return esiFetch<PublicContractItem[]>(`/contracts/public/items/${contract_id}?page=${page}`, options);
} }
export function getPublicContracts(region_id: number, page: number = 1, options?: PublicEsiOptions) { export function getPublicContracts(region_id: number, page: number = 1, options?: PublicEsiOptions): Promise<PublicContract[]> {
return esiFetch<PublicContract[]>(`/contracts/public/${region_id}?page=${page}`, options); return esiFetch<PublicContract[]>(`/contracts/public/${region_id}?page=${page}`, options);
} }
export function getCorporationContracts(options: EsiOptions, corporation_id: number, page: number = 1) { export function getCorporationContracts(options: EsiOptions, corporation_id: number, page: number = 1): Promise<Contract[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_corporation_contracts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_corporation_contracts.v1']);
return esiFetch<Contract[]>(`/corporations/${corporation_id}/contracts/?page=${page}`, { return esiFetch<Contract[]>(`/corporations/${corporation_id}/contracts/?page=${page}`, {
...options, ...options,
@@ -118,7 +144,7 @@ export function getCorporationContracts(options: EsiOptions, corporation_id: num
}); });
} }
export function getCorporationContractBids(options: EsiOptions, corporation_id: number, contract_id: number) { export function getCorporationContractBids(options: EsiOptions, corporation_id: number, contract_id: number): Promise<ContractBid[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_corporation_contracts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_corporation_contracts.v1']);
return esiFetch<ContractBid[]>(`/corporations/${corporation_id}/contracts/${contract_id}/bids/`, { return esiFetch<ContractBid[]>(`/corporations/${corporation_id}/contracts/${contract_id}/bids/`, {
...options, ...options,
@@ -126,7 +152,7 @@ export function getCorporationContractBids(options: EsiOptions, corporation_id:
}); });
} }
export function getCorporationContractItems(options: EsiOptions, corporation_id: number, contract_id: number) { export function getCorporationContractItems(options: EsiOptions, corporation_id: number, contract_id: number): Promise<ContractItem[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_corporation_contracts.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-contracts.read_corporation_contracts.v1']);
return esiFetch<ContractItem[]>(`/corporations/${corporation_id}/contracts/${contract_id}/items/`, { return esiFetch<ContractItem[]>(`/corporations/${corporation_id}/contracts/${contract_id}/items/`, {
...options, ...options,

View File

@@ -50,7 +50,7 @@ export function listCorporationProjects(
limit?: number; limit?: number;
state?: 'Unspecified' | 'Active' | 'Closed' | 'Completed' | 'Expired' | 'Deleted'; state?: 'Unspecified' | 'Active' | 'Closed' | 'Completed' | 'Expired' | 'Deleted';
} = {}, } = {},
) { ): Promise<CorporationProjectResponse> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_projects.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_projects.v1']);
const queryParams = new URLSearchParams(); const queryParams = new URLSearchParams();
if (filters.after) queryParams.append('after', filters.after); if (filters.after) queryParams.append('after', filters.after);

View File

@@ -8,7 +8,7 @@ import { checkScopesAndGetCharacterId, esiFetch, type EsiOptions, type PublicEsi
import type { Blueprint, Icons, STANDING } from './types/shared'; import type { Blueprint, Icons, STANDING } from './types/shared';
import type { CorporationRoles } from './types/corporation'; import type { CorporationRoles } from './types/corporation';
export async function getNpcCorporations(options?: PublicEsiOptions) { export async function getNpcCorporations(options?: PublicEsiOptions): Promise<number[]> {
return await esiFetch<number[]>('/corporations/npccorps', options); return await esiFetch<number[]>('/corporations/npccorps', options);
} }
@@ -29,7 +29,7 @@ interface CorporationInfo {
war_eligible?: boolean; war_eligible?: boolean;
} }
export async function getCorporationData(corporation_id: number, options?: PublicEsiOptions) { export async function getCorporationData(corporation_id: number, options?: PublicEsiOptions): Promise<CorporationInfo> {
return await esiFetch<CorporationInfo>(`/corporations/${corporation_id}/`, options); return await esiFetch<CorporationInfo>(`/corporations/${corporation_id}/`, options);
} }
@@ -40,11 +40,15 @@ interface AllianceHistory {
start_date: string; start_date: string;
} }
export async function getCorporationAllianceHistory(corporation_id: number, options?: PublicEsiOptions) { export async function getCorporationAllianceHistory(corporation_id: number, options?: PublicEsiOptions): Promise<AllianceHistory[]> {
return await esiFetch<AllianceHistory[]>(`/corporations/${corporation_id}/alliancehistory/`, options); return await esiFetch<AllianceHistory[]>(`/corporations/${corporation_id}/alliancehistory/`, options);
} }
export async function getCorporationBlueprints(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationBlueprints(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<Partial<Blueprint>[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_blueprints.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_blueprints.v1']);
return await esiFetch<Partial<Blueprint>[]>(`/corporations/${corporation_id}/blueprints/?page=${page}`, { return await esiFetch<Partial<Blueprint>[]>(`/corporations/${corporation_id}/blueprints/?page=${page}`, {
...options, ...options,
@@ -52,7 +56,7 @@ export async function getCorporationBlueprints(options: EsiOptions, corporation_
}); });
} }
export async function getAllCorporationALSCLogs(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getAllCorporationALSCLogs(options: EsiOptions, corporation_id: number, page: number = 1): Promise<any[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_container_logs.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_container_logs.v1']);
return await esiFetch<any[]>(`/corporations/${corporation_id}/containers/logs/?page=${page}`, { return await esiFetch<any[]>(`/corporations/${corporation_id}/containers/logs/?page=${page}`, {
...options, ...options,
@@ -70,7 +74,7 @@ export interface CorporationDivisions {
}[]; }[];
} }
export async function getCorporationDivisions(options: EsiOptions, corporation_id: number) { export async function getCorporationDivisions(options: EsiOptions, corporation_id: number): Promise<CorporationDivisions> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_divisions.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_divisions.v1']);
return await esiFetch<CorporationDivisions>(`/corporations/${corporation_id}/divisions/`, { return await esiFetch<CorporationDivisions>(`/corporations/${corporation_id}/divisions/`, {
...options, ...options,
@@ -84,14 +88,14 @@ export interface CorporationFacility {
type_id: number; type_id: number;
} }
export async function getCorporationFacilities(options: EsiOptions, corporation_id: number) { export async function getCorporationFacilities(options: EsiOptions, corporation_id: number): Promise<CorporationFacility[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_facilities.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_facilities.v1']);
return await esiFetch<CorporationFacility[]>(`/corporations/${corporation_id}/facilities/`, { return await esiFetch<CorporationFacility[]>(`/corporations/${corporation_id}/facilities/`, {
...options, ...options,
}); });
} }
export async function getCorporationIcons(corporation_id: number, options?: PublicEsiOptions) { export async function getCorporationIcons(corporation_id: number, options?: PublicEsiOptions): Promise<Icons> {
return await esiFetch<Icons>(`/corporations/${corporation_id}/icons/`, options); return await esiFetch<Icons>(`/corporations/${corporation_id}/icons/`, options);
} }
@@ -103,7 +107,7 @@ export interface CorporationMedal {
title: string; title: string;
} }
export async function getCorporationMedals(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationMedals(options: EsiOptions, corporation_id: number, page: number = 1): Promise<CorporationMedal[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_medals.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_medals.v1']);
return await esiFetch<CorporationMedal[]>(`/corporations/${corporation_id}/medals/?page=${page}`, { return await esiFetch<CorporationMedal[]>(`/corporations/${corporation_id}/medals/?page=${page}`, {
...options, ...options,
@@ -120,7 +124,11 @@ export interface CorporationIssuedMedal {
status: string; status: string;
} }
export async function getCorporationIssuedMedals(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationIssuedMedals(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<CorporationIssuedMedal[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_medals.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_medals.v1']);
return await esiFetch<CorporationIssuedMedal[]>(`/corporations/${corporation_id}/medals/issued/?page=${page}`, { return await esiFetch<CorporationIssuedMedal[]>(`/corporations/${corporation_id}/medals/issued/?page=${page}`, {
...options, ...options,
@@ -128,7 +136,7 @@ export async function getCorporationIssuedMedals(options: EsiOptions, corporatio
}); });
} }
export async function getCorporationMembers(options: EsiOptions, corporation_id: number) { export async function getCorporationMembers(options: EsiOptions, corporation_id: number): Promise<number[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_corporation_membership.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_corporation_membership.v1']);
return await esiFetch<number[]>(`/corporations/${corporation_id}/members/`, { return await esiFetch<number[]>(`/corporations/${corporation_id}/members/`, {
...options, ...options,
@@ -136,7 +144,7 @@ export async function getCorporationMembers(options: EsiOptions, corporation_id:
}); });
} }
export async function getCorporationMemberLimit(options: EsiOptions, corporation_id: number) { export async function getCorporationMemberLimit(options: EsiOptions, corporation_id: number): Promise<number> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.track_members.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.track_members.v1']);
return await esiFetch<number>(`/corporations/${corporation_id}/members/limit/`, { return await esiFetch<number>(`/corporations/${corporation_id}/members/limit/`, {
...options, ...options,
@@ -149,7 +157,7 @@ export interface CorporationMemberTitles {
titles: number[]; titles: number[];
} }
export async function getCorporationMemberTitles(options: EsiOptions, corporation_id: number) { export async function getCorporationMemberTitles(options: EsiOptions, corporation_id: number): Promise<CorporationMemberTitles[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_titles.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_titles.v1']);
return await esiFetch<CorporationMemberTitles[]>(`/corporations/${corporation_id}/members/titles/`, { return await esiFetch<CorporationMemberTitles[]>(`/corporations/${corporation_id}/members/titles/`, {
...options, ...options,
@@ -167,7 +175,7 @@ export interface CorporationMemberTracking {
start_date?: string; start_date?: string;
} }
export async function getCorporationMemberTracking(options: EsiOptions, corporation_id: number) { export async function getCorporationMemberTracking(options: EsiOptions, corporation_id: number): Promise<CorporationMemberTracking[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.track_members.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.track_members.v1']);
return await esiFetch<CorporationMemberTracking[]>(`/corporations/${corporation_id}/membertracking/`, { return await esiFetch<CorporationMemberTracking[]>(`/corporations/${corporation_id}/membertracking/`, {
...options, ...options,
@@ -187,7 +195,7 @@ export interface CorporationMemberRole {
roles_at_other: CorporationRoles[]; roles_at_other: CorporationRoles[];
} }
export async function getCorporationMemberRoles(options: EsiOptions, corporation_id: number) { export async function getCorporationMemberRoles(options: EsiOptions, corporation_id: number): Promise<CorporationMemberRole[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_corporation_membership.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_corporation_membership.v1']);
return await esiFetch<CorporationMemberRole[]>(`/corporations/${corporation_id}/members/roles/`, { return await esiFetch<CorporationMemberRole[]>(`/corporations/${corporation_id}/members/roles/`, {
...options, ...options,
@@ -212,7 +220,11 @@ export interface CorporationMemberRoleHistory {
| 'roles_at_other'; | 'roles_at_other';
} }
export async function getCorporationMemberRoleHistory(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationMemberRoleHistory(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<CorporationMemberRoleHistory[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_corporation_membership.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_corporation_membership.v1']);
return await esiFetch<CorporationMemberRoleHistory[]>(`/corporations/${corporation_id}/roles/history/?page=${page}`, { return await esiFetch<CorporationMemberRoleHistory[]>(`/corporations/${corporation_id}/roles/history/?page=${page}`, {
...options, ...options,
@@ -226,7 +238,11 @@ export interface CorporationShareholder {
shareholder_type: 'character' | 'corporation'; shareholder_type: 'character' | 'corporation';
} }
export async function getCorporationShareholders(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationShareholders(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<CorporationShareholder[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_corporation_wallets.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_corporation_wallets.v1']);
return await esiFetch<CorporationShareholder[]>(`/corporations/${corporation_id}/shareholders/?page=${page}`, { return await esiFetch<CorporationShareholder[]>(`/corporations/${corporation_id}/shareholders/?page=${page}`, {
...options, ...options,
@@ -240,7 +256,11 @@ export interface CorporationStanding {
standing: STANDING; standing: STANDING;
} }
export async function getCorporationStandings(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationStandings(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<CorporationStanding[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_standings.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_standings.v1']);
return await esiFetch<CorporationStanding[]>(`/corporations/${corporation_id}/standings/?page=${page}`, { return await esiFetch<CorporationStanding[]>(`/corporations/${corporation_id}/standings/?page=${page}`, {
...options, ...options,
@@ -259,7 +279,11 @@ export interface CorporationStarbase {
unanchor_at?: string; unanchor_at?: string;
} }
export async function getCorporationStarbases(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationStarbases(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<CorporationStarbase[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_starbases.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_starbases.v1']);
return await esiFetch<CorporationStarbase[]>(`/corporations/${corporation_id}/starbases/?page=${page}`, { return await esiFetch<CorporationStarbase[]>(`/corporations/${corporation_id}/starbases/?page=${page}`, {
...options, ...options,
@@ -288,7 +312,12 @@ export interface StarbaseDetail {
use_alliance_standings: boolean; use_alliance_standings: boolean;
} }
export async function getCorporationStarbaseDetail(options: EsiOptions, corporation_id: number, starbase_id: number, system_id: number) { export async function getCorporationStarbaseDetail(
options: EsiOptions,
corporation_id: number,
starbase_id: number,
system_id: number,
): Promise<StarbaseDetail> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_starbases.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_starbases.v1']);
return await esiFetch<StarbaseDetail>(`/corporations/${corporation_id}/starbases/${starbase_id}/?system_id=${system_id}`, { return await esiFetch<StarbaseDetail>(`/corporations/${corporation_id}/starbases/${starbase_id}/?system_id=${system_id}`, {
...options, ...options,
@@ -331,7 +360,11 @@ export interface CorporationStructure {
unanchors_at: string; unanchors_at: string;
} }
export async function getCorporationStructures(options: EsiOptions, corporation_id: number, page: number = 1) { export async function getCorporationStructures(
options: EsiOptions,
corporation_id: number,
page: number = 1,
): Promise<CorporationStructure[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_structures.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_structures.v1']);
return await esiFetch<CorporationStructure[]>(`/corporations/${corporation_id}/structures/?page=${page}`, { return await esiFetch<CorporationStructure[]>(`/corporations/${corporation_id}/structures/?page=${page}`, {
...options, ...options,
@@ -351,7 +384,7 @@ export interface CorporationTitle {
title_id: number; title_id: number;
} }
export async function getCorporationTitles(options: EsiOptions, corporation_id: number) { export async function getCorporationTitles(options: EsiOptions, corporation_id: number): Promise<CorporationTitle[]> {
checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_titles.v1']); checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-corporations.read_titles.v1']);
return await esiFetch<CorporationTitle[]>(`/corporations/${corporation_id}/titles/`, { return await esiFetch<CorporationTitle[]>(`/corporations/${corporation_id}/titles/`, {
...options, ...options,

View File

@@ -7,10 +7,12 @@ export * from './util/options';
export * from './mail'; export * from './mail';
export * from './character'; export * from './character';
export * from './alliance'; export * from './alliance';
export * from './contracts';
import * as alliance from './alliance'; import * as alliance from './alliance';
import * as assets from './assets'; import * as assets from './assets';
import * as character from './character'; import * as character from './character';
import * as corporation from './corporation'; import * as corporation from './corporation';
import * as contracts from './contracts';
export { alliance, assets, character, corporation }; export { alliance, assets, character, corporation, contracts };

View File

@@ -8,7 +8,7 @@ export interface Location {
} }
// required scope: esi-location.read_location.v1 // required scope: esi-location.read_location.v1
export function getCharacterLocation(options: EsiOptions) { export function getCharacterLocation(options: EsiOptions): Promise<Partial<Location>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-location.read_location.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-location.read_location.v1']);
return esiFetch<Partial<Location>>(`/characters/${character_id}/location/`, options); return esiFetch<Partial<Location>>(`/characters/${character_id}/location/`, options);
} }
@@ -21,7 +21,7 @@ export interface Online {
} }
// required scope: esi-location.read_online.v1 // required scope: esi-location.read_online.v1
export function getCharacterOnline(options: EsiOptions) { export function getCharacterOnline(options: EsiOptions): Promise<Partial<Online>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-location.read_online.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-location.read_online.v1']);
return esiFetch<Partial<Online>>(`/characters/${character_id}/online/`, options); return esiFetch<Partial<Online>>(`/characters/${character_id}/online/`, options);
} }
@@ -33,7 +33,7 @@ export interface CurrentShip {
} }
// required scope: esi-location.read_ship_type.v1 // required scope: esi-location.read_ship_type.v1
export function getCharacterCurrentShip(options: EsiOptions) { export function getCharacterCurrentShip(options: EsiOptions): Promise<Partial<CurrentShip>> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-location.read_ship_type.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-location.read_ship_type.v1']);
return esiFetch<Partial<CurrentShip>>(`/characters/${character_id}/ship/`, options); return esiFetch<Partial<CurrentShip>>(`/characters/${character_id}/ship/`, options);
} }

View File

@@ -16,7 +16,7 @@ export interface MailHeader {
} }
// requires scope: esi-mail.read_mail.v1 // requires scope: esi-mail.read_mail.v1
export function getMailHeaders(options: EsiOptions) { export function getMailHeaders(options: EsiOptions): Promise<MailHeader[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']);
return esiFetch<MailHeader[]>(`/characters/${character_id}/mail/`, { return esiFetch<MailHeader[]>(`/characters/${character_id}/mail/`, {
...options, ...options,
@@ -34,7 +34,7 @@ export interface SendMail {
} }
// requires scope: esi-mail.send_mail.v1 // requires scope: esi-mail.send_mail.v1
export function sendMail(options: EsiOptions, mail: SendMail) { export function sendMail(options: EsiOptions, mail: SendMail): Promise<any> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.send_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.send_mail.v1']);
return esiFetch(`/characters/${character_id}/mail/`, { return esiFetch(`/characters/${character_id}/mail/`, {
...options, ...options,
@@ -44,7 +44,7 @@ export function sendMail(options: EsiOptions, mail: SendMail) {
} }
// requires scope: esi-mail.read_mail.v1 // requires scope: esi-mail.read_mail.v1
export function deleteMail(options: EsiOptions, mailID: number) { export function deleteMail(options: EsiOptions, mailID: number): Promise<any> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']);
return esiFetch(`/characters/${character_id}/mail/${mailID}/`, { return esiFetch(`/characters/${character_id}/mail/${mailID}/`, {
...options, ...options,
@@ -66,7 +66,7 @@ export interface Mail {
} }
// requires scope: esi-mail.read_mail.v1 // requires scope: esi-mail.read_mail.v1
export function getMail(options: EsiOptions, mailID: number) { export function getMail(options: EsiOptions, mailID: number): Promise<Mail> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']);
return esiFetch<Mail>(`/characters/${character_id}/mail/${mailID}/`, { return esiFetch<Mail>(`/characters/${character_id}/mail/${mailID}/`, {
...options, ...options,
@@ -79,7 +79,7 @@ export interface MailMetadata {
} }
// requires scope: esi-mail.organize_mail.v1 // requires scope: esi-mail.organize_mail.v1
export function updateMailMetadata(options: EsiOptions, mailID: number, metadata: MailMetadata) { export function updateMailMetadata(options: EsiOptions, mailID: number, metadata: MailMetadata): Promise<any> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']);
return esiFetch(`/characters/${character_id}/mail/${mailID}/`, { return esiFetch(`/characters/${character_id}/mail/${mailID}/`, {
...options, ...options,
@@ -99,7 +99,7 @@ export interface MailLabels {
} }
// requires scope: esi-mail.read_mail.v1 // requires scope: esi-mail.read_mail.v1
export function getMailLabels(options: EsiOptions) { export function getMailLabels(options: EsiOptions): Promise<MailLabels> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']);
return esiFetch<MailLabels>(`/characters/${character_id}/mail/labels/`, { return esiFetch<MailLabels>(`/characters/${character_id}/mail/labels/`, {
...options, ...options,
@@ -112,7 +112,7 @@ export interface CreateMailLabel {
} }
// requires scope: esi-mail.organize_mail.v1 // requires scope: esi-mail.organize_mail.v1
export function createMailLabel(options: EsiOptions, label: CreateMailLabel) { export function createMailLabel(options: EsiOptions, label: CreateMailLabel): Promise<any> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']);
return esiFetch(`/characters/${character_id}/mail/labels/`, { return esiFetch(`/characters/${character_id}/mail/labels/`, {
...options, ...options,
@@ -122,7 +122,7 @@ export function createMailLabel(options: EsiOptions, label: CreateMailLabel) {
} }
// requires scope: esi-mail.organize_mail.v1 // requires scope: esi-mail.organize_mail.v1
export function deleteMailLabel(options: EsiOptions, labelID: number) { export function deleteMailLabel(options: EsiOptions, labelID: number): Promise<any> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.organize_mail.v1']);
return esiFetch(`/characters/${character_id}/mail/labels/${labelID}/`, { return esiFetch(`/characters/${character_id}/mail/labels/${labelID}/`, {
...options, ...options,
@@ -136,7 +136,7 @@ export interface MailingList {
} }
// requires scope: esi-mail.read_mail.v1 // requires scope: esi-mail.read_mail.v1
export function getMailingLists(options: EsiOptions) { export function getMailingLists(options: EsiOptions): Promise<MailingList[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-mail.read_mail.v1']);
return esiFetch<MailingList[]>(`/characters/${character_id}/mail/lists/`, { return esiFetch<MailingList[]>(`/characters/${character_id}/mail/lists/`, {
...options, ...options,

View File

@@ -13,7 +13,7 @@ export interface CharacterAttributes {
} }
// required scope: esi-skills.read_skills.v1 // required scope: esi-skills.read_skills.v1
export function getCharacterAttributes(options: EsiOptions) { export function getCharacterAttributes(options: EsiOptions): Promise<CharacterAttributes> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-skills.read_skills.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-skills.read_skills.v1']);
return esiFetch<CharacterAttributes>(`/characters/${character_id}/attributes`, { return esiFetch<CharacterAttributes>(`/characters/${character_id}/attributes`, {
...options, ...options,
@@ -32,7 +32,7 @@ export interface SkillQueueItem {
} }
// required scope: esi-skills.read_skillqueue.v1 // required scope: esi-skills.read_skillqueue.v1
export function getCharacterSkillQueue(options: EsiOptions) { export function getCharacterSkillQueue(options: EsiOptions): Promise<SkillQueueItem[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-skills.read_skillqueue.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-skills.read_skillqueue.v1']);
return esiFetch<SkillQueueItem[]>(`/characters/${character_id}/skillqueue`, { return esiFetch<SkillQueueItem[]>(`/characters/${character_id}/skillqueue`, {
...options, ...options,
@@ -53,14 +53,14 @@ export interface CharacterSkills {
} }
// required scope: esi-skills.read_skills.v1 // required scope: esi-skills.read_skills.v1
export function getCharacterSkills(options: EsiOptions) { export function getCharacterSkills(options: EsiOptions): Promise<CharacterSkills> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-skills.read_skills.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-skills.read_skills.v1']);
return esiFetch<CharacterSkills>(`/characters/${character_id}/skills`, { return esiFetch<CharacterSkills>(`/characters/${character_id}/skills`, {
...options, ...options,
}); });
} }
export function calculateTrainingPercentage(queuedSkill: SkillQueueItem) { export function calculateTrainingPercentage(queuedSkill: SkillQueueItem): number {
// percentage in when training started // percentage in when training started
const trainingStartPosition = (queuedSkill.training_start_sp! - queuedSkill.level_start_sp!) / queuedSkill.level_end_sp!; const trainingStartPosition = (queuedSkill.training_start_sp! - queuedSkill.level_start_sp!) / queuedSkill.level_end_sp!;
// percentage completed between start and now // percentage completed between start and now

View File

@@ -2,7 +2,7 @@ import { ESI_SCOPE } from '../oauth';
import { checkScopesAndGetCharacterId, esiFetch, type EsiOptions } from './util/fetch'; import { checkScopesAndGetCharacterId, esiFetch, type EsiOptions } from './util/fetch';
// required scope: esi-wallet.read_character_wallet.v1 // required scope: esi-wallet.read_character_wallet.v1
export function getCharacterWallet(options: EsiOptions) { export function getCharacterWallet(options: EsiOptions): Promise<number> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_character_wallet.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_character_wallet.v1']);
return esiFetch<number>(`/characters/${character_id}/wallet/`, { return esiFetch<number>(`/characters/${character_id}/wallet/`, {
...options, ...options,
@@ -23,7 +23,7 @@ export interface WalletTransaction {
} }
// required scope: esi-wallet.read_character_wallet.v1 // required scope: esi-wallet.read_character_wallet.v1
export function getCharacterWalletTransactions(options: EsiOptions, fromId: number) { export function getCharacterWalletTransactions(options: EsiOptions, fromId: number): Promise<Partial<WalletTransaction>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_character_wallet.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_character_wallet.v1']);
return esiFetch<Partial<WalletTransaction>[]>(`/characters/${character_id}/wallet/transactions/`, { return esiFetch<Partial<WalletTransaction>[]>(`/characters/${character_id}/wallet/transactions/`, {
...options, ...options,
@@ -49,7 +49,7 @@ export interface WalletJournalEntry {
} }
// required scope: esi-wallet.read_character_wallet.v1 // required scope: esi-wallet.read_character_wallet.v1
export function getCharacterWalletJournal(options: EsiOptions, page: number = 1) { export function getCharacterWalletJournal(options: EsiOptions, page: number = 1): Promise<Partial<WalletJournalEntry>[]> {
const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_character_wallet.v1']); const character_id = checkScopesAndGetCharacterId(options, ESI_SCOPE['esi-wallet.read_character_wallet.v1']);
return esiFetch<Partial<WalletJournalEntry>[]>(`/characters/${character_id}/wallet/journal/?page=${page}`, { return esiFetch<Partial<WalletJournalEntry>[]>(`/characters/${character_id}/wallet/journal/?page=${page}`, {
...options, ...options,

View File

@@ -0,0 +1,10 @@
// Get info for a blueprint
GET https://api.everef.net/v1/industry/cost
?blueprint_id=21028
&runs=40
&structure_type_id=35825
&security=NULL_SEC
&rig_id=43891
&rig_id=43892
&copying_cost=0.0168

View File

@@ -0,0 +1,94 @@
import createClient, { type FetchOptions, type FetchResponse } from 'openapi-fetch';
import type { components, paths } from './schema.d';
export * as schema from './schema.d';
const client = createClient<paths>({
baseUrl: 'https://api.everef.net',
});
export function getBlueprintCosts(blueprintTypeId: number): Promise<
FetchResponse<
{
parameters: {
query?: {
input?: components['schemas']['IndustryCostInput'];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['IndustryCost'];
};
};
400: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['ApiError'];
};
};
500: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['ApiError'];
};
};
};
},
FetchOptions<{
parameters: {
query?: {
input?: components['schemas']['IndustryCostInput'];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
200: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['IndustryCost'];
};
};
400: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['ApiError'];
};
};
500: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': components['schemas']['ApiError'];
};
};
};
}>,
`${string}/${string}`
>
> {
return client.GET('/v1/industry/cost', {
query: {
blueprint_type_id: blueprintTypeId,
},
});
}

702
packages/lib/src/eve/everef/schema.d.ts vendored Normal file
View File

@@ -0,0 +1,702 @@
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/
export interface paths {
"/v1/industry/cost": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get: operations["industryCost"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/v1/search": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Search for inventory types
* @description Search for EVE Online inventory types by name
*/
get: operations["search"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
}
export type webhooks = Record<string, never>;
export interface components {
schemas: {
ApiError: {
message?: string;
};
CopyingCost: {
/** @description The alpha clone tax amount */
alpha_clone_tax?: number;
/** @description The estimated item value (EIV). This may not be completely accurate. */
estimated_item_value?: number;
/** @description The facility amount */
facility_tax?: number;
job_cost_base?: number;
materials?: {
[key: string]: components["schemas"]["MaterialCost"];
};
materials_volume?: number;
/** Format: int64 */
product_id?: number;
product_volume?: number;
/**
* Format: double
* @description The number of runs
*/
runs?: number;
/** @description The SCC surcharge amount */
scc_surcharge?: number;
/** @description Bonuses to system cost from structures, rigs, etc. */
system_cost_bonuses?: number;
/**
* @description The system cost index amount.
* Note that this will always be a slightly off, as the ESI does not report the full precision of the system cost index rates.
* See https://github.com/esi/esi-issues/issues/1411
*/
system_cost_index?: number;
time?: string;
total_cost?: number;
total_cost_per_run?: number;
/** @description The total amount of ISK required to start the job */
total_job_cost?: number;
total_material_cost?: number;
};
IndustryCost: {
copying?: {
[key: string]: components["schemas"]["CopyingCost"];
};
input?: components["schemas"]["IndustryCostInput"];
invention?: {
[key: string]: components["schemas"]["InventionCost"];
};
manufacturing?: {
[key: string]: components["schemas"]["ProductionCost"];
};
reaction?: {
[key: string]: components["schemas"]["ProductionCost"];
};
};
IndustryCostInput: {
/**
* Format: int32
* @description The Advanced Capital Ship Construction skill level the installing character
* @default 5
*/
advanced_capital_ship_construction: number;
/**
* Format: int32
* @description The Advanced Industrial Ship Construction skill level the installing character
* @default 5
*/
advanced_industrial_ship_construction: number;
/**
* Format: int32
* @description The Advanced Industry skill level the installing character
* @default 5
*/
advanced_industry: number;
/**
* Format: int32
* @description The Advanced Large Ship Construction skill level the installing character
* @default 5
*/
advanced_large_ship_construction: number;
/**
* Format: int32
* @description The Advanced Medium Ship Construction skill level the installing character
* @default 5
*/
advanced_medium_ship_construction: number;
/**
* Format: int32
* @description The Advanced Small Ship Construction skill level the installing character
* @default 5
*/
advanced_small_ship_construction: number;
/**
* @description Whether installing character is an alpha clone or not
* @default false
*/
alpha: boolean;
/**
* Format: int32
* @description The Amarr Encryption Methods skill level the installing character
* @default 5
*/
amarr_encryption_methods: number;
/**
* Format: int32
* @description The Amarr Starship Engineering skill level the installing character
* @default 5
*/
amarr_starship_engineering: number;
/**
* Format: int64
* @description The blueprint ID to calculate
*/
blueprint_id?: number;
/**
* Format: int32
* @description The Caldari Encryption Methods skill level the installing character
* @default 5
*/
caldari_encryption_methods: number;
/**
* Format: int32
* @description The Caldari Starship Engineering skill level the installing character
* @default 5
*/
caldari_starship_engineering: number;
/** @description The copying cost index of the system where the job is installed */
copying_cost?: number;
/**
* Format: int32
* @description The Core Subsystem Technology skill level the installing character
* @default 5
*/
core_subsystem_technology: number;
/**
* Format: int64
* @description The decryptor type ID to use
*/
decryptor_id?: number;
/**
* Format: int32
* @description The Defensive Subsystem Technology skill level the installing character
* @default 5
*/
defensive_subsystem_technology: number;
/**
* Format: int32
* @description The Electromagnetic Physics skill level the installing character
* @default 5
*/
electromagnetic_physics: number;
/**
* Format: int32
* @description The Electronic Engineering skill level the installing character
* @default 5
*/
electronic_engineering: number;
/**
* @description The facility tax rate of the station or structure where the job is installed
* @default 0
*/
facility_tax: number;
/**
* Format: int32
* @description The Gallente Encryption Methods skill level the installing character
* @default 5
*/
gallente_encryption_methods: number;
/**
* Format: int32
* @description The Gallente Starship Engineering skill level the installing character
* @default 5
*/
gallente_starship_engineering: number;
/**
* Format: int32
* @description The Graviton Physics skill level the installing character
* @default 5
*/
graviton_physics: number;
/**
* Format: int32
* @description The High Energy Physics skill level the installing character
* @default 5
*/
high_energy_physics: number;
/**
* Format: int32
* @description The Hydromagnetic Physics skill level the installing character
* @default 5
*/
hydromagnetic_physics: number;
/**
* Format: int32
* @description The Industry skill level the installing character
* @default 5
*/
industry: number;
/** @description The invention cost index of the system where the job is installed */
invention_cost?: number;
/**
* Format: int32
* @description The Laser Physics skill level the installing character
* @default 5
*/
laser_physics: number;
/** @description The manufacturing cost index of the system where the job is installed */
manufacturing_cost?: number;
/**
* @description Where to get material prices from
* @default ESI_AVG
* @enum {string}
*/
material_prices: "ESI_AVG" | "FUZZWORK_JITA_SELL_MIN" | "FUZZWORK_JITA_SELL_AVG" | "FUZZWORK_JITA_BUY_MAX" | "FUZZWORK_JITA_BUY_AVG";
/**
* Format: int32
* @description The material efficiency of the blueprint. Defaults to 10 for T1 products or invention output ME to T2 products
*/
me?: number;
/**
* Format: int32
* @description The Mechanical Engineering skill level the installing character
* @default 5
*/
mechanical_engineering: number;
/**
* Format: int32
* @description The Metallurgy skill level the installing character
* @default 5
*/
metallurgy: number;
/**
* Format: int32
* @description The Minmatar Encryption Methods skill level the installing character
* @default 5
*/
minmatar_encryption_methods: number;
/**
* Format: int32
* @description The Minmatar Starship Engineering skill level the installing character
* @default 5
*/
minmatar_starship_engineering: number;
/**
* Format: int32
* @description The Molecular Engineering skill level the installing character
* @default 5
*/
molecular_engineering: number;
/**
* Format: int32
* @description The Mutagenic Stabilization skill level the installing character
* @default 5
*/
mutagenic_stabilization: number;
/**
* Format: int32
* @description The Nanite Engineering skill level the installing character
* @default 5
*/
nanite_engineering: number;
/**
* Format: int32
* @description The Nuclear Physics skill level the installing character
* @default 5
*/
nuclear_physics: number;
/**
* Format: int32
* @description The Offensive Subsystem Technology skill level the installing character
* @default 5
*/
offensive_subsystem_technology: number;
/**
* Format: int32
* @description The Outpost Construction skill level the installing character
* @default 5
*/
outpost_construction: number;
/**
* Format: int32
* @description The Plasma Physics skill level the installing character
* @default 5
*/
plasma_physics: number;
/**
* Format: int64
* @description The desired product type ID
*/
product_id?: number;
/**
* Format: int32
* @description The Propulsion Subsystem Technology skill level the installing character
* @default 5
*/
propulsion_subsystem_technology: number;
/**
* Format: int32
* @description The Quantum Physics skill level the installing character
* @default 5
*/
quantum_physics: number;
/** @description The reaction cost index of the system where the job is installed */
reaction_cost?: number;
/**
* Format: int32
* @description The Reactions skill level the installing character
* @default 5
*/
reactions: number;
/**
* Format: int32
* @description The Research skill level the installing character
* @default 5
*/
research: number;
/** @description The researching material efficiency cost index of the system where the job is installed */
researching_me_cost?: number;
/** @description The researching time efficiency cost index of the system where the job is installed */
researching_te_cost?: number;
/** @description The type IDs of the rigs installed on the sture structure where the job is installed */
rig_id?: number[];
/**
* Format: int32
* @description The Rocket Science skill level the installing character
* @default 5
*/
rocket_science: number;
/**
* Format: int32
* @description The number of runs
* @default 1
*/
runs: number;
/**
* Format: int32
* @description The Science skill level the installing character
* @default 5
*/
science: number;
/**
* @description The security class of the system where the job is installed. If neither security nor system is supplied, high sec is assumed
* @enum {string}
*/
security?: "HIGH_SEC" | "LOW_SEC" | "NULL_SEC";
/**
* Format: int32
* @description The Sleeper Encryption Methods skill level the installing character
* @default 5
*/
sleeper_encryption_methods: number;
/**
* Format: int64
* @description The type ID of the structure where the job is installed. If not set, an NPC station is assumed.
*/
structure_type_id?: number;
/**
* @description Bonus to apply to system cost, such as the faction warfare bonus
* @default 0
* @example -0.5
*/
system_cost_bonus: number;
/**
* Format: int32
* @description The ID of the system where the job is installed. This will resolve security class and cost indices. If neither security nor system is supplied, high sec is assumed
*/
system_id?: number;
/**
* Format: int32
* @description The time efficiency of the blueprint. Defaults to 20 for T1 products or invention output TE to T2 products
*/
te?: number;
/**
* Format: int32
* @description The Triglavian Encryption Methods skill level the installing character
* @default 5
*/
triglavian_encryption_methods: number;
/**
* Format: int32
* @description The Triglavian Quantum Engineering skill level the installing character
* @default 5
*/
triglavian_quantum_engineering: number;
/**
* Format: int32
* @description The Upwell Encryption Methods skill level the installing character
* @default 5
*/
upwell_encryption_methods: number;
/**
* Format: int32
* @description The Upwell Starship Engineering skill level the installing character
* @default 5
*/
upwell_starship_engineering: number;
};
InventionCost: {
/** @description The alpha clone tax amount */
alpha_clone_tax?: number;
avg_cost_per_copy?: number;
avg_cost_per_run?: number;
avg_cost_per_unit?: number;
avg_time_per_copy?: string;
avg_time_per_run?: string;
avg_time_per_unit?: string;
/**
* Format: int64
* @description The source blueprint of the invention
*/
blueprint_id?: number;
/** @description The estimated item value (EIV). This may not be completely accurate. */
estimated_item_value?: number;
/** Format: double */
expected_copies?: number;
/** Format: double */
expected_runs?: number;
/** Format: double */
expected_units?: number;
/** @description The facility amount */
facility_tax?: number;
job_cost_base?: number;
materials?: {
[key: string]: components["schemas"]["MaterialCost"];
};
materials_volume?: number;
/**
* Format: int32
* @description The material efficiency of the invented blueprint
*/
me?: number;
/** Format: double */
probability?: number;
/** Format: int64 */
product_id?: number;
product_volume?: number;
/**
* Format: double
* @description The number of runs
*/
runs?: number;
/**
* Format: int32
* @description The number of runs on each successfully invented copy
*/
runs_per_copy?: number;
/** @description The SCC surcharge amount */
scc_surcharge?: number;
/** @description Bonuses to system cost from structures, rigs, etc. */
system_cost_bonuses?: number;
/**
* @description The system cost index amount.
* Note that this will always be a slightly off, as the ESI does not report the full precision of the system cost index rates.
* See https://github.com/esi/esi-issues/issues/1411
*/
system_cost_index?: number;
/**
* Format: int32
* @description The time efficiency of the invented blueprint
*/
te?: number;
time?: string;
total_cost?: number;
/** @description The total amount of ISK required to start the job */
total_job_cost?: number;
total_material_cost?: number;
/** Format: int32 */
units_per_run?: number;
};
MaterialCost: {
cost?: number;
cost_per_unit?: number;
/** Format: double */
quantity?: number;
/** Format: int64 */
type_id?: number;
volume?: number;
volume_per_unit?: number;
};
ProductionCost: {
/** @description The alpha clone tax amount */
alpha_clone_tax?: number;
/**
* Format: int64
* @description The source blueprint of the manufacture
*/
blueprint_id?: number;
/** @description The estimated item value (EIV). This may not be completely accurate. */
estimated_item_value?: number;
/** @description The facility amount */
facility_tax?: number;
materials?: {
[key: string]: components["schemas"]["MaterialCost"];
};
materials_volume?: number;
/**
* Format: int32
* @description The material efficiency used
*/
me?: number;
/** Format: int64 */
product_id?: number;
product_volume?: number;
/**
* Format: double
* @description The number of runs
*/
runs?: number;
/** @description The SCC surcharge amount */
scc_surcharge?: number;
/** @description Bonuses to system cost from structures, rigs, etc. */
system_cost_bonuses?: number;
/**
* @description The system cost index amount.
* Note that this will always be a slightly off, as the ESI does not report the full precision of the system cost index rates.
* See https://github.com/esi/esi-issues/issues/1411
*/
system_cost_index?: number;
/**
* Format: int32
* @description The time efficiency used
*/
te?: number;
time?: string;
time_per_run?: string;
time_per_unit?: string;
total_cost?: number;
total_cost_per_run?: number;
total_cost_per_unit?: number;
/** @description The total amount of ISK required to start the job */
total_job_cost?: number;
total_material_cost?: number;
/**
* Format: int64
* @description Total number of item produced
*/
units?: number;
/**
* Format: int64
* @description Total number of item produced
*/
units_per_run?: number;
};
SearchEntry: {
/** Format: int64 */
id?: number;
language?: string;
/**
* Format: int64
* @description Relevance score of the search result. Lower is better.
*/
relevance?: number;
title?: string;
/** @enum {string} */
type?: "inventory_type" | "market_group" | "category" | "group";
type_name?: string;
urls?: components["schemas"]["SearchEntryUrls"];
};
SearchEntryUrls: {
everef?: string;
reference_data?: string;
};
SearchResult: {
entries?: components["schemas"]["SearchEntry"][];
};
};
responses: never;
parameters: never;
requestBodies: never;
headers: never;
pathItems: never;
}
export type $defs = Record<string, never>;
export interface operations {
industryCost: {
parameters: {
query?: {
input?: components["schemas"]["IndustryCostInput"];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Success */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["IndustryCost"];
};
};
/** @description Client error */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ApiError"];
};
};
/** @description Server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ApiError"];
};
};
};
};
search: {
parameters: {
query: {
/** @description Search query (minimum 3 characters) */
q: string;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Success */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["SearchResult"];
};
};
/** @description Client error */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ApiError"];
};
};
/** @description Server error */
500: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ApiError"];
};
};
};
};
}

View File

@@ -1,4 +1,4 @@
export * from './esi/index'; export * from './esi';
export * from './db'; export * from './db';
export * from './ref'; export * from './ref';
export * from './third-party'; export * from './third-party';

View File

View File

View File

@@ -0,0 +1,19 @@
import { schema } from '@/eve/everef';
export type IndustryCostInput = schema.components['schemas']['IndustryCostInput'];
export type GeneralOptions = Pick<IndustryCostInput, 'alpha' | 'runs' | 'product_id' | 'material_prices'>;
export type LocationOptions = Pick<
IndustryCostInput,
'system_id' | 'structure_type_id' | 'rig_id' | 'system_cost_bonus' | 'security' | 'facility_tax'
>;
export type IndexOptions = Pick<
IndustryCostInput,
'researching_me_cost' | 'researching_te_cost' | 'manufacturing_cost' | 'copying_cost' | 'invention_cost' | 'reaction_cost'
>;
export type BlueprintOptions = Pick<IndustryCostInput, 'blueprint_id' | 'copying_cost' | 'me' | 'te' | 'decryptor_id'>;
export type Skills = Omit<IndustryCostInput, keyof BlueprintOptions | keyof IndexOptions | keyof LocationOptions | keyof GeneralOptions>;

View File

@@ -18,7 +18,7 @@ export interface Attribute {
readonly tooltip_description?: LocalizedString; readonly tooltip_description?: LocalizedString;
} }
export const getAttribute = (id: number) => { export const getAttribute = (id: number): Attribute => {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.dogma_attributes[String(id)]; const data = dataSets.dogma_attributes[String(id)];
if (!data) throw new Error(`Attribute ID ${id} not found in reference data`); if (!data) throw new Error(`Attribute ID ${id} not found in reference data`);

View File

@@ -37,14 +37,21 @@ export interface Blueprint {
}; };
} }
export function getBlueprint(blueprint_type_id: number) { export function getBlueprint(blueprint_type_id: number): Blueprint {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.blueprints[String(blueprint_type_id)]; const data = dataSets.blueprints[String(blueprint_type_id)];
if (!data) throw new Error(`Blueprint Type ID ${blueprint_type_id} not found in reference data`); if (!data) throw new Error(`Blueprint Type ID ${blueprint_type_id} not found in reference data`);
return data; return data;
} }
export function getManufacturingMaterials(blueprint: Blueprint) { export function getManufacturingMaterials(blueprint: Blueprint):
| any[]
| Promise<
{
type: Type;
quantity: number;
}[]
> {
const manufacturing = blueprint.activities[ActivityType.MANUFACTURING]; const manufacturing = blueprint.activities[ActivityType.MANUFACTURING];
if (!manufacturing) return []; if (!manufacturing) return [];
@@ -56,7 +63,14 @@ export function getManufacturingMaterials(blueprint: Blueprint) {
); );
} }
export function getManufacturingProducts(blueprint: Blueprint) { export function getManufacturingProducts(blueprint: Blueprint):
| any[]
| Promise<
{
type: Type;
quantity: number;
}[]
> {
const manufacturing = blueprint.activities[ActivityType.MANUFACTURING]; const manufacturing = blueprint.activities[ActivityType.MANUFACTURING];
if (!manufacturing) return []; if (!manufacturing) return [];
@@ -68,7 +82,14 @@ export function getManufacturingProducts(blueprint: Blueprint) {
); );
} }
export function getInventionMaterials(blueprint: Blueprint) { export function getInventionMaterials(blueprint: Blueprint):
| any[]
| Promise<
{
type: Type;
quantity: number;
}[]
> {
const invention = blueprint.activities[ActivityType.INVENTION]; const invention = blueprint.activities[ActivityType.INVENTION];
if (!invention) return []; if (!invention) return [];
@@ -80,7 +101,14 @@ export function getInventionMaterials(blueprint: Blueprint) {
); );
} }
export function getInventionProducts(blueprint: Blueprint) { export function getInventionProducts(blueprint: Blueprint):
| any[]
| Promise<
{
type: Type;
quantity: number;
}[]
> {
const invention = blueprint.activities[ActivityType.INVENTION]; const invention = blueprint.activities[ActivityType.INVENTION];
if (!invention) return []; if (!invention) return [];
@@ -92,7 +120,14 @@ export function getInventionProducts(blueprint: Blueprint) {
); );
} }
export function getInventionSkills(blueprint: Blueprint) { export function getInventionSkills(blueprint: Blueprint):
| any[]
| Promise<
{
type: Type;
level: number;
}[]
> {
const invention = blueprint.activities[ActivityType.INVENTION]; const invention = blueprint.activities[ActivityType.INVENTION];
if (!invention) return []; if (!invention) return [];

View File

@@ -27,7 +27,7 @@ export interface Category {
readonly icon_id?: number; readonly icon_id?: number;
} }
export function getCategory(category_id: number) { export function getCategory(category_id: number): Category {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.categories[String(category_id)]; const data = dataSets.categories[String(category_id)];
if (!data) throw new Error(`Category ID ${category_id} not found in reference data`); if (!data) throw new Error(`Category ID ${category_id} not found in reference data`);

View File

@@ -1,4 +1,4 @@
import { getAttribute } from './attribute'; import { getAttribute, type Attribute } from './attribute';
import type { LocalizedString } from './shared-types'; import type { LocalizedString } from './shared-types';
import { dataSets, loadModels } from './loadModels'; import { dataSets, loadModels } from './loadModels';
@@ -37,29 +37,29 @@ export interface Effect {
readonly name: string; readonly name: string;
} }
export function getEffect(effect_id: number) { export function getEffect(effect_id: number): Effect {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.dogma_effects[String(effect_id)]; const data = dataSets.dogma_effects[String(effect_id)];
if (!data) throw new Error(`Effect ID ${effect_id} not found in reference data`); if (!data) throw new Error(`Effect ID ${effect_id} not found in reference data`);
return data; return data;
} }
export function getDischargeAttribute(effect: Effect) { export function getDischargeAttribute(effect: Effect): Attribute {
return effect.discharge_attribute_id && getAttribute(effect.discharge_attribute_id); return effect.discharge_attribute_id && getAttribute(effect.discharge_attribute_id);
} }
export function getFalloffAttribute(effect: Effect) { export function getFalloffAttribute(effect: Effect): Attribute {
return effect.falloff_attribute_id && getAttribute(effect.falloff_attribute_id); return effect.falloff_attribute_id && getAttribute(effect.falloff_attribute_id);
} }
export function getDurationAttribute(effect: Effect) { export function getDurationAttribute(effect: Effect): Attribute {
return effect.duration_attribute_id && getAttribute(effect.duration_attribute_id); return effect.duration_attribute_id && getAttribute(effect.duration_attribute_id);
} }
export function getRangeAttribute(effect: Effect) { export function getRangeAttribute(effect: Effect): Attribute {
return effect.range_attribute_id && getAttribute(effect.range_attribute_id); return effect.range_attribute_id && getAttribute(effect.range_attribute_id);
} }
export function getTrackingSpeedAttribute(effect: Effect) { export function getTrackingSpeedAttribute(effect: Effect): Attribute {
return effect.tracking_speed_attribute_id && getAttribute(effect.tracking_speed_attribute_id); return effect.tracking_speed_attribute_id && getAttribute(effect.tracking_speed_attribute_id);
} }

View File

@@ -13,7 +13,7 @@ export interface Group {
readonly use_base_price: boolean; readonly use_base_price: boolean;
readonly type_ids?: number[]; readonly type_ids?: number[];
} }
export function getGroup(group_id: number) { export function getGroup(group_id: number): Group {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.groups[String(group_id)]; const data = dataSets.groups[String(group_id)];
if (!data) throw new Error(`Group ID ${group_id} not found in reference data`); if (!data) throw new Error(`Group ID ${group_id} not found in reference data`);

View File

@@ -14,7 +14,7 @@ export interface Icon {
readonly file: string; readonly file: string;
} }
export function getIcon(icon_id: number) { export function getIcon(icon_id: number): Icon {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.icons[String(icon_id)]; const data = dataSets.icons[String(icon_id)];
if (!data) throw new Error(`Icon ID ${icon_id} not found in reference data`); if (!data) throw new Error(`Icon ID ${icon_id} not found in reference data`);
@@ -33,9 +33,5 @@ export function getIconUrl(
isBpc?: boolean; isBpc?: boolean;
} = {}, } = {},
): string { ): string {
return `https://images.evetech.net/types/${icon_id}/icon${ return `https://images.evetech.net/types/${icon_id}/icon${isBp ? '/bp' : isBpc ? '/bpc' : ''}?size=${size}`;
isBp ? '/bp'
: isBpc ? '/bpc'
: ''
}?size=${size}`;
} }

View File

@@ -32,7 +32,7 @@ const dataSets = {
types: {} as Record<string, Type>, types: {} as Record<string, Type>,
units: {} as Record<string, Unit>, units: {} as Record<string, Unit>,
}; };
export async function loadModels() { export async function loadModels(): Promise<void> {
dataSets.dogma_attributes = JSON.parse(fs.readFileSync(join(__dirname, '../data/reference-data/dogma_attributes.json')).toString()); dataSets.dogma_attributes = JSON.parse(fs.readFileSync(join(__dirname, '../data/reference-data/dogma_attributes.json')).toString());
dataSets.blueprints = JSON.parse(fs.readFileSync(join(__dirname, '../data/reference-data/blueprints.json')).toString()); dataSets.blueprints = JSON.parse(fs.readFileSync(join(__dirname, '../data/reference-data/blueprints.json')).toString());
dataSets.categories = JSON.parse(fs.readFileSync(join(__dirname, '../data/reference-data/categories.json')).toString()); dataSets.categories = JSON.parse(fs.readFileSync(join(__dirname, '../data/reference-data/categories.json')).toString());

View File

@@ -11,7 +11,7 @@ export interface MarketGroup {
readonly has_types: boolean; readonly has_types: boolean;
} }
export function getMarketGroup(market_group_id: number) { export function getMarketGroup(market_group_id: number): MarketGroup {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.market_groups[String(market_group_id)]; const data = dataSets.market_groups[String(market_group_id)];
if (!data) throw new Error(`Market group ID ${market_group_id} not found in reference data`); if (!data) throw new Error(`Market group ID ${market_group_id} not found in reference data`);

View File

@@ -9,7 +9,7 @@ export interface MetaGroup {
readonly icon_suffix?: string; readonly icon_suffix?: string;
} }
export function getMetaGroup(meta_group_id: number) { export function getMetaGroup(meta_group_id: number): MetaGroup {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.meta_groups[String(meta_group_id)]; const data = dataSets.meta_groups[String(meta_group_id)];
if (!data) throw new Error(`Meta group ID ${meta_group_id} not found in reference data`); if (!data) throw new Error(`Meta group ID ${meta_group_id} not found in reference data`);

View File

@@ -16,7 +16,7 @@ export interface Region {
readonly name: LocalizedString; readonly name: LocalizedString;
} }
export function getRegion(region_id: number) { export function getRegion(region_id: number): Region {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.regions[String(region_id)]; const data = dataSets.regions[String(region_id)];
if (!data) throw new Error(`Region ID ${region_id} not found in reference data`); if (!data) throw new Error(`Region ID ${region_id} not found in reference data`);

View File

@@ -1,5 +1,5 @@
import type { LocalizedString, TypeIDQuantity } from './shared-types'; import type { LocalizedString, TypeIDQuantity } from './shared-types';
import { getType } from './type'; import { getType, type Type } from './type';
import { dataSets, loadModels } from './loadModels'; import { dataSets, loadModels } from './loadModels';
export interface Schematic { export interface Schematic {
@@ -11,27 +11,33 @@ export interface Schematic {
readonly pin_type_ids: number[]; readonly pin_type_ids: number[];
} }
export function getSchematic(schematic_id: number) { export function getSchematic(schematic_id: number): Schematic {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.schematics[String(schematic_id)]; const data = dataSets.schematics[String(schematic_id)];
if (!data) throw new Error(`Schematic ID ${schematic_id} not found in reference data`); if (!data) throw new Error(`Schematic ID ${schematic_id} not found in reference data`);
return data; return data;
} }
export function getMaterialQuantities(schematic: Schematic) { export function getMaterialQuantities(schematic: Schematic): {
type: Type;
quantity: number;
}[] {
return Object.entries(schematic.materials).map(([type_id, { quantity }]) => ({ return Object.entries(schematic.materials).map(([type_id, { quantity }]) => ({
type: getType(Number(type_id)), type: getType(Number(type_id)),
quantity, quantity,
})); }));
} }
export function getProductQuantities(schematic: Schematic) { export function getProductQuantities(schematic: Schematic): {
type: Type;
quantity: number;
}[] {
return Object.entries(schematic.products).map(([type_id, { quantity }]) => ({ return Object.entries(schematic.products).map(([type_id, { quantity }]) => ({
type: getType(Number(type_id)), type: getType(Number(type_id)),
quantity, quantity,
})); }));
} }
export function getPinTypes(schematic: Schematic) { export function getPinTypes(schematic: Schematic): Type[] {
return schematic.pin_type_ids.map(getType); return schematic.pin_type_ids.map(getType);
} }

View File

@@ -11,26 +11,26 @@ export interface Skill {
readonly required_skills?: { [skill_type_id: string]: number }; // skill_type_id : level readonly required_skills?: { [skill_type_id: string]: number }; // skill_type_id : level
} }
export function getSkill(type_id: number) { export function getSkill(type_id: number): Skill {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.skills[String(type_id)]; const data = dataSets.skills[String(type_id)];
if (!data) throw new Error(`Skill ID ${type_id} not found in reference data`); if (!data) throw new Error(`Skill ID ${type_id} not found in reference data`);
return data; return data;
} }
export function getPrimaryDogmaAttribute(skill: Skill) { export function getPrimaryDogmaAttribute(skill: Skill): Attribute {
return getAttribute(skill.primary_dogma_attribute_id); return getAttribute(skill.primary_dogma_attribute_id);
} }
export function getSecondaryDogmaAttribute(skill: Skill) { export function getSecondaryDogmaAttribute(skill: Skill): Attribute {
return getAttribute(skill.secondary_dogma_attribute_id); return getAttribute(skill.secondary_dogma_attribute_id);
} }
export function getPrimaryCharacterAttribute(skill: Skill) { export function getPrimaryCharacterAttribute(skill: Skill): Attribute {
return getAttribute(skill.primary_character_attribute_id); return getAttribute(skill.primary_character_attribute_id);
} }
export function getSecondaryCharacterAttribute(skill: Skill) { export function getSecondaryCharacterAttribute(skill: Skill): Attribute {
return getAttribute(skill.secondary_character_attribute_id); return getAttribute(skill.secondary_character_attribute_id);
} }

View File

@@ -1,9 +1,16 @@
import type { AttributeIDValue, BlueprintTypeIDActivity, EffectIDDefault, LocalizedString, MaterialIDQuantity } from './shared-types'; import type {
ActivityType,
AttributeIDValue,
BlueprintTypeIDActivity,
EffectIDDefault,
LocalizedString,
MaterialIDQuantity,
} from './shared-types';
import { IconSize } from './icon'; import { IconSize } from './icon';
import { getUnit, type Unit } from './unit'; import { getUnit, type Unit } from './unit';
import { CommonAttribute, getAttribute } from './attribute'; import { CommonAttribute, getAttribute, type Attribute } from './attribute';
import { getGroup } from './group'; import { getGroup, type Group } from './group';
import { getMetaGroup } from './meta-group'; import { getMetaGroup, type MetaGroup } from './meta-group';
import { dataSets, loadModels } from './loadModels'; import { dataSets, loadModels } from './loadModels';
interface Masteries { interface Masteries {
@@ -67,7 +74,7 @@ export interface Type {
readonly is_blueprint?: boolean; readonly is_blueprint?: boolean;
} }
export function getType(type_id: number) { export function getType(type_id: number): Type {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const data = dataSets.types[String(type_id)]; const data = dataSets.types[String(type_id)];
if (!data) throw new Error(`Type ID ${type_id} not found in reference data`); if (!data) throw new Error(`Type ID ${type_id} not found in reference data`);
@@ -114,7 +121,12 @@ export function getSkillBonuses(type: Type): {
return skillBonuses; return skillBonuses;
} }
export function getRoleBonuses(type: Type) { export function getRoleBonuses(type: Type): {
bonus: number;
bonus_text: LocalizedString;
importance: number;
unit: Unit;
}[] {
if (!type.traits || !type.traits.role_bonuses) return []; if (!type.traits || !type.traits.role_bonuses) return [];
return Object.values(type.traits.role_bonuses).map((bonus) => ({ return Object.values(type.traits.role_bonuses).map((bonus) => ({
bonus: bonus.bonus, bonus: bonus.bonus,
@@ -136,7 +148,7 @@ export function eveTycoonLink(type_id: number) {
return `https://evetycoon.com/market/${type_id}`; return `https://evetycoon.com/market/${type_id}`;
} }
export function getTypeAttributes(type: Type) { export function getTypeAttributes(type: Type): any[] {
if (!type.dogma_attributes) return []; if (!type.dogma_attributes) return [];
Object.keys(type.dogma_attributes).map((attribute_id) => ({ Object.keys(type.dogma_attributes).map((attribute_id) => ({
attribute: getAttribute(Number(attribute_id)), attribute: getAttribute(Number(attribute_id)),
@@ -144,7 +156,7 @@ export function getTypeAttributes(type: Type) {
})); }));
} }
export function typeHasAnyAttribute(type: Type, attribute_ids: CommonAttribute[]) { export function typeHasAnyAttribute(type: Type, attribute_ids: CommonAttribute[]): boolean {
if (!type.dogma_attributes) return false; if (!type.dogma_attributes) return false;
for (const attribute_id of attribute_ids) { for (const attribute_id of attribute_ids) {
if (type.dogma_attributes[attribute_id]) return true; if (type.dogma_attributes[attribute_id]) return true;
@@ -152,7 +164,10 @@ export function typeHasAnyAttribute(type: Type, attribute_ids: CommonAttribute[]
return false; return false;
} }
export function getTypeSkills(type: Type) { export function getTypeSkills(type: Type): {
skill: Type;
level: number;
}[] {
if (!type.required_skills) return []; if (!type.required_skills) return [];
return Object.keys(type.required_skills).map((skill_type_id) => ({ return Object.keys(type.required_skills).map((skill_type_id) => ({
skill: getType(Number(skill_type_id)), skill: getType(Number(skill_type_id)),
@@ -160,7 +175,13 @@ export function getTypeSkills(type: Type) {
})); }));
} }
export function typeGetAttribute(type: Type, attribute_id: number) { export function typeGetAttribute(
type: Type,
attribute_id: number,
): {
attribute: Attribute;
value: number;
} {
if (!type.dogma_attributes || !type.dogma_attributes[attribute_id]) return null; if (!type.dogma_attributes || !type.dogma_attributes[attribute_id]) return null;
return { return {
attribute: getAttribute(attribute_id), attribute: getAttribute(attribute_id),
@@ -168,7 +189,10 @@ export function typeGetAttribute(type: Type, attribute_id: number) {
}; };
} }
export function getTypeBlueprints(type: Type) { export function getTypeBlueprints(type: Type): {
blueprint: Type;
activity: ActivityType;
}[] {
if (!type.produced_by_blueprints) return []; if (!type.produced_by_blueprints) return [];
return Object.values(type.produced_by_blueprints).map((blueprint) => ({ return Object.values(type.produced_by_blueprints).map((blueprint) => ({
blueprint: getType(blueprint.blueprint_type_id), blueprint: getType(blueprint.blueprint_type_id),
@@ -176,22 +200,25 @@ export function getTypeBlueprints(type: Type) {
})); }));
} }
export function getTypeSchematics(type: Type) { export function getTypeSchematics(type: Type): Type[] {
return type.produced_by_schematic_ids?.map((schematic_id) => getType(schematic_id)) ?? []; return type.produced_by_schematic_ids?.map((schematic_id) => getType(schematic_id)) ?? [];
} }
export function getTypeGroup(type: Type) { export function getTypeGroup(type: Type): Group {
if (!type.group_id) return null; if (!type.group_id) return null;
return getGroup(type.group_id); return getGroup(type.group_id);
} }
export function getTypeVariants(type: Type) { export function getTypeVariants(type: Type): {
metaGroup: MetaGroup;
types: Type[];
}[] {
return Object.entries(type.type_variations || {}).map(([meta_group_id, variant_ids]) => ({ return Object.entries(type.type_variations || {}).map(([meta_group_id, variant_ids]) => ({
metaGroup: getMetaGroup(Number(meta_group_id)), metaGroup: getMetaGroup(Number(meta_group_id)),
types: variant_ids.map((type_id) => getType(type_id)), types: variant_ids.map((type_id) => getType(type_id)),
})); }));
} }
export function typeHasAttributes(type: Type) { export function typeHasAttributes(type: Type): boolean {
return type.dogma_attributes && Object.keys(type.dogma_attributes).length > 0; return type.dogma_attributes && Object.keys(type.dogma_attributes).length > 0;
} }

View File

@@ -18,7 +18,7 @@ export interface Unit {
readonly name: LocalizedString; readonly name: LocalizedString;
} }
export function getUnit(unit_id: number) { export function getUnit(unit_id: number): Unit {
if (!dataSets.loaded) loadModels(); if (!dataSets.loaded) loadModels();
const unit = dataSets.units[String(unit_id)]; const unit = dataSets.units[String(unit_id)];
if (!unit) throw new Error(`Unit ID ${unit_id} not found in reference data`); if (!unit) throw new Error(`Unit ID ${unit_id} not found in reference data`);
@@ -61,6 +61,6 @@ export function renderUnit(unit: Unit, value: number, locale: string = 'en'): st
} }
} }
export function isUnitInversePercentage(unit: Unit) { export function isUnitInversePercentage(unit: Unit): boolean {
return unit.unit_id == 108 || unit.unit_id == 111; return unit.unit_id == 108 || unit.unit_id == 111;
} }

View File

@@ -1,4 +1,4 @@
import { createLogger, format, transports } from 'winston'; import { createLogger, format, Logger, transports } from 'winston';
const development = 'development'; const development = 'development';
const production = 'production'; const production = 'production';
@@ -6,7 +6,7 @@ const NODE_ENV = process.env.NODE_ENV || development;
const LOG_LEVEL = process.env.LOG_LEVEL || NODE_ENV === development ? 'debug' : 'info'; const LOG_LEVEL = process.env.LOG_LEVEL || NODE_ENV === development ? 'debug' : 'info';
const DEBUG = LOG_LEVEL === 'debug'; const DEBUG = LOG_LEVEL === 'debug';
export function init(name: string = 'App') { export function init(name: string = 'App'): Logger {
const jsonFormat = format.combine(format.timestamp(), format.json()); const jsonFormat = format.combine(format.timestamp(), format.json());
const logger = createLogger({ const logger = createLogger({
level: LOG_LEVEL, level: LOG_LEVEL,

View File

@@ -0,0 +1,10 @@
export function isPromise<T>(value: T | Promise<T>): value is Promise<T> {
return typeof (value as Promise<T>)?.then === 'function';
}
export async function awaitMaybePromise<T>(value: T | Promise<T>) {
if (isPromise(value)) {
return await value;
}
return Promise.resolve(value);
}

View File

@@ -0,0 +1,99 @@
import { Database } from 'bun:sqlite';
export function dynamicInsert<T extends {} = any>(db: Database, table: string, item: T) {
const keys = Object.keys(item);
const values = keys.map((k) => item[k]);
const stmt = db.prepare(`INSERT INTO ${table} (${keys.join(', ')}) VALUES (${keys.map((k) => '?').join(', ')})`);
return stmt.run(...values).lastInsertRowid;
}
export function dynamicUpdate<T extends {} = any>(db: Database, table: string, item: T, key: string, keyValue: any) {
const keys = Object.keys(item);
const values = keys.map((k) => item[k]);
const stmt = db.prepare(`UPDATE ${table} SET ${keys.map((k) => `${k} = ?`).join(', ')} WHERE ${key} = ?`);
return stmt.run(...values, keyValue).changes;
}
export interface QueryOptions<T extends {}> {
skip?: number;
limit?: number;
orderBy?: Partial<Record<keyof T, 'ASC' | 'DESC'>>;
}
type Where<T> = Partial<Record<keyof T, any>> & { or?: Partial<Record<keyof T, any>> };
export function select<T extends {}>(db: Database, table: string, options?: QueryOptions<T>, select: string = '*', where?: Where<T>): T[] {
let query = `SELECT ${select} FROM ${table}\n`;
const values = [];
if (where) {
query += `WHERE `;
if (where.or) {
query += `${Object.keys(where.or)
.map((k) => {
values.push(where.or[k]);
return `${k} = ?\n`;
})
.join('OR ')}`;
delete where.or;
}
if (Object.keys(where).length > 0) {
query += `${Object.keys(where)
.map((k) => {
values.push(where[k]);
return `${k} = ?\n`;
})
.join('AND ')}`;
}
}
if (options?.orderBy) {
query += `ORDER BY\n${Object.keys(options.orderBy)
.map((k) => {
values.push(options.orderBy[k]);
return `${k} ?`;
})
.join(',\n')}\n`;
}
if (options?.skip) {
values.push(options.limit || -1);
values.push(options.skip);
query += `LIMIT ? OFFSET ?`;
}
return db.prepare(query).all(...values) as T[];
}
export function remove<T>(db: Database, table: string, where?: Where<T>) {
let query = `DELETE FROM ${table}`;
const values = [];
if (where) {
query += `WHERE `;
if (where.or) {
query += `${Object.keys(where.or)
.map((k) => {
values.push(where.or[k]);
return `${k} = ?\n`;
})
.join('OR ')}`;
delete where.or;
}
if (Object.keys(where).length > 0) {
query += `${Object.keys(where)
.map((k) => {
values.push(where[k]);
return `${k} = ?\n`;
})
.join('AND ')}`;
}
}
return db.prepare(query).run(...values).changes;
}

View File

@@ -19,7 +19,7 @@
"noEmitOnError": false, "noEmitOnError": false,
"declaration": true, "declaration": true,
"outDir": "dist/types", "outDir": "dist/types",
"rootDir": "src", "rootDir": ".",
"allowImportingTsExtensions": true "allowImportingTsExtensions": true
}, },
"include": ["src", "types", "src/jsx/types.d.ts", "scripts"], "include": ["src", "types", "src/jsx/types.d.ts", "scripts"],

View File

@@ -19,7 +19,8 @@ export default defineConfig([
platform: 'node', platform: 'node',
dts: true, dts: true,
minify: false, minify: false,
mangle: false, sourcemap: true,
unbundle: true,
external: ['bun:sqlite', 'bun'], external: ['bun:sqlite', 'bun'],
}, },
]); ]);

View File

@@ -12,20 +12,20 @@ DOTENV_PUBLIC_KEY_DEVELOPMENT="02572da3d4f3a844588a944214c0e142a5a01deaa6551456a
DOTENV_PUBLIC_KEY="02292a330aa041b5f7efc51504e0c208accba67a6877a217ab43cbb59c3c0c3e66" DOTENV_PUBLIC_KEY="02292a330aa041b5f7efc51504e0c208accba67a6877a217ab43cbb59c3c0c3e66"
# .env # .env
DEBUG="encrypted:BH4VZPx8vYDz9+wOLYTG3iyzwjd0CPrQKsa13qqZlL56VuP+fn3inwc4CgIGR9+GZ3yChV/RYGAnH2aTyda70ndm//c4YN1xe51YquEgmLHHxAHFAf8+deqetbADQc/OyOp8QRs=" DEBUG="true"
PORT="encrypted:BInhSdlEztIkFKZQXKdNIrr+JtotI3WkdZ8COeGB8+Ihhe+8QiVfeUjqX+AGPg5EW88xE8afebum/OUpt/NGVQBqRmxc8DzRi02ShKtF/JqEKczSipOFZLXctZm/OWp5PTlrvSY=" PORT="3001"
NODE_ENV="encrypted:BMoifBpI9mSASWO1Mj6UcLwc3HR9Y/GNV4Ac/iJzoWgED/qkm+5XLdwIho+FTWXdqOTmpMn77JUjmlPctVEQz2qFQXeBV6n4va/3sZ5NDQq6WIFaaxU4Ru0Ab4JsopYnqHs+txP17iqH18rK" NODE_ENV="development"
LOG_LEVEL="encrypted:BBeNG+hfeuUeBqu9XPdywtmh14W6Ng3jjob1uXPtQDlpTyykFmTsjQRyN49qB32hP/Dxl9LlDBFBYoDvsRR70ykXv9qjxvtwgcwPTxfKAD4F1fIkg324NKBFKI+uOppRsCQYJ7HG" LOG_LEVEL="debug"
BASE_URL="encrypted:BFDXxzQnyyy/d6N9e5GPP3K0a3N3wvLYVeR5G0AYz9eqi+5Ubb6DfoNIrNqLHXoOYRSJPBgDgvHwU8M3Xdv7bNckQjrkhkKQTuz5CPMK3rp0TkHb5ccaWCKc8f65CQ65z7dchdFKm/oTlzshPObtGkWQnV9ZSB0VJXx4" BASE_URL="http://dev.starkitten.cafe"
EVE_CLIENT_ID="encrypted:BCRo2KZwwBpXcURQFnUn6coiprzBjXW1OakelETLS6aQZaO9awf4GCWZ8djDanBcaEfAnRBfNp2Jlr6IhA4MaGwDEbF/ehaI1rT2bQHD3ALFezyXcQnG+S9GgHCwrRNXa32Vw4OQjxAvEAYJP0hQa3CMkxpdN1sg6N2Q66e/H+Bo" EVE_CLIENT_ID="4cfee6b0c8fc40b29e0415f6309bd756"
EVE_CLIENT_SECRET="encrypted:BJcXRi1NzC2BMYh+nsGy5AyudGvaG1pxDXuCXLRIbAYRT9rQWG64Ev4eHY0Hee7eAKR85YsH8xEY2vXcTGST0FVwCrwNkOT3pxF6vSwjQgkJAB0QAyONjdjrmxJYPIx6n1+AR2dRGQ/NDTwHltDbX3l+rta71Glb+Cpy5iuzHMXJQCbifVn4tVI=" EVE_CLIENT_SECRET="1Y5SBrdRMNuy9YWfwGMHsvUmTejqcQqDj4muuhOj"
EVE_CALLBACK_URL="encrypted:BOoYseMLToFnaG000LxCWO6V4Nlrv3S+ubuBsqtskBeUoO36odLvmRzLGgTJ69AQW5CaK1WzO8Agwiy88KcgcpbHqklfuCuWuuL8dVa5sQt573IKkIMHgyt8TtYVIZkbh5KM/eMgGru9aLEF5FlhPMv/s2yLHufHN+RLnuVzP0PVk9FWLUcavWKuqSwC" EVE_CALLBACK_URL="http://dev.starkitten.cafe/api/auth/callback"
ESI_USER_AGENT="encrypted:BCXSJs69AMhQPwVejRA7sD7YAvIphM+aoOqpDphOk08aSxeuYpynYcEwZlvuwQZhFIL0rI5DhRIhkK4299VT7tmMV5Yopx6LbMiVJ+moCK1EIoguUqIj+Yadq5Kwp8bSPa/GGNdFwoOirI9oJp6zmBndzTzGLwGPCbSRUsa0dxjp+53FFNWLIUcdjlO1Pe5/GLWcUkXIZd8M2lLQ/a5mD+ewbGPl6MroSGq2zGgWMGSNqpFilg==" ESI_USER_AGENT="Star Kitten DEV/0.0.1 (star-kitten-dev@f302.me; +https://git.f302.me/jb/star-kitten)"
DISCORD_APP_ID="encrypted:BL21AyCTN6+iGCSyHk34+izYNBFCtGgkvjjDtdsD955WKobm7RcFRUrvLieZXeePC7g2gm6m9A5FjNwlX6j/SuNejnZPuX4Rn+zfOp831dX0mtKiaac0CMTbIpOKIOVYMgIugHH1GJGja+plw45w+eYH+zg=" DISCORD_APP_ID="1292871047942504572"
DISCORD_APP_SECRET="encrypted:BLcXsfZaFtEpzPeyKR2xXOYhnFpEpVRI4m/xBpFcjcDBUiKpcSi0QwQXjXBlUfwT35C/5TpaBa8WtQxGh/0n49DaGOhjhVlbAKaWnoqeGVvYgpZKBWo/BXnaLOncF5wy2/GgBwmbxNA0VxLtl2cJCAzlUW1nvF/xAh6B7gxUdNQq" DISCORD_APP_SECRET="Ioji-sKdo2hoCJe8A82M_c6AwRcuDphE"
DISCORD_PUBLIC_KEY="encrypted:BHd+GM5GIZ65jRuniQU2nFA3qYTStzADiEO0EQFMLvVsRsg+PmrJr7udgdSHMFRr6zXMdiD2MyZi55xZN6qTz/ShrWhtvyV8zTuKNH0/CUxiEFaaBdQQIpYNvmAUrEON7Dt/ajm+rFeo5HFydTiOqoE2OUEf7VLjmt4jBb3Na+3EZ0PFdHhNM5Hen8vyZisjVs4AFzV5H0OgtLZYu4xcy18=" DISCORD_PUBLIC_KEY="9ac29ee2d8170cb720caab3a382221aff577f82d7bfa03cd0dd737832053246c"
DISCORD_BOT_TOKEN="encrypted:BP7NGOn1JhkSjK0j9bGx7ywNsLzRiZBtKg8EIHF0AzjDh9JGt3tJOZX2vYaen824sWFJGDPOyWUae1jknVx6URl26g3pXRISetowtOFhtOH4yC/lS9qJ7f4MTYr29smKB9klDv+Z7JtKcjLju1u4sFYizC0pCl+fOFFX4616l0RQaYVHqCalWLPrr2jiipwGzGPg+Rctd5maA4GlHNUmQCcB5/rIrlxmtg==" DISCORD_BOT_TOKEN="MTI5Mjg3MTA0Nzk0MjUwNDU3Mg.Gx8VvN.hrJMd94CZl0dHFhFS40lmB_ynNfJTC56QATHBg"
DISCORD_TEST_GUILD_ID="encrypted:BGVm9myDnJYQm1zGvEJAaRyY9hnEVGU2fNWd2EmHm3CspMjc26e1sBwp+Cz/2QDxnQxARNQBXModvAK913NdAYcb9HWO57Xg7yC6a6M4p8p73P5foJfs7l78YMyjgO+Fh/HrHwcGeBM+V6cmVaY8nI/Mvw==" DISCORD_TEST_GUILD_ID="424296600773459998"
JANICE_KEY="encrypted:BOizj0f3hpQrP6elDX1Mo0wnOaNQRWhFDFnTJSxVCPbjkv4O/mmTx9+PwSJA/2Shrq3/+ea/PvMP76YkRpPv6EitlfZl3A6d4YhEdHGvD1nhH8dIvDOwoeCLXvlVnsb6S/O7NM+RnJVvH6xmyjP5bJVHFuLgm9+YBCWNnb+AWu9v" JANICE_KEY="DUyi5Q3Dod48IoswUBkEfNRs8Qf3cwNN"
PERPLEXITY_API_KEY="encrypted:BB1oGMElNVwXvcrkPUbHLOg4wf43Kobdyo+BptnfuRuQJUQYvUYQ+ALLWshk/hvJNTbQcOA0czr+lLnwgZwQlephTsDz9tea5qS/0NqVOq/jeFn2O7P4e9vzVrD2XP7avhzVSVyVDnORHrAuCXLKOiM87DxLMj7xaYv745xateDKVOG3+MwJVWgj31coS0q5y0ICw2RB" PERPLEXITY_API_KEY="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"
STAR_KITTEN_KV_DB_PATH="encrypted:BIg9Hiq4Oc/InaGyQD92V1ghIzoY2TDYyvFlyyom8luHvsCwtwCYCLkM0T564HZ9BUjgG9x+NPZ1htw5x1aGkV4frBLA4q/afhx/Ad2Z20SUPudF8c2K9ICaW+HvJZUuFQzRfz6f9w0u+R7RCRio" STAR_KITTEN_KV_DB_PATH="data/dev-kv.db"

View File

@@ -5,19 +5,19 @@
DOTENV_PUBLIC_KEY_PRODUCTION="02f0469506f6722d8fcc179c199ff159ca32f082000c8e7a1465891adb50a4c031" DOTENV_PUBLIC_KEY_PRODUCTION="02f0469506f6722d8fcc179c199ff159ca32f082000c8e7a1465891adb50a4c031"
# .env.production # .env.production
DEBUG="encrypted:BLRJy/AWcYEX8ZS6P4+igHMZ4TZpKibq84Zb9wS7lW1GGC8g31hn0z5+AqMvl4mVKbmlvd1dOESSES85TjcxdlTWDB0R0lx25cLX/ueX3ZCvjuHOeZOkdFeRnWvHsB587Q6tYxac" DEBUG="false"
PORT="encrypted:BDBqBCPqHTNjJKOZyuPnmWn+DY1DPSUN7mZRZu/vHhlafoa0Niuy4sjC6DAg25uc0DojvNyytxlAv/F5ko7vuWrQm27dliuYxQxk8gsNybtibCsOdS+2PXtppUgzcF4qPl538oo=" PORT="3000"
NODE_ENV="encrypted:BCCLAZZJrDcWeG71xVyu29GG+Af1ytHgBc4/R8QT6au+rtxM1vM32gW3Whbap5+Bt+GVAR86QonADSZmeVfYCZ+sjqdOBokg9Vbk8ivs8hHNX2V4v9XwAvF1BwchTalUTSdtnfCv3qthg8Y=" NODE_ENV="production"
LOG_LEVEL="encrypted:BPvgXocX/WBBbK+CaYrfMZnnnU2o2NCrAtNy5sQNBETp9h8MGisyHG5RYIPWGHDiIAZOH3V95ulf6/2edUngHYtU9lEZcDoBHxNpW0a80KoZ+iYUif4eRUTRbG4HWi3Jwhs7eTo=" LOG_LEVEL="info"
BASE_URL="encrypted:BF3lujdQPVb6Q/s/oZT0xrziMdE0hPqSy3McLNDOCQb+cWx9mqZDuYpVBLxs2T19zGdP6yjNX8jLjEYPYmh9OyYGRItLRK3gMgVYZQTEjf+B1SNtOeF4QN5Ct0cpipdVD81iTPdQUyCQ0mvYHJhtpWFWUbmyDkTD" BASE_URL="https://starkitten.cafe"
DISCORD_APP_ID="encrypted:BExz43HXZ9g0m/QLu0iuI/qSt3OaGYVw2g0f5nZel1ys0mpqAuci2cS8fCcVzfwMJn/6p1RYsmB3A7fflNy7YeiBX8Ma/cHdOF3Zyoj2yNoqqehNC2KTK0C9tbnSY6E9bhuVQJTMb35OzAMj7WcREwbZM/U=" DISCORD_APP_ID="1288711114388930601"
DISCORD_APP_SECRET="encrypted:BIv5jEjpZ9J4BKKJ22edzaNoud4PqJ5gc4QY57aObxPZS+9lb+SGvfCDjUIQ8nQSJveKbHXuZLtIg3xzvPA9zhRZmSzWQuZDmcqSrgUIS0t/lxz1gMmlT3pE2puWdvM8EWPTLBCR/n5B//rCCyNuVhQ7kWhyw1f9f1H+o1NkLhYx" DISCORD_APP_SECRET="HYK03ffTN3Cl7c0p4jqo2wl0y_AD4EQ-"
DISCORD_PUBLIC_KEY="encrypted:BN+q3uWIyoKRi0gBnbzUPuoam/8q1t2Q7/YtaWkQzf1pauzp/WvjpLnHCBuVoCZ8a0MBSb/LInXLB9QtkerfBw1ssp1DHV2zwY6ll+AfqXK86N54dpWFPB/M0sGodNh6f5eldSn+Xxlhbni9iXYTvS91hv5WzoD9v9NNx17rMrTl7Gp4dpRVdcx+AakIa4GjLSfve/rNQW6zLngpE1LaDF4=" DISCORD_PUBLIC_KEY="447bb2c27ad4127eba078b74f84c058205787df36b90e63de8b19e045fb9307f"
DISCORD_BOT_TOKEN="encrypted:BHXawD07KwH77vcFbVnrIJ3Fkl+RuZnKIkRo7RttPAUSVlXOdCECujXLudAcKMH5WiiexdGIj0K0xabtR0z/fGPTyaF0knggrPQBYHkc8MSQVVY504xpnseV/8rer/yk5KTVlOP9Aa6fwXs68pKvJwhl6Rg8jAffxxEtCfVbJ5uDLIgOyCYGn8UkGph3hc9cMFNQ3zMTHe0zJmDMpotByvqSSP4zG95qPA==" DISCORD_BOT_TOKEN="MTI4ODcxMTExNDM4ODkzMDYwMQ.GqwYGA.EzZZP7heEHTkH7jrxFTp7FhIlnXT06AUhYLKHE"
EVE_CLIENT_ID="encrypted:BGz8McWi5toM40GAa8fJmTEi2L+r8rvkB5A88GCryIRt71f/C9bmaOZXPMu8lhn+JqlwmH7UJ/mabQkBuyKPl5ION11veeQRERjw3murhX1wHJM0P/C9dQiDGMP//yqUWv3UbRG5DVZYkz1N8wngqfajQQ9rbglA4SuZYyjUhGNO" EVE_CLIENT_ID="3e12fdcfe611408d9cb499b0795b9fac"
EVE_CLIENT_SECRET="encrypted:BNW8BEjqWVBHQa07rlJdjExy8ANCvc+tCEXeLMDleTpQOLnAZCuiv1ONMm8ytz7toD3bZkqWcSzoqSJTr8uSl+Nfle72nbxpofYbbBh/wGJkKScmiAXTLz+UJB6a7Wck8eX8TTKEgxo9JDOElz5qR7AgSoy9kU1CJyzsOkFfqgQV+uD8z2+8lvs=" EVE_CLIENT_SECRET="b7ex0i8ZOLFWEaRThSFVCXk5KV7Z16NEbhneCXRk"
EVE_CALLBACK_URL="encrypted:BEigQd6FfoyqzO9QJfyFkYFDJ1QnAIXIMj1/ScKP5BqE20l7eaitRAbdXnUtRAFtRxgA1HU6kmBfMzYm9XQLbM/Umm9yStyaKR2AC7Bkyw5xJ7IfTJP3hhrGbWroQtxse4GOddOF4SE99QpPt7f13ABRvycJOBDjKSQH7yUxFChjAHtHq33iNLgn" EVE_CALLBACK_URL="https://starkitten.cafe/api/auth/callback"
ESI_USER_AGENT="encrypted:BEvfNDuhTzHfJlNokl1gh7wMVGoGxfVvCjFnMJupDBwG0GPFlnJmMBKPR7uii9+ML2aerxLNPPlR+OvVRtQy9pbTDsKE4G+1oyjQ72DNDk37HybPNR7ATQtqdz35HxOJeia38N3XgylC3sH16VnVtY9mD5DuKoMKh3XIX843FnbrEsQGJL0pIEWGbHC5wkkGtaxfs1cBu3fDDjbIt6/2Ggx7zzlDmtzujZRxaq7ksWvvMdT2pXLRvrA=" ESI_USER_AGENT="Concierge Freight/0.0.1 (concierge-freight@f302.me; +https://git.f302.me/jb/star-kitten)"
AUTH_DB_PATH="encrypted:BBNfPkks5tw/h0obJDuDSCPoCbFZFOZUX3Br7GKytMVkeltG7xOqiuT6RBMYffzNnfdlJKqseWP5EG7shoBB20spTPRHnmHFAfNi6SBEB93oP5s9TtpTMGAGD5+BMV2aBOv0mHwGcyfY49haXly+T8fKW5A0k8C5" AUTH_DB_PATH="/var/lib/litefs/auth.db"
JANICE_KEY="encrypted:BBhnf2qamAD7CdVDEGFtJkBKbg9m/U/KMqBE0Ws01HLF+ZF58xTRhREiPgeOPE0E8ZJslxgYJ8BxdAhXCfCuKk/T4qE56rZNTFidSOXdycfI/T3TxaZc1/B5PFrcyUDXwCgmySx8vSZ5V8slqdjIHZSI+rSt6cFrLW/R37cY+RIu" JANICE_KEY="DUyi5Q3Dod48IoswUBkEfNRs8Qf3cwNN"
PERPLEXITY_API_KEY="encrypted:BDImj/MShxH3jECidjrfU1VbRytCICiNz6uOhouZSB5K4QhPC/UlSl83XWqOSLEsl5wyX0dk+ca10Low0HBPJMALLZuao195oiEjReyXp6RC4L5gqK/JCeJiTiJOqhZ0ERYsBlbJB9b/hyq6MZULh0cd5am8vYzWprqdJ8op/poDWPtAGeOSU5P3/niPQ/tKa3f+Pnz5" PERPLEXITY_API_KEY="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"

View File

@@ -5,6 +5,7 @@
"author": "j-b-3", "author": "j-b-3",
"type": "module", "type": "module",
"module": "src/main.ts", "module": "src/main.ts",
"private": true,
"devDependencies": { "devDependencies": {
"@dotenvx/dotenvx": "^1.49.0", "@dotenvx/dotenvx": "^1.49.0",
"@types/bun": "^1.2.21", "@types/bun": "^1.2.21",
@@ -15,7 +16,7 @@
}, },
"dependencies": { "dependencies": {
"@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev", "@projectdysnomia/dysnomia": "github:projectdysnomia/dysnomia#dev",
"@star-kitten/lib": "workspace:^0.0.0" "@star-kitten/lib": "workspace:*"
}, },
"scripts": { "scripts": {
"dev": "bunx dotenvx run -f .env.development -- bun --watch src/main.ts", "dev": "bunx dotenvx run -f .env.development -- bun --watch src/main.ts",
@@ -24,10 +25,6 @@
"lint": "prettier --check .", "lint": "prettier --check .",
"format": "prettier --write .", "format": "prettier --write .",
"test": "bun test", "test": "bun test",
"get-data": "bun refresh:reference-data && bun refresh:hoboleaks && bun static-export",
"refresh:reference-data": "bun ../util/dist/download-and-extract.js https://data.everef.net/reference-data/reference-data-latest.tar.xz ./data/reference-data",
"refresh:hoboleaks": "bun ../util/dist/download-and-extract.js https://data.everef.net/hoboleaks-sde/hoboleaks-sde-latest.tar.xz ./data/hoboleaks",
"static-export": "bun ../eve/scripts/export-solar-systems.ts",
"encrypt": "bunx dotenvx encrypt -f .env.development && bunx dotenvx encrypt -f .env.production", "encrypt": "bunx dotenvx encrypt -f .env.development && bunx dotenvx encrypt -f .env.production",
"decrypt": "bunx dotenvx decrypt -f .env.development && bunx dotenvx decrypt -f .env.production" "decrypt": "bunx dotenvx decrypt -f .env.development && bunx dotenvx decrypt -f .env.production"
} }

View File

@@ -5,7 +5,6 @@
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"moduleDetection": "force", "moduleDetection": "force",
"allowJs": true,
// Bundler mode // Bundler mode
"moduleResolution": "bundler", "moduleResolution": "bundler",