do all of this stuff, i guess.

Add credits, Hiveswap things, change authentication security, and ads.
This commit is contained in:
MeowcaTheoRange 2023-09-05 00:21:26 -05:00
parent 9a8f6874f7
commit fd06319e07
51 changed files with 2795 additions and 543 deletions

520
package-lock.json generated
View file

@ -12,6 +12,7 @@
"@types/cookie-parser": "^1.4.3",
"@types/crypto-js": "^4.1.1",
"@types/react": "^18.2.14",
"argon2": "^0.31.1",
"body-parser": "^1.20.2",
"cookie": "^0.5.0",
"cookie-parser": "^1.4.6",
@ -51,6 +52,53 @@
"node": ">=6.9.0"
}
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
"dependencies": {
"detect-libc": "^2.0.0",
"https-proxy-agent": "^5.0.0",
"make-dir": "^3.1.0",
"node-fetch": "^2.6.7",
"nopt": "^5.0.0",
"npmlog": "^5.0.1",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"tar": "^6.1.11"
},
"bin": {
"node-pre-gyp": "bin/node-pre-gyp"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"dependencies": {
"abbrev": "1"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@next/env": {
"version": "13.4.7",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.7.tgz",
@ -226,6 +274,14 @@
"node": ">= 8"
}
},
"node_modules/@phc/format": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz",
"integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==",
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz",
@ -373,8 +429,7 @@
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"node_modules/accepts": {
"version": "1.3.8",
@ -388,11 +443,42 @@
"node": ">= 0.6"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dependencies": {
"debug": "4"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/agent-base/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/agent-base/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -425,6 +511,37 @@
"node": ">= 8"
}
},
"node_modules/aproba": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
},
"node_modules/are-we-there-yet": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/argon2": {
"version": "0.31.1",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.31.1.tgz",
"integrity": "sha512-ik2xnJrLXazya7m4Nz1XfBSRjXj8Koq8qF9PsQC8059p20ifWc9zx/hgU3ItZh/3TnwXkv0RbhvjodPkmFf0bg==",
"hasInstallScript": true,
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.11",
"@phc/format": "^1.0.0",
"node-addon-api": "^7.0.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@ -442,8 +559,7 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/binary-extensions": {
"version": "2.2.0",
@ -494,7 +610,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -625,6 +740,14 @@
"fsevents": "~2.3.2"
}
},
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"engines": {
"node": ">=10"
}
},
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
@ -662,6 +785,14 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
"bin": {
"color-support": "bin.js"
}
},
"node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
@ -674,8 +805,7 @@
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/concurrently": {
"version": "8.2.0",
@ -704,6 +834,11 @@
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
}
},
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@ -819,6 +954,11 @@
"ms": "^2.1.1"
}
},
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@ -836,6 +976,14 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/detect-libc": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
"engines": {
"node": ">=8"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -867,8 +1015,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
@ -1074,6 +1221,33 @@
"node": ">= 0.6"
}
},
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/fs-minipass/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@ -1093,6 +1267,25 @@
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"node_modules/gauge": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
"dependencies": {
"aproba": "^1.0.3 || ^2.0.0",
"color-support": "^1.1.2",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.1",
"object-assign": "^4.1.1",
"signal-exit": "^3.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wide-align": "^1.1.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@ -1116,6 +1309,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@ -1200,6 +1412,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@ -1215,6 +1432,39 @@
"node": ">= 0.8"
}
},
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dependencies": {
"agent-base": "6",
"debug": "4"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/https-proxy-agent/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/https-proxy-agent/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@ -1241,6 +1491,15 @@
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@ -1284,7 +1543,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -1342,6 +1600,39 @@
"loose-envify": "cli.js"
}
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dependencies": {
"semver": "^6.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -1425,7 +1716,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@ -1441,6 +1731,48 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minipass": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"dependencies": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/minizlib/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"bin": {
"mkdirp": "bin/cmd.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mongodb": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.6.0.tgz",
@ -1575,6 +1907,49 @@
}
}
},
"node_modules/node-addon-api": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz",
"integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA=="
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/nodemon": {
"version": "2.0.22",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
@ -1648,6 +2023,25 @@
"node": ">=0.10.0"
}
},
"node_modules/npmlog": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
"dependencies": {
"are-we-there-yet": "^2.0.0",
"console-control-strings": "^1.1.0",
"gauge": "^3.0.0",
"set-blocking": "^2.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
@ -1667,6 +2061,14 @@
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@ -1675,6 +2077,14 @@
"node": ">= 0.8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
@ -1854,6 +2264,19 @@
"react": "^18.2.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@ -1891,6 +2314,20 @@
"node": ">=0.10.0"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@ -2026,6 +2463,11 @@
"node": ">= 0.8.0"
}
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@ -2053,6 +2495,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/simple-update-notifier": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz",
@ -2144,11 +2591,18 @@
"node": ">=10.0.0"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -2162,7 +2616,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -2215,6 +2668,22 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/tar": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
"integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
"dependencies": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^5.0.0",
"minizlib": "^2.1.1",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/tiny-case": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
@ -2362,6 +2831,11 @@
"node": ">= 0.8"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@ -2410,6 +2884,14 @@
"node": ">=12"
}
},
"node_modules/wide-align": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"dependencies": {
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@ -2427,6 +2909,11 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@ -2436,6 +2923,11 @@
"node": ">=10"
}
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",

View file

@ -26,6 +26,7 @@
"@types/cookie-parser": "^1.4.3",
"@types/crypto-js": "^4.1.1",
"@types/react": "^18.2.14",
"argon2": "^0.31.1",
"body-parser": "^1.20.2",
"cookie": "^0.5.0",
"cookie-parser": "^1.4.6",

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -9,6 +9,7 @@
padding: 8px;
width: max-content;
max-width: 100%;
overflow: hidden;
}
.Box.secondary {
@ -21,11 +22,11 @@
}
.Box .innerContent {
padding: 4px 4px;
padding-top: 8px;
padding: 6px 4px;
display: inline-flex;
flex-direction: column;
gap: 8px;
max-width: 100%;
}
.Box .innerContentNoTitle {

View file

@ -47,15 +47,6 @@
transition: transform 0.25s cubic-bezier(0, 0.25, 0.5, 1);
}
.CelesteBox .TextHolder {
visibility: hidden;
}
.CelesteBox.open .TextHolder {
visibility: visible;
transition: visibility 0.25s step-end;
}
.PortraitHolder {
width: 128px;
height: 128px;
@ -74,3 +65,13 @@
line-height: 35px;
user-select: none;
}
.CelesteBox .TextHolder {
visibility: hidden;
display: none;
}
.CelesteBox.open .TextHolder {
visibility: visible;
display: flex;
}

View file

@ -14,44 +14,16 @@ export default function TextHandler({
wantTextboxDoneStuff: [boolean, (wantTextboxDone: boolean) => void];
}) {
const textSpan = useRef<HTMLSpanElement>(null);
const [content, setContent] = useState(Runner(dialogIndex.dialog));
const [content, setContent] = useState(Runner(dialogIndex.dialog, "start"));
const animationFrame = useRef(0);
let clickSound: AudioBuffer;
let inSound: AudioBuffer;
let outSound: AudioBuffer;
let context: AudioContext;
let gain: GainNode;
let contextGot = false;
async function getContext() {
context = new AudioContext();
gain = context.createGain();
gain.gain.value = 0.2;
gain.connect(context.destination);
await fetch("assets/celeste/click.wav")
.then(response => response.arrayBuffer())
.then(arrayBuffer => context.decodeAudioData(arrayBuffer))
.then((audioBuffer: AudioBuffer) => (clickSound = audioBuffer));
await fetch("assets/celeste/in.wav")
.then(response => response.arrayBuffer())
.then(arrayBuffer => context.decodeAudioData(arrayBuffer))
.then((audioBuffer: AudioBuffer) => (inSound = audioBuffer));
await fetch("assets/celeste/out.wav")
.then(response => response.arrayBuffer())
.then(arrayBuffer => context.decodeAudioData(arrayBuffer))
.then((audioBuffer: AudioBuffer) => (outSound = audioBuffer));
}
useEffect(generateContent, [dialogIndex, dialogIsOpen]);
function generateContent() {
console.log("generating");
if (!dialogIsOpen) return;
if (textSpan.current == null) return;
cancelAnimationFrame(animationFrame.current);
setContent(Runner(dialogIndex.dialog));
setContent(Runner(dialogIndex.dialog, "start"));
}
(async () => {
await getContext();
contextGot = true;
})();
useEffect(formatContent, [content]);
function formatContent() {
console.log("formatting", content);
@ -134,12 +106,6 @@ export default function TextHandler({
default:
waitLength = 0.025;
}
// if (makeSound && contextGot) {
// let source = context.createBufferSource();
// source.buffer = clickSound;
// source.connect(gain);
// source.start();
// }
await wait(waitLength).then(() => {
animationFrame.current = requestAnimationFrame(showLetters);
});
@ -158,12 +124,18 @@ export default function TextHandler({
);
}
function Runner(text: ElementArray) {
if (typeof text === "string") return StringRunner(text);
else if (Array.isArray(text)) return <span>{text.map(Runner)}</span>;
function Runner(text: ElementArray, index?: string) {
if (typeof text === "string") return StringRunner(text, index);
else if (Array.isArray(text))
return (
<span key={index}>
{text.map((x, i) => Runner(x, (index ?? "") + "_" + i))}
</span>
);
else if (typeof text === "object") {
return (
<span
key={index}
className={
text.effects?.className
? text.effects.className +
@ -173,19 +145,19 @@ function Runner(text: ElementArray) {
}
style={text.effects?.style ?? {}}
>
{Runner(text.text)}
{Runner(text.text, index)}
</span>
);
}
}
function StringRunner(string: string) {
function StringRunner(string: string, index?: string) {
return (
<>
{string.split("").map((letter, i) => (
<span
className={`letter ${styles.letter}`}
key={i + Math.random()}
key={(index ?? "") + "_" + i + Math.random()}
>
{letter}
</span>

View file

@ -1,61 +1,73 @@
.Nav {
background-color: var(--pri-bg);
color: var(--pri-fg);
background-color: var(--pri-bg);
color: var(--pri-fg);
position: sticky;
top: 8px;
left: 8px;
z-index: 9;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
text-align: center;
width: calc(100vw - 16px);
height: 48px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
padding: 8px 12px;
position: sticky;
top: 8px;
left: 8px;
z-index: 9;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
text-align: center;
width: calc(100vw - 16px);
height: 48px;
border: 1px solid currentColor;
border-radius: 2px;
box-sizing: border-box;
padding: 8px 12px;
}
.Nav .left {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
text-align: center;
width: 100%;
gap: 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
text-align: center;
width: 100%;
gap: 16px;
}
.Nav .right {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
text-align: center;
width: 100%;
gap: 16px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
text-align: center;
width: 100%;
gap: 16px;
}
.Nav .titlePath {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
text-align: left;
gap: 4px;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
text-align: left;
gap: 4px;
}
.Nav .path {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
gap: 6px;
max-width: 100px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
gap: 6px;
max-width: 100px;
}
.shortTitle {
display: none;
}
@media (max-width: 784px) {
.shortTitle {
display: initial;
}
.longTitle {
display: none;
}
}

View file

@ -1,45 +1,98 @@
import globals from "@/styles/global.module.css";
import { AnyObject } from "@/types/generics";
import AuthContext from "@/utility/react/AuthContext";
import Link from "next/link";
import { useContext, useEffect, useState } from "react";
import styles from "./Nav.module.css";
export default function Nav(elementProps: AnyObject) {
return (
<div className={styles.Nav} {...elementProps}>
<div className={styles.left}>
<div className={styles.titlePath}>
<span className={globals.title}>
<Link className={globals.link} href="/">
TrollCall
</Link>
</span>
const userCredentials = useContext(AuthContext);
// Prevent hydration error. Nav Auth section is a client-rendered element.
const [isClient, setIsClient] = useState(false);
useEffect(() => setIsClient(true), []);
return (
<div
className={styles.Nav}
{...elementProps}
>
<div className={styles.left}>
<div className={styles.titlePath}>
<span className={globals.title + " " + styles.longTitle}>
<Link
className={globals.link}
href="/"
>
TrollCall
</Link>
</span>
<span className={globals.title + " " + styles.shortTitle}>
<Link
className={globals.link}
href="/"
>
TC
</Link>
</span>
</div>
<span className={globals.icon}>
<Link
className={globals.link}
href="/add/troll/"
>
add
</Link>
</span>
<span className={globals.iconlike}>
<Link
className={globals.link}
href="/hiveswap/"
>
HS
</Link>
</span>
<span className={globals.icon}>
<Link
className={globals.link}
href="http://discord.trollcall.xyz/"
>
message
</Link>
</span>
</div>
<div className={styles.right}>
{isClient &&
userCredentials.TROLLCALL_NAME != null &&
userCredentials.TROLLCALL_NAME != "" ? (
<>
<span className={globals.icon}>
<Link
href={`/clan/${userCredentials.TROLLCALL_NAME}`}
className={globals.link}
>
group
</Link>
</span>
<span className={globals.icon}>
<Link
href={`/edit/clan/${userCredentials.TROLLCALL_NAME}`}
className={globals.link}
>
settings
</Link>
</span>
<span className={globals.icon}>
<Link
href={`/logout`}
className={globals.link}
>
logout
</Link>
</span>
</>
) : (
<></>
)}
</div>
</div>
<span className={globals.icon}>
<Link className={globals.link} href="/add/troll/">
add
</Link>
</span>
<span className={globals.iconlike}>
<Link className={globals.link} href="/hiveswap/">
HS
</Link>
</span>
<span className={globals.icon}>
<Link className={globals.link} href="http://discord.trollcall.xyz/">
groups
</Link>
</span>
</div>
<div className={styles.right}>
<span className={globals.text}>
Part of{" "}
<a className={globals.link} href="https://www.google.com/">
The Admin Clan
</a>
</span>
<span className={globals.icon}>settings</span>
<span className={globals.icon}>logout</span>
</div>
</div>
);
);
}

View file

@ -0,0 +1,23 @@
.Mothvertisement {
margin-left: auto;
display: block;
margin-right: auto;
max-width: 728px;
width: 100%;
height: 90px;
border: 1px solid var(--pri-fg);
border-radius: 2px;
opacity: 0.5;
transition: opacity 0.125s;
}
.Mothvertisement:hover {
opacity: 1;
}
@media (max-width: 750px) {
.Mothvertisement {
max-width: 300px;
width: 100%;
height: 250px;
}
}

View file

@ -0,0 +1,41 @@
import globals from "@/styles/global.module.css";
import Link from "next/link";
import { useEffect, useState } from "react";
import styles from "./Mothvertising.module.css";
export default function Mothvertising() {
const [hide, setHide] = useState(false);
useEffect(() => {
setHide(window.localStorage.getItem("hideAds") === "true");
}, []);
return !hide ? (
<div className={globals.boxLike}>
<iframe
src="https://mothvertising.moth.monster/embed"
className={styles.Mothvertisement}
key={Math.random()}
></iframe>
<div className={globals.horizontalListLeft}>
<button
onClick={() => {
window.localStorage.setItem("hideAds", "true");
setHide(true);
}}
className={globals.small + " " + globals.buttonLink}
>
Hide forever
</button>
<span className={globals.small}>-</span>
<Link
className={globals.small + " " + globals.link}
href={"https://mothvertising.moth.monster/"}
target="_blank"
>
Mothvertising
</Link>
</div>
</div>
) : (
<></>
);
}

View file

@ -0,0 +1,12 @@
.NavLink {
margin-left: auto;
display: block;
margin-right: auto;
border: 1px solid var(--pri-fg);
border-radius: 2px;
opacity: 0.5;
transition: opacity 0.125s;
}
.NavLink:hover {
opacity: 1;
}

View file

@ -0,0 +1,44 @@
import globals from "@/styles/global.module.css";
import Link from "next/link";
import { useEffect, useState } from "react";
import styles from "./NavLink.module.css";
export default function NavLink() {
const [hide, setHide] = useState(false);
useEffect(() => {
setHide(window.localStorage.getItem("hideAds") === "true");
}, []);
return !hide ? (
<div className={globals.boxLike}>
<iframe
src="https://dimden.neocities.org/navlink/"
key={Math.random()}
className={styles.NavLink}
name="neolink"
width="180"
height="180"
></iframe>
<div className={globals.horizontalListLeft}>
<button
onClick={() => {
window.localStorage.setItem("hideAds", "true");
setHide(true);
}}
className={globals.small + " " + globals.buttonLink}
>
Hide forever
</button>
<span className={globals.small}>-</span>
<Link
className={globals.small + " " + globals.link}
href={"https://dimden.dev/navlinkads/"}
target="_blank"
>
NavLink Ads
</Link>
</div>
</div>
) : (
<></>
);
}

View file

@ -1,6 +1,7 @@
.ClanCard {
min-width: 600px;
/* min-width: 600px; */
width: 100%;
align-items: stretch;
}
.ClanCard.Skeleton {
@ -9,9 +10,10 @@
}
.ClanCard .headerImage {
display: flex;
margin: 0 -8px;
margin-top: -8px;
width: auto;
width: calc(100% + 16px);
height: 100px;
background-color: var(--pri-fg);
border: none;
@ -25,7 +27,8 @@
.ClanCard .horizontal {
display: grid;
grid-template-columns: auto 1fr;
grid-template-columns: auto auto;
justify-content: center;
gap: 16px;
padding: 8px;
box-sizing: border-box;
@ -55,4 +58,12 @@
display: flex;
flex-direction: column;
gap: 4px;
overflow: hidden;
width: 100%;
}
.ClanCard .horizontal .horizontalRight > * {
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
}

View file

@ -4,11 +4,17 @@ import globals from "@/styles/global.module.css";
import { Color3 } from "@/types/assist/color";
import { ClientClan } from "@/types/clan";
import { PronounGrouper } from "@/utility/language";
import Conditional from "@/utility/react/Conditional";
import Conditional, { ConditionalParent } from "@/utility/react/Conditional";
import Link from "next/link";
import styles from "./ClanCard.module.css";
export default function ClanCard({ clan }: { clan: ClientClan }) {
export default function ClanCard({
clan,
link = true
}: {
clan: ClientClan;
link?: boolean;
}) {
return (
<Box
properties={{
@ -16,7 +22,7 @@ export default function ClanCard({ clan }: { clan: ClientClan }) {
theme: clan.color ? Color3.fromRGB(...clan.color) : undefined
}}
>
<Conditional condition={clan.bgimage != null}>
<Conditional condition={link && clan.bgimage != null}>
<div className={styles.headerImage}>
<img
src={clan.bgimage as string}
@ -36,13 +42,23 @@ export default function ClanCard({ clan }: { clan: ClientClan }) {
</div>
</Conditional>
<div className={styles.horizontalRight}>
<p className={globals.title}>
<Link
href={`/clan/${clan.name}`}
className={globals.link}
<p
className={globals.title}
title={clan.displayName ?? clan.name}
>
<ConditionalParent
condition={link}
parent={children => (
<Link
href={`/clan/${clan.name}`}
className={globals.link}
>
{children}
</Link>
)}
>
{clan.displayName ?? clan.name}
</Link>
</ConditionalParent>
</p>
<p className={globals.iconText}>
<span className={globals.iconSmall}>group</span>

View file

@ -7,36 +7,42 @@ import Link from "next/link";
import styles from "./SignCard.module.css";
export default function SignCard({ sign }: { sign: TrueSignType }) {
return (
<Box
properties={{
nfw: true,
class: styles.SignCard,
theme: Color3.fromRGB(...sign.color.color),
}}
>
<div className={styles.gridItem}>
<img
src={"/assets/signs/" + sign.color.name + "/" + sign.name + ".svg"}
className={styles.topImage}
alt=""
></img>
</div>
<div className={styles.gridItem + " " + styles.secondary}>
<p className={globals.title}>
<Link
href={`/hiveswap/truesign/${sign.name}`}
className={globals.link}
>
{sign.name}
</Link>
</p>
<p className={globals.horizontalList}>
<span className={globals.text}>{sign.sway.name}</span>
<span className={globals.text}>+</span>
<span className={globals.text}>{sign.aspect.name}</span>
</p>
</div>
</Box>
);
return (
<Box
properties={{
nfw: true,
class: styles.SignCard,
theme: new Color3(...sign.color.color)
}}
>
<div className={styles.gridItem}>
<img
src={
"/assets/signs/" +
sign.color.name +
"/" +
sign.name +
".svg"
}
className={styles.topImage}
alt=""
></img>
</div>
<div className={styles.gridItem + " " + styles.secondary}>
<p className={globals.title}>
<Link
href={`/hiveswap/truesigns/${sign.name}`}
className={globals.link}
>
{sign.name}
</Link>
</p>
<p className={globals.horizontalList}>
<span className={globals.text}>{sign.sway.name}</span>
<span className={globals.text}>+</span>
<span className={globals.text}>{sign.aspect.name}</span>
</p>
</div>
</Box>
);
}

View file

@ -1,5 +1,5 @@
.TrollCard {
min-width: 600px;
/* min-width: 600px; */
width: 100%;
}
@ -11,6 +11,7 @@
.TrollCard .top {
display: grid;
grid-template-columns: max-content auto;
justify-content: center;
gap: 8px;
}

View file

@ -17,11 +17,10 @@ export default function TrollCard({ troll }: { troll: ClientTroll }) {
const [randomLove, setRandomLove] = useState("");
const [randomHate, setRandomHate] = useState("");
const [randomQuote, setRandomQuote] = useState("");
const trollColor =
troll.pageColor ??
troll.textColor ??
const trollColor = (troll.pageColor?.map(x => x / 255) ??
troll.textColor?.map(x => x / 255) ??
troll.falseSign?.color.color ??
troll.trueSign?.color.color;
troll.trueSign?.color.color) as [number, number, number] | undefined;
useEffect(() => {
if (troll.preferences.love != null && troll.preferences.love.length > 0)
setRandomLove(pickRandom(troll.preferences.love));
@ -34,7 +33,7 @@ export default function TrollCard({ troll }: { troll: ClientTroll }) {
<Box
properties={{
class: styles.TrollCard,
theme: trollColor ? Color3.fromRGB(...trollColor) : undefined
theme: trollColor ? new Color3(...trollColor) : undefined
}}
>
<div className={styles.top}>
@ -48,7 +47,10 @@ export default function TrollCard({ troll }: { troll: ClientTroll }) {
</div>
</Conditional>
<div className={styles.gridItem + " " + styles.secondary}>
<p className={globals.title}>
<p
className={globals.title}
title={troll.name.join(" ")}
>
<Link
href={`/troll/${troll.owner?.name ?? ""}/${
troll.name[0]

View file

@ -17,6 +17,18 @@ if (process.env.MONGODB_DATABASE_NAME == null) {
process.exit();
}
export const client = new MongoClient(process.env.MONGODB_DATABASE, {});
let client;
if (process.env.NODE_ENV === "development") {
//@ts-ignore
if (!global._mongoClient) {
//@ts-ignore
global._mongoClient = new MongoClient(process.env.MONGODB_DATABASE, {});
}
//@ts-ignore
client = global._mongoClient;
} else {
client = new MongoClient(process.env.MONGODB_DATABASE, {});
}
export const mainDB = client.db(process.env.MONGODB_DATABASE_NAME);

View file

@ -16,7 +16,7 @@ export async function ClanGET(
? existingClan
: await getSingleClan(query);
if (clan == null) return null;
const serverClan = await ServerClanToClientClan(clan);
const serverClan = await ServerClanToClientClan({ ...clan });
serverClan.flairs = cutArray(
await getManyFlairs(
{ _id: { $in: clan.flairs } },

View file

@ -14,17 +14,19 @@ export async function TrollGET(
existingTroll?: ServerTroll
): Promise<ClientTroll | null> {
const clan =
existingOwner ??
(await getSingleClan({
name: query?.clan
}));
existingOwner != null || query == null
? existingOwner
: await getSingleClan({
name: query.clan
});
if (clan == null) return null;
const troll =
existingTroll ??
(await getSingleTroll({
"name.0": query?.troll,
"owner": clan._id
}));
existingTroll != null || query == null
? existingTroll
: await getSingleTroll({
"name.0": query.troll,
"owner": clan._id
});
if (troll == null) return null;
const serverTroll = await ServerTrollToClientTroll(troll);
serverTroll.flairs = cutArray(

View file

@ -1,7 +1,6 @@
import { Levels, Permissions } from "@/permissions";
import { ServerClan } from "@/types/clan";
import CryptoJS from "crypto-js";
import AES from "crypto-js/aes";
import { verify } from "argon2";
import { ObjectId } from "mongodb";
export function getLevel(clan: Partial<ServerClan> & { flairs: ObjectId[] }) {
@ -17,18 +16,15 @@ export function compareLevels(level: string, compareLevel: string) {
return Levels[level] > Levels[compareLevel];
}
export function compareCredentials(
export async function compareCredentials(
clan: ServerClan,
cookies: Partial<{
[key: string]: string;
}>
) {
const decryptCode = AES.decrypt(
clan.code,
process.env.ENCRYPT_CODE ?? "HACKTHIS"
).toString(CryptoJS.enc.Utf8);
if (cookies.TROLLCALL_CODE == null) return null;
return (
decryptCode === cookies.TROLLCALL_CODE &&
(await verify(clan.code, cookies.TROLLCALL_CODE)) &&
clan.name === cookies.TROLLCALL_NAME
);
}

View file

@ -1,13 +1,17 @@
import Box from "@/components/Box/Box";
import Nav from "@/components/Nav/Nav";
import Mothvertising from "@/components/ads/Mothvertising/Mothvertising";
import NavLink from "@/components/ads/NavLink/NavLink";
import "@/styles/_app.css";
import "@/styles/global.module.css";
import globals from "@/styles/global.module.css";
import { Color3 } from "@/types/assist/color";
import AuthContext from "@/utility/react/AuthContext";
import Themer, { ThemeModeContext } from "@/utility/react/Themer";
import { getCookies } from "cookies-next";
import type { AppProps } from "next/app";
import Link from "next/link";
import { useState } from "react";
import { useEffect, useState } from "react";
export default function App({ Component, pageProps }: AppProps) {
const [theme, setTheme] = useState([
@ -15,6 +19,14 @@ export default function App({ Component, pageProps }: AppProps) {
new Color3(0.7, 0.7, 0.6),
false
] as [Color3, Color3, boolean?]);
const cookies = getCookies() as {
TROLLCALL_NAME: string;
TROLLCALL_CODE: string;
};
const [adService, setAdService] = useState(false);
useEffect(() => {
setAdService(Math.random() > 0.5);
}, []);
return (
<main className={"App" + (theme[2] ? " " + "inverted" : "")}>
<Themer
@ -22,108 +34,130 @@ export default function App({ Component, pageProps }: AppProps) {
sec={theme[1]}
inverted={theme[2]}
/>
<Nav />
<ThemeModeContext.Provider value={theme[2]}>
<div className="mainContent">
<Component
{...pageProps}
themerVars={[theme, setTheme]}
/>
<Box
properties={{
title: {
text: "TrollCall.xyz"
},
theme: theme[1]
}}
>
<p className={globals.horizontalList}>
<Link
className={globals.link}
href="/help/opensource"
>
<span className={globals.text}>
Open-source licenses & credits
<AuthContext.Provider value={cookies}>
<Nav />
<ThemeModeContext.Provider value={theme[2]}>
<div className="mainContent">
<Component
{...pageProps}
themerVars={[theme, setTheme]}
/>
<Box
properties={{
title: {
text: "TrollCall.xyz"
},
theme: theme[1]
}}
>
{adService ? <Mothvertising /> : <NavLink />}
<p className={globals.horizontalList}>
<Link
className={globals.link}
href="/test"
>
<span className={globals.text}>
Testpage
</span>
</Link>
<span className={globals.text}>-</span>
<Link
className={globals.link}
href="/help/credits"
>
<span className={globals.text}>
Open-source licenses & credits
</span>
</Link>
<span className={globals.text}>-</span>
<Link
className={globals.link}
href="https://www.buymeacoffee.com/trollcall"
>
<span className={globals.text}>
Buy TrollCall a <b>sensible codebase</b>
</span>
</Link>
</p>
<p className={globals.text}>
TrollCall rev. 4 created by MeowcaTheoRange.
</p>
<p className={globals.text}>
<b>trollcall.xyz</b> domain owned by Redact.
</p>
<p className={globals.text}>
The TrollCall name is derived from the original
Hiveswap Troll Call. The name may be used in an
entity context or a project context.
</p>
<p className={globals.text}>
The textboxes found in the [INSERT PAGE HERE]
are inspired by those from the game{" "}
<b>Celeste</b>.
</p>
<p>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://github.com/MeowcaTheoRange/Fonts"
>
TrollCall Display
</Link>{" "}
font by MeowcaTheoRange.
</span>
</Link>
</p>
<p className={globals.text}>
TrollCall rev. 4 created by MeowcaTheoRange.
</p>
<p className={globals.text}>
<b>trollcall.xyz</b> domain owned by Redact.
</p>
<p className={globals.text}>
The TrollCall name is derived from the original
Hiveswap Troll Call. The name may be used in an
entity context or a project context.
</p>
<p className={globals.text}>
The textboxes found in the [INSERT PAGE HERE] are
inspired by those from the game <b>Celeste</b>.
</p>
<p>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://github.com/MeowcaTheoRange/Fonts"
>
TrollCall Display
</Link>{" "}
font by MeowcaTheoRange.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Space+Grotesk"
>
Space Grotesk
</Link>{" "}
font by Florian Karsten.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Space+Mono"
>
Space Mono
</Link>{" "}
font by Colophon Foundry.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Poppins"
>
Poppins
</Link>{" "}
font by Indian Type Foundry.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Flow+Circular"
>
Flow Circular
</Link>{" "}
font by Dan Ross.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://www.creativefabrica.com/product/renogare/"
>
Renogare
</Link>{" "}
font by Deepak Dogra.
</span>
</p>
<p className={globals.text}>
Homestuck and HIVESWAP © Homestuck Inc.
</p>
</Box>
</div>
</ThemeModeContext.Provider>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Space+Grotesk"
>
Space Grotesk
</Link>{" "}
font by Florian Karsten.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Space+Mono"
>
Space Mono
</Link>{" "}
font by Colophon Foundry.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Poppins"
>
Poppins
</Link>{" "}
font by Indian Type Foundry.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://fonts.google.com/specimen/Flow+Circular"
>
Flow Circular
</Link>{" "}
font by Dan Ross.
</span>
<span className={globals.blockText}>
<Link
className={globals.link}
href="https://www.creativefabrica.com/product/renogare/"
>
Renogare
</Link>{" "}
font by Deepak Dogra.
</span>
</p>
<p className={globals.text}>
Homestuck and HIVESWAP © Homestuck Inc.
</p>
</Box>
</div>
</ThemeModeContext.Provider>
</AuthContext.Provider>
</main>
);
}

View file

@ -10,8 +10,8 @@ import {
getLevel
} from "@/lib/trollcall/perms";
import { PartialClanSchema, SubmitClan } from "@/types/client/clan";
import { hash } from "argon2";
import { serialize } from "cookie";
import AES from "crypto-js/aes";
import { nanoid } from "nanoid";
import { NextApiRequest, NextApiResponse } from "next";
@ -21,9 +21,9 @@ export default async function handler(
) {
const { body, cookies, query, method } = req;
if (method === "GET") {
const clan = await ClanGET(query);
const clan = await ClanGET({ name: query.clan });
if (clan == null) return res.status(404).end();
res.json(await ClanGET(query));
res.json(clan);
} else if (method === "PUT") {
let validatedClan: Partial<SubmitClan>;
try {
@ -38,11 +38,14 @@ export default async function handler(
});
if (checkExistingClan == null) return res.status(404).end();
let isModerator = false;
if (!compareCredentials(checkExistingClan, cookies)) {
if (!(await compareCredentials(checkExistingClan, cookies))) {
const thisClan = await getSingleClan({
name: cookies.TROLLCALL_NAME
});
if (thisClan == null || !compareCredentials(thisClan, cookies))
if (
thisClan == null ||
!(await compareCredentials(thisClan, cookies))
)
return res.status(403).end();
if (!compareLevels(getLevel(thisClan), "MODERATOR"))
return res.status(403).end();
@ -53,10 +56,7 @@ export default async function handler(
serverClan.code = checkExistingClan.code || nanoid(16);
// Encrypt code lole
serverClan.code = AES.encrypt(
serverClan.code,
process.env.ENCRYPT_CODE ?? "HACKTHIS"
).toString();
serverClan.code = await hash(serverClan.code);
if (!compareLevels(getLevel(checkExistingClan), "SUPPORTER")) {
serverClan.bgimage = null;

View file

@ -3,8 +3,8 @@ import { SubmitClanToServerClan } from "@/lib/trollcall/convert/clan";
import { compareLevels, getLevel } from "@/lib/trollcall/perms";
import { ServerClan } from "@/types/clan";
import { SubmitClanSchema } from "@/types/client/clan";
import { hash } from "argon2";
import { serialize } from "cookie";
import AES from "crypto-js/aes";
import { nanoid } from "nanoid";
import { NextApiRequest, NextApiResponse } from "next";
@ -34,10 +34,7 @@ export default async function handler(
if (serverClan.code == null) serverClan.code = nanoid(16);
// Encrypt code lole
serverClan.code = AES.encrypt(
serverClan.code,
process.env.ENCRYPT_CODE ?? "HACKTHIS"
).toString();
serverClan.code = hash(serverClan.code).toString();
if (!compareLevels(getLevel(serverClan), "SUPPORTER"))
serverClan.bgimage = null;

View file

@ -18,6 +18,7 @@ export default async function handler(
thisTroll.owner = (await ClanGET({
_id: troll.owner
})) as ClientClan;
console.log(thisTroll.owner);
return thisTroll;
},

View file

@ -2,7 +2,6 @@ import { ClanGET } from "@/lib/trollcall/api/clan";
import { getSingleClan } from "@/lib/trollcall/clan";
import { ServerTrollToClientTroll } from "@/lib/trollcall/convert/troll";
import { getManyPagedTrolls } from "@/lib/trollcall/troll";
import { ClientClan } from "@/types/clan";
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
@ -16,15 +15,15 @@ export default async function handler(
name: query.clan
});
if (clan == null) return res.status(404).end();
const clientClan = await ClanGET(null, clan);
if (clientClan == null) return res.status(404).end();
const trolls = await getManyPagedTrolls(
{
"owner": clan._id
},
async (troll: any) => {
const thisTroll = await ServerTrollToClientTroll(troll);
thisTroll.owner = (await ClanGET({
_id: troll.owner
})) as ClientClan;
thisTroll.owner = clientClan;
return thisTroll;
},

View file

@ -35,11 +35,14 @@ export default async function handler(
name: query.clan
});
if (checkClan == null) return res.status(404).end();
if (!compareCredentials(checkClan, cookies)) {
if (!(await compareCredentials(checkClan, cookies))) {
const thisClan = await getSingleClan({
name: cookies.TROLLCALL_NAME
});
if (thisClan == null || !compareCredentials(thisClan, cookies))
if (
thisClan == null ||
!(await compareCredentials(thisClan, cookies))
)
return res.status(403).end();
console.log(getLevel(thisClan));
if (!compareLevels(getLevel(thisClan), "MODERATOR"))

View file

@ -17,11 +17,14 @@ export default async function handler(
name: query.clan
});
if (clan == null) return res.status(404).end();
if (!compareCredentials(clan, cookies)) {
if (!(await compareCredentials(clan, cookies))) {
const thisClan = await getSingleClan({
name: cookies.TROLLCALL_NAME
});
if (thisClan == null || !compareCredentials(thisClan, cookies))
if (
thisClan == null ||
!(await compareCredentials(thisClan, cookies))
)
return res.status(403).end();
if (!compareLevels(getLevel(thisClan), "MODERATOR"))
return res.status(403).end();

View file

@ -24,7 +24,7 @@ export default async function handler(
name: cookies.TROLLCALL_NAME
});
if (checkClan == null) return res.status(404).end();
if (!compareCredentials(checkClan, cookies))
if (!(await compareCredentials(checkClan, cookies)))
return res.status(403).end();
const checkExistingTroll = await getSingleTroll({
"name.0": validatedTroll.name[0],

View file

@ -0,0 +1,93 @@
import Box from "@/components/Box/Box";
import ClanCard from "@/components/cards/ClanCard/ClanCard";
import TrollCard from "@/components/cards/TrollCard/TrollCard";
import TrollSkeleton from "@/components/cards/TrollCard/TrollSkeleton";
import { ClanGET } from "@/lib/trollcall/api/clan";
import { Color3 } from "@/types/assist/color";
import { ClientClan } from "@/types/clan";
import { ThemerGetSet } from "@/types/generics";
import { ClientTroll } from "@/types/troll";
import Conditional from "@/utility/react/Conditional";
import { GetServerSideProps, GetStaticPropsContext } from "next";
import { useEffect, useState } from "react";
export default function Index({
themerVars: [theme, setTheme],
clan
}: {
themerVars: ThemerGetSet;
clan: ClientClan;
}) {
const [fetchedTrolls, setFetchedTrolls] = useState<ClientTroll[] | null>(
null
);
useEffect(() => {
async function getTroll() {
const res = await fetch("/api/troll/" + clan.name + "/...");
const json = await res.json();
setFetchedTrolls(json);
}
getTroll();
const color = clan.color?.map(x => x / 255) as [number, number, number];
if (color != null)
setTheme([new Color3(...color), new Color3(...color).darken(50)]);
}, []);
return (
<>
<Conditional condition={clan.bgimage != null}>
<style>{`
main.App {
background-image: linear-gradient(#0008, #0008), url(${clan.bgimage});
background-size: cover;
background-repeat: repeat;
background-position: 50% 50%;
}
${clan.css ?? ""}
`}</style>
</Conditional>
<ClanCard
clan={clan}
link={false}
/>
<Box
properties={{
title: {
text: "Clan Trolls",
small: true
}
}}
>
{fetchedTrolls == null ? (
<>
<TrollSkeleton />
<TrollSkeleton />
<TrollSkeleton />
</>
) : (
fetchedTrolls.map((troll: ClientTroll, idx) => (
<TrollCard
troll={troll}
key={idx + "troll"}
/>
))
)}
</Box>
</>
);
}
export const getServerSideProps: GetServerSideProps<{
clan: ClientClan;
}> = async (context: GetStaticPropsContext) => {
if (context.params?.clan == null) return { notFound: true };
const clan = await ClanGET({ name: context.params.clan });
if (clan == null)
return {
notFound: true
};
return {
props: {
clan
}
};
};

View file

@ -2,13 +2,16 @@ import Box from "@/components/Box/Box";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { ThemerGetSet } from "@/types/generics";
import { defaultTheme } from "@/utility/react/Themer";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme]
}: {
themerVars: ThemerGetSet;
}) {
useEffect(() => setTheme(defaultTheme), []);
return (
<>
<Box
@ -148,6 +151,15 @@ export default function Index({
@types/react
</Link>
</li>
<li className={globals.text}>
<Link
className={globals.link}
href="https://www.npmjs.com/package/argon2"
target="_blank"
>
argon2
</Link>
</li>
<li className={globals.text}>
<Link
className={globals.link}
@ -285,6 +297,69 @@ export default function Index({
</li>
</ul>
</Box>
<Box
properties={{
title: {
text: "Asset credits"
}
}}
>
<p className={globals.text}>
Extended Zodiac sign SVGs created by{" "}
<Link
className={globals.link}
href={
"https://www.deviantart.com/ylimegirl/art/Extended-Zodiac-Vectors-All-signs-721467417"
}
>
Ylimegirl on DeviantArt
</Link>
.
</p>
<p className={globals.text}>
Aspect symbol SVGs created by{" "}
<Link
className={globals.link}
href={
"https://meggies-effort.myshopify.com/products/aspect-symbols-homestuck"
}
>
Meggie's Effort
</Link>{" "}
(beware popups).
</p>
<hr className={globals.sep} />
<p className={globals.text}>
Mothvertisements served by{" "}
<Link
className={globals.link}
href={"https://mothvertising.moth.monster/"}
>
moth.monster
</Link>
</p>
<p className={globals.text}>
NavLink Ads served by{" "}
<Link
className={globals.link}
href={"https://dimden.dev/navlinkads/"}
>
dimden.dev
</Link>
</p>
<p className={globals.text}>
~&gt;{" "}
<button
onClick={() => {
window.localStorage.setItem("hideAds", "false");
window.location.reload();
}}
className={globals.buttonLink}
>
Give me back my ads!
</button>
</p>
</Box>
<Box
properties={{
title: {
@ -367,6 +442,23 @@ export default function Index({
Homestuck and HIVESWAP © Homestuck Inc.
</p>
</Box>
<Box properties={{ title: { text: "Contact Me" } }}>
<p className={globals.text}>
Please{" "}
<Link
className={globals.link}
href={"https://abtmtr.link/"}
>
let MeowcaTheoRange know
</Link>{" "}
if you have any questions about these credits!
</p>
</Box>
<Box properties={{ title: { text: "Helper Credits" } }}>
<p className={globals.text}>
A list of people who are on the TrollCall team.
</p>
</Box>
</>
);
}

View file

@ -0,0 +1,116 @@
import Box from "@/components/Box/Box";
import SignCard from "@/components/cards/SignCard/SignCard";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import {
Aspect,
AspectKeys,
AspectType,
AspectValues,
TrueSignValues
} from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme],
aspect
}: {
themerVars: ThemerGetSet;
aspect: AspectType;
}) {
useEffect(
() =>
setTheme([
new Color3(...aspect.color),
new Color3(...aspect.color).darken(50)
]),
[]
);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<Link
className={globals.link}
href="/hiveswap/aspects"
>
<span className={globals.text}>aspects</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>{aspect.name}</span>
</p>
</Box>
<Box
properties={{
title: {
text: aspect.name
},
theme: new Color3(...aspect.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/aspect/${aspect.name}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>{aspect.description}</span>
</p>
</Box>
<Box
properties={{
title: {
text: "True Signs"
},
theme: new Color3(...aspect.color).darken(70)
}}
>
<div className={globals.horizontalList}>
{TrueSignValues.filter(
x => x.aspect.name == aspect.name
).map((sign, tsidx) => (
<SignCard
sign={sign}
key={"ts" + aspect.name + tsidx}
/>
))}
</div>
</Box>
</>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: AspectValues.map(aspect => ({
params: {
name: aspect.name
}
})),
fallback: true
};
};
export const getStaticProps: GetStaticProps<{
aspect: AspectType;
}> = (context: GetStaticPropsContext) => {
if (context.params?.name == null) return { notFound: true };
const aspect = context.params.name as string;
if (!AspectKeys.includes(aspect)) return { notFound: true };
return {
props: { aspect: Aspect[aspect] }
};
};

View file

@ -0,0 +1,67 @@
import Box from "@/components/Box/Box";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import { AspectValues } from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { hiveswapTheme } from "@/utility/react/Themer";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme]
}: {
themerVars: ThemerGetSet;
}) {
useEffect(() => setTheme(hiveswapTheme), []);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>aspects</span>
</p>
</Box>
<Box
properties={{
title: {
text: "Aspects"
}
}}
>
<p className={globals.text}>Insert text here.</p>
</Box>
{AspectValues.map((aspect, idx) => (
<Box
key={idx}
properties={{
title: {
text: aspect.name,
link: `/hiveswap/aspects/${aspect.name}`
},
theme: new Color3(...aspect.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/aspect/${aspect.name}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>
{aspect.description}
</span>
</p>
</Box>
))}
</>
);
}

View file

@ -0,0 +1,115 @@
import Box from "@/components/Box/Box";
import SignCard from "@/components/cards/SignCard/SignCard";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import {
SignColor,
SignColorKeys,
SignColorType,
SignColorValues,
TrueSignValues
} from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme],
color
}: {
themerVars: ThemerGetSet;
color: SignColorType;
}) {
useEffect(
() =>
setTheme([
new Color3(...color.color),
new Color3(...color.color).darken(50)
]),
[]
);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<Link
className={globals.link}
href="/hiveswap/aspects"
>
<span className={globals.text}>aspects</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>{color.name}</span>
</p>
</Box>
<Box
properties={{
title: {
text: color.name + ` (${color.sign})`
},
theme: new Color3(...color.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/signs/${color.name}/${color.sign}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>{color.description}</span>
</p>
</Box>
<Box
properties={{
title: {
text: "True Signs"
}
}}
>
<div className={globals.horizontalList}>
{TrueSignValues.filter(x => x.color.name == color.name).map(
(sign, tsidx) => (
<SignCard
sign={sign}
key={"ts" + color.name + tsidx}
/>
)
)}
</div>
</Box>
</>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: SignColorValues.map(color => ({
params: {
name: color.name
}
})),
fallback: true
};
};
export const getStaticProps: GetStaticProps<{
color: SignColorType;
}> = (context: GetStaticPropsContext) => {
if (context.params?.name == null) return { notFound: true };
const color = context.params.name as string;
if (!SignColorKeys.includes(color)) return { notFound: true };
return {
props: { color: SignColor[color] }
};
};

View file

@ -0,0 +1,67 @@
import Box from "@/components/Box/Box";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import { SignColorValues } from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { hiveswapTheme } from "@/utility/react/Themer";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme]
}: {
themerVars: ThemerGetSet;
}) {
useEffect(() => setTheme(hiveswapTheme), []);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>sway</span>
</p>
</Box>
<Box
properties={{
title: {
text: "Sign Colors"
}
}}
>
<p className={globals.text}>Insert text here.</p>
</Box>
{SignColorValues.map((color, idx) => (
<Box
key={idx}
properties={{
title: {
text: color.name + ` (${color.sign})`,
link: `/hiveswap/colors/${color.name}`
},
theme: new Color3(...color.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/signs/${color.name}/${color.sign}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>
{color.description}
</span>
</p>
</Box>
))}
</>
);
}

View file

@ -0,0 +1,95 @@
import Box from "@/components/Box/Box";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { ThemerGetSet } from "@/types/generics";
import { hiveswapTheme } from "@/utility/react/Themer";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme]
}: {
themerVars: ThemerGetSet;
}) {
// Make universal theme
useEffect(() => setTheme(hiveswapTheme), []);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<span className={globals.text}>hiveswap</span>
</p>
</Box>
<Box
properties={{
title: {
text: "Hiveswap"
}
}}
>
<p className={globals.text}>
Welcome to the Hiveswap portion of TrollCall. Here we pay
homage to the original{" "}
<Link
className={globals.link}
href="http://hs.hiveswap.com/ezodiac/"
>
Extended Zodiac
</Link>{" "}
website by providing its services, but this time, in a kind
of cool modern statically generated way.
</p>
<p className={globals.text}>Also, original writing.</p>
<hr className={globals.sep} />
<p className={globals.title}>Aspects</p>
<p>Insert text here.</p>
<div className={globals.buttonLeft}>
<Link
className={globals.linkButton}
href="/hiveswap/aspects"
>
Go to Aspects page
</Link>
<hr className={globals.sep} />
</div>
<hr className={globals.invisep} />
<p className={globals.title}>Sway</p>
<p>Insert text here.</p>
<div className={globals.buttonLeft}>
<Link
className={globals.linkButton}
href="/hiveswap/sway"
>
Go to Sway page
</Link>
<hr className={globals.sep} />
</div>
<hr className={globals.invisep} />
<p className={globals.title}>Sign Colors</p>
<p>Insert text here.</p>
<div className={globals.buttonLeft}>
<Link
className={globals.linkButton}
href="/hiveswap/colors"
>
Go to Sign Colors page
</Link>
<hr className={globals.sep} />
</div>
<hr className={globals.invisep} />
<p className={globals.title}>True Signs</p>
<p>Insert text here.</p>
<div className={globals.buttonLeft}>
<Link
className={globals.linkButton}
href="/hiveswap/truesigns"
>
Go to True Signs page
</Link>
<hr className={globals.sep} />
</div>
</Box>
</>
);
}

View file

@ -0,0 +1,126 @@
import Box from "@/components/Box/Box";
import SignCard from "@/components/cards/SignCard/SignCard";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import {
SignColorValues,
Sway,
SwayKeys,
SwayType,
SwayValues,
TrueSignValues
} from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme],
sway
}: {
themerVars: ThemerGetSet;
sway: SwayType;
}) {
useEffect(
() =>
setTheme([
new Color3(...sway.color),
new Color3(...sway.color).darken(50)
]),
[]
);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<Link
className={globals.link}
href="/hiveswap/aspects"
>
<span className={globals.text}>aspects</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>{sway.name}</span>
</p>
</Box>
<Box
properties={{
title: {
text: sway.name
},
theme: new Color3(...sway.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/sway/${sway.name}.png`}
width="64"
height="64"
></img>
<span className={globals.text}>{sway.description}</span>
</p>
</Box>
<Box
properties={{
title: {
text: "True Signs"
},
theme: new Color3(...sway.color).darken(70)
}}
>
<hr className={globals.invisepHeader} />
{SignColorValues.map((color, idx) => (
<>
<p className={globals.titleSmall}>{color.name}</p>
<hr className={globals.sepHeader} />
<div className={globals.horizontalList}>
{TrueSignValues.filter(
x =>
x.sway.name == sway.name &&
x.color.name == color.name
).map((sign, tsidx) => (
<SignCard
sign={sign}
key={"ts" + sway.name + tsidx}
/>
))}
</div>
</>
))}
</Box>
</>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: SwayValues.map(sway => ({
params: {
name: sway.name
}
})),
fallback: true
};
};
export const getStaticProps: GetStaticProps<{
sway: SwayType;
}> = (context: GetStaticPropsContext) => {
if (context.params?.name == null) return { notFound: true };
const sway = context.params.name as string;
if (!SwayKeys.includes(sway)) return { notFound: true };
return {
props: { sway: Sway[sway] }
};
};

View file

@ -0,0 +1,65 @@
import Box from "@/components/Box/Box";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import { SwayValues } from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { hiveswapTheme } from "@/utility/react/Themer";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme]
}: {
themerVars: ThemerGetSet;
}) {
useEffect(() => setTheme(hiveswapTheme), []);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>sway</span>
</p>
</Box>
<Box
properties={{
title: {
text: "Sway"
}
}}
>
<p className={globals.text}>Insert text here.</p>
</Box>
{SwayValues.map((sway, idx) => (
<Box
key={idx}
properties={{
title: {
text: sway.name,
link: `/hiveswap/sway/${sway.name}`
},
theme: new Color3(...sway.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/sway/${sway.name}.png`}
width="64"
height="64"
></img>
<span className={globals.text}>{sway.description}</span>
</p>
</Box>
))}
</>
);
}

View file

@ -0,0 +1,163 @@
import Box from "@/components/Box/Box";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import {
TrueSign,
TrueSignKeys,
TrueSignType,
TrueSignValues
} from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from "next";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme],
trueSign
}: {
themerVars: ThemerGetSet;
trueSign: TrueSignType;
}) {
useEffect(
() =>
setTheme([
new Color3(...trueSign.color.color),
new Color3(...trueSign.color.color).darken(50)
]),
[]
);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<Link
className={globals.link}
href="/hiveswap/truesigns"
>
<span className={globals.text}>truesigns</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>{trueSign.name}</span>
</p>
</Box>
<Box
properties={{
title: {
text: trueSign.name
},
theme: new Color3(...trueSign.color.color)
}}
>
<p className={globals.iconTextTop}>
<img
className={globals.signage}
src={`/assets/signs/${trueSign.color.name}/${trueSign.name}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>
The True Sign of {trueSign.name} represents the{" "}
{trueSign.color.name}-blooded in the world, those who
are {trueSign.aspect.name}-bound and occupy the{" "}
{trueSign.sway.name} dream realm.
</span>
</p>
</Box>
<Box
properties={{
title: {
text: trueSign.color.name + ` (${trueSign.color.sign})`,
link: "/hiveswap/colors/" + trueSign.color.name
},
theme: new Color3(...trueSign.color.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/signs/${trueSign.color.name}/${trueSign.color.sign}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>
{trueSign.color.description}
</span>
</p>
</Box>
<Box
properties={{
title: {
text: trueSign.aspect.name + "-bound",
link: "/hiveswap/aspects/" + trueSign.aspect.name
},
theme: new Color3(...trueSign.aspect.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/aspect/${trueSign.aspect.name}.svg`}
width="64"
height="64"
></img>
<span className={globals.text}>
{trueSign.aspect.description}
</span>
</p>
</Box>
<Box
properties={{
title: {
text: trueSign.sway.name + "",
link: "/hiveswap/sway/" + trueSign.sway.name
},
theme: new Color3(...trueSign.sway.color)
}}
>
<p className={globals.iconText}>
<img
className={globals.signage}
src={`/assets/sway/${trueSign.sway.name}.png`}
width="64"
height="64"
></img>
<span className={globals.text}>
{trueSign.sway.description}
</span>
</p>
</Box>
</>
);
}
export const getStaticPaths: GetStaticPaths = () => {
return {
paths: TrueSignValues.map(trueSign => ({
params: {
name: trueSign.name
}
})),
fallback: true
};
};
export const getStaticProps: GetStaticProps<{
trueSign: TrueSignType;
}> = (context: GetStaticPropsContext) => {
if (context.params?.name == null) return { notFound: true };
const trueSign = context.params.name as string;
if (!TrueSignKeys.includes(trueSign)) return { notFound: true };
return {
props: { trueSign: TrueSign[trueSign] }
};
};

View file

@ -0,0 +1,72 @@
import Box from "@/components/Box/Box";
import SignCard from "@/components/cards/SignCard/SignCard";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import {
SignColorValues,
TrueSignValues
} from "@/types/assist/extended_zodiac";
import { ThemerGetSet } from "@/types/generics";
import { hiveswapTheme } from "@/utility/react/Themer";
import Link from "next/link";
import { useEffect } from "react";
export default function Index({
themerVars: [theme, setTheme]
}: {
themerVars: ThemerGetSet;
}) {
useEffect(() => setTheme(hiveswapTheme), []);
return (
<>
<Box properties={{}}>
<p className={globals.iconText}>
<span className={globals.icon}>arrow_back</span>
<Link
className={globals.link}
href="/hiveswap/"
>
<span className={globals.text}>hiveswap</span>
</Link>
<span className={globals.text}>/</span>
<span className={globals.text}>truesigns</span>
</p>
</Box>
<Box
properties={{
title: {
text: "True Signs"
}
}}
>
<p className={globals.text}>Insert text here.</p>
</Box>
{SignColorValues.map((color, idx) => (
<Box
key={"color" + idx}
properties={{
title: {
text: color.name
},
theme: new Color3(...color.color)
}}
>
<p className={globals.text}>
An assortment of {color.name}-blooded signs.
</p>
<div className={globals.horizontalList}>
{TrueSignValues.filter(
x => x.color.name == color.name
).map((sign, tsidx) => (
<SignCard
sign={sign}
key={"ts" + color.name + tsidx}
/>
))}
</div>
</Box>
))}
</>
);
}

View file

@ -5,10 +5,13 @@ import TrollCard from "@/components/cards/TrollCard/TrollCard";
import TrollSkeleton from "@/components/cards/TrollCard/TrollSkeleton";
import globals from "@/styles/global.module.css";
import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import { ClientClan } from "@/types/clan";
import { ThemerGetSet } from "@/types/generics";
import { ClientTroll } from "@/types/troll";
import { defaultTheme } from "@/utility/react/Themer";
import { getCookies } from "cookies-next";
import Link from "next/link";
import { useEffect, useState } from "react";
getCookies();
@ -35,6 +38,7 @@ export default function Index({
setFetchedClans(json);
}
getClan();
setTheme(defaultTheme);
}, []);
return (
<>
@ -47,6 +51,25 @@ export default function Index({
>
<span className={globals.text}>Welcome to TrollCall!</span>
</Box>
<Box
properties={{
title: {
text: "Hiveswap"
},
theme: new Color3(0.25, 0, 0.5)
}}
>
<span className={globals.text}>
Indulge yourself within the Extended Zodiac and its effects
on... everything, I guess.
</span>
<Link
className={globals.linkButton}
href="/hiveswap"
>
Enter the Hiveswap section
</Link>
</Box>
<Box
properties={{
title: {
@ -55,10 +78,6 @@ export default function Index({
}
}}
>
{/* <span className={globals.text}>
This is a series of cards that represent the most important
aspects of TrollCall.
</span> */}
{fetchedTrolls == null ? (
<>
<TrollSkeleton />
@ -67,7 +86,10 @@ export default function Index({
</>
) : (
fetchedTrolls.map((troll: ClientTroll, idx) => (
<TrollCard troll={troll} />
<TrollCard
troll={troll}
key={idx + "troll"}
/>
))
)}
</Box>
@ -79,10 +101,6 @@ export default function Index({
}
}}
>
{/* <span className={globals.text}>
This is a series of cards that represent the most important
aspects of TrollCall.
</span> */}
{fetchedClans == null ? (
<>
<ClanSkeleton />
@ -91,7 +109,10 @@ export default function Index({
</>
) : (
fetchedClans.map((clan: ClientClan, idx) => (
<ClanCard clan={clan} />
<ClanCard
clan={clan}
key={idx + "clan"}
/>
))
)}
</Box>

View file

@ -11,7 +11,9 @@ import "@/styles/index.module.css";
import { Color3 } from "@/types/assist/color";
import { ThemerGetSet } from "@/types/generics";
import { ClientTroll } from "@/types/troll";
import { defaultTheme } from "@/utility/react/Themer";
import { getCookies } from "cookies-next";
import Link from "next/link";
import { useEffect, useState } from "react";
getCookies();
@ -29,6 +31,7 @@ export default function Index({
setFetchedTroll(json);
}
getTroll();
setTheme(defaultTheme);
}, []);
const [openCB, CelesteBoxInstance] = CelesteBox({
@ -60,6 +63,24 @@ export default function Index({
},
"I am very proud of myself for making this!"
]
},
{
character: "madeline_lol",
dialog: [
"AAAAAWAWAWAWAWAWWAJJKKOGJNKASNGllgnwklwa klw kflfwajniopfNOKPFOIWANIOPWNWONGOKWALGNW gkwognwipngwgnwiakopgl,"
]
},
{
character: "madeline_lol",
dialog: [
"The quick red girl jumped over the giant mountain."
]
},
{
character: "madeline_lol",
dialog: [
"BABBABABABABABAB ab abal bla balb/@?>@?>!? !.rm1//.r1m /lm2/.2 2 2 2222/22//2/2//???@?@?2/2/2/2/2/2/2"
]
}
]
}
@ -143,6 +164,65 @@ export default function Index({
}
}}
>
<p className={globals.text}>
Here you can select some themes to test what TrollCall looks
like with ridiculous colors. It's pretty fun to try!
</p>
<p className={globals.text}>General themes</p>
<div className={globals.buttonRow}>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.9, 0.9, 0.8),
new Color3(0.7, 0.7, 0.6),
theme[2]
])
}
>
Default theme
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.5, 0.5, 0.4),
new Color3(0.1, 0.1, 0),
theme[2]
])
}
>
HC theme
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0, 0, 0),
new Color3(0, 0, 0),
false
])
}
>
AMOLED theme
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(1, 1, 1),
new Color3(1, 1, 1),
true
])
}
>
DELOMA theme
</button>
</div>
<p className={globals.text}>Coloured themes</p>
<div className={globals.buttonRow}>
<button
className={globals.button}
@ -154,7 +234,7 @@ export default function Index({
])
}
>
Red theme
Rust theme
</button>
<button
className={globals.button}
@ -166,7 +246,7 @@ export default function Index({
])
}
>
Orange theme
Bronze theme
</button>
<button
className={globals.button}
@ -178,7 +258,7 @@ export default function Index({
])
}
>
Yellow theme
Gold theme
</button>
<button
className={globals.button}
@ -202,7 +282,7 @@ export default function Index({
])
}
>
Green theme
Olive theme
</button>
<button
className={globals.button}
@ -274,7 +354,7 @@ export default function Index({
])
}
>
Pink theme
Violet theme
</button>
<button
className={globals.button}
@ -289,56 +369,283 @@ export default function Index({
Fuchsia theme
</button>
</div>
<p className={globals.text}>Experimental themes</p>
<div className={globals.buttonRow}>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.9, 0.9, 0.8),
new Color3(0.7, 0.7, 0.6),
new Color3(0, 0.5, 0.6),
new Color3(0, 0.1, 0.2),
theme[2]
])
}
>
Default theme
Celeste-ish
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.5, 0.5, 0.4),
new Color3(0.1, 0.1, 0),
new Color3(0.6, 0, 0),
new Color3(0.2, 0, 0),
theme[2]
])
}
>
HC theme
Time
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.5, 0, 0.6),
new Color3(0.1, 0, 0.2),
theme[2]
])
}
>
Rage
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.5, 0.5, 0.6),
new Color3(0, 0, 0.1),
theme[2]
])
}
>
Space
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(1, 1, 0),
new Color3(0.5, 1, 0),
theme[2]
])
}
>
Citrus
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(1, 0, 0),
new Color3(1, 0.75, 0),
theme[2]
])
}
>
Hotdog
</button>
</div>
<p className={globals.text}>
Spectacular Comment Chain-adjacent themes
</p>
<div className={globals.buttonRow}>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.6, 0, 1),
new Color3(0, 0.5, 0.5),
false
])
}
>
Lunar1314
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(1, 0.6, 0),
new Color3(0.5, 1, 1),
true
])
}
>
Solar1314
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0, 1, 0),
new Color3(1, 1, 1),
theme[2]
])
}
>
MrWaluigi
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(1, 0.5, 0.75),
new Color3(0.5, 0.25, 0.375),
theme[2]
])
}
>
Madisongs
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(1, 0.25, 0.5),
new Color3(0.5, 0.125, 0.25),
theme[2]
])
}
>
Badisongs
</button>
<span className={globals.text}>-</span>
<button
className={globals.buttonLink}
onClick={() =>
setTheme([
new Color3(0.5, 0.9, 1),
new Color3(0.25, 0.45, 0.5),
theme[2]
])
}
>
Addisongs
</button>
</div>
<p className={globals.text}>Vine funny themes</p>
<div className={globals.buttonRow}>
<button
className={globals.button}
onClick={() =>
setTheme([
new Color3(0.5, 1, 0.5),
new Color3(1, 1, 1),
true
])
}
>
White people be like
</button>
<button
className={globals.button}
onClick={() =>
setTheme([
new Color3(0, 0.5, 0),
new Color3(0, 0, 0),
false
])
}
>
Black people be like
</button>
</div>
<div className={globals.buttonRow}>
<a
className={globals.link}
href="https://youtu.be/raUjQRHMHIo"
target="_blank"
>
If you don't get the reference
</a>
</div>
<p className={globals.text}>User utility</p>
<div className={globals.buttonRow}>
<button
className={globals.buttonLink}
className={globals.button}
onClick={() =>
setTheme([theme[0], theme[1], !theme[2]])
}
>
Invert current theme
Invert theme palette
</button>
</div>
</Box>
<Box
properties={{
title: {
text: "Scroll module"
text: "UI module"
}
}}
>
<p className={globals.text}>Blah blah blah</p>
<p className={globals.text}>Blah blah blah</p>
<p className={globals.text}>Blah blah blah</p>
<p className={globals.text}>Blah blah blah</p>
<p className={globals.text}>Blah blah blah</p>
<p className={globals.text}>Blah blah blah</p>
<p className={globals.text}>Test all of the UI in TrollCall.</p>
<p className={globals.title}>globals.title applied to p</p>
<span className={globals.title}>
globals.title applied to span
</span>
<p className={globals.titleSmall}>
globals.titleSmall applied to p
</p>
<span className={globals.titleSmall}>
globals.titleSmall applied to span
</span>
<p className={globals.blockText}>
globals.blockText applied to p
</p>
<span className={globals.blockText}>
globals.blockText applied to span
</span>
<p className={globals.small}>globals.small applied to p</p>
<span className={globals.small}>
globals.small applied to span
</span>
<p className={globals.mono}>globals.mono applied to p</p>
<span className={globals.mono}>
globals.mono applied to span
</span>
<p className={globals.text}>globals.icon applied to p</p>
<p className={globals.icon}>face</p>
<p className={globals.text}>globals.icon applied to span</p>
<span className={globals.icon}>face</span>
<p className={globals.text}>globals.iconSmall applied to p</p>
<p className={globals.iconSmall}>face</p>
<p className={globals.text}>
globals.iconSmall applied to span
</p>
<span className={globals.iconSmall}>face</span>
<p className={globals.text}>globals.iconlike applied to p</p>
<p className={globals.iconlike}>HS</p>
<p className={globals.text}>globals.iconlike applied to span</p>
<span className={globals.iconlike}>HS</span>
<Link
href="#link"
className={globals.link}
id="link"
>
globals.link applied to a
</Link>
<button className={globals.button}>
globals.button applied to button
</button>
<Link
href="#linkButton"
className={globals.linkButton}
id="linkButton"
>
globals.linkButton applied to a
</Link>
<button className={globals.buttonLink}>
globals.buttonLink applied to button
</button>
</Box>
</>
);

View file

@ -1,44 +1,44 @@
body,
div#__next,
main.App {
margin: 0;
min-height: 100vh;
width: 100vw;
box-sizing: border-box;
margin: 0;
min-height: 100vh;
width: 100vw;
box-sizing: border-box;
/* Default text styling */
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
/* Default text styling */
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
}
main.App {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 8px;
background-color: var(--sec-bg);
color: var(--sec-fg);
background-image: url("/assets/pattern/pattern.png");
background-blend-mode: hard-light;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 8px;
background-color: var(--sec-bg);
color: var(--sec-fg);
background-image: url("/assets/pattern/pattern.png");
background-blend-mode: hard-light;
}
main.App.inverted {
background-image: url("/assets/pattern/pattern_inv.png");
background-image: url("/assets/pattern/pattern_inv.png");
}
main.App div.mainContent {
display: flex;
box-sizing: border-box;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 8px 0;
gap: 8px;
width: 100%;
max-width: 768px;
/* height: 100vh; */
display: flex;
box-sizing: border-box;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding-top: 8px;
gap: 8px;
width: 100%;
max-width: 768px;
/* height: 100vh; */
}
/* Change behaviour of some elements */
@ -46,12 +46,12 @@ main.App div.mainContent {
p,
ul,
ol {
margin: 0;
padding: 0;
display: block;
margin: 0;
padding: 0;
display: block;
}
ul,
ol {
list-style-position: inside;
list-style-position: inside;
}

View file

@ -1,67 +1,5 @@
@import url(./fonts.css);
.title {
font-size: 16px;
line-height: 20px;
font-family: "TrollCall Display";
text-transform: uppercase;
}
.titleSmall {
font-size: 14px;
line-height: 18px;
font-family: "TrollCall Display";
text-transform: uppercase;
}
.text {
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
}
.blockText {
display: block;
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
}
.small {
font-size: 12px;
line-height: 14px;
font-family: "Space Grotesk";
}
.mono {
font-size: 16px;
line-height: 20px;
font-family: "Space Mono";
}
.icon {
font-size: 24px;
line-height: 24px;
font-family: "Material Symbols Outlined";
font-variation-settings: "FILL" 1, "opsz" 24, "GRAD" 0, "wght" 400;
user-select: none;
}
.iconSmall {
font-size: 16px;
line-height: 16px;
font-family: "Material Symbols Outlined";
font-variation-settings: "FILL" 1, "opsz" 24, "GRAD" 0, "wght" 400;
user-select: none;
}
.iconlike {
font-size: 20px;
line-height: 20px;
font-family: "Space Mono";
user-select: none;
}
.link {
text-decoration: none;
color: inherit;
@ -75,6 +13,29 @@
text-shadow: 0 0 8px currentColor;
}
.linkButton {
text-decoration: none;
color: inherit;
box-shadow: 0 0 2px currentColor;
background-color: transparent;
border: 1px solid currentColor;
padding: 4px 8px;
border-radius: 2px;
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
cursor: pointer;
text-align: center;
transition: box-shadow 0.125s;
}
.linkButton:hover {
text-decoration: none;
box-shadow: 0 0 8px currentColor;
}
.button {
color: inherit;
box-shadow: 0 0 2px currentColor;
@ -118,6 +79,82 @@
text-shadow: 0 0 8px currentColor;
}
.title {
font-size: 16px;
line-height: 20px;
font-family: "TrollCall Display";
text-transform: uppercase;
}
.titleSmall {
font-size: 14px;
line-height: 18px;
font-family: "TrollCall Display";
text-transform: uppercase;
}
.text {
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
}
.blockText {
display: block;
font-size: 16px;
line-height: 20px;
font-family: "Space Grotesk";
}
.small {
font-size: 12px;
line-height: 14px;
font-family: "Space Grotesk";
}
.mono {
font-size: 16px;
line-height: 20px;
font-family: "Space Mono";
}
.icon {
display: inline-block;
font-size: 24px;
line-height: 24px;
height: 24px;
font-family: "Material Symbols Outlined";
font-variation-settings: "FILL" 1, "opsz" 24, "GRAD" 0, "wght" 400;
user-select: none;
}
.iconSmall {
display: inline-block;
font-size: 16px;
line-height: 16px;
height: 16px;
font-family: "Material Symbols Outlined";
font-variation-settings: "FILL" 1, "opsz" 24, "GRAD" 0, "wght" 400;
user-select: none;
}
.iconlike {
display: inline-block;
font-size: 20px;
line-height: 24px;
height: 24px;
padding-bottom: 2px;
vertical-align: middle;
font-family: "Space Mono";
user-select: none;
}
.boxLike {
display: inline-flex;
flex-direction: column;
gap: 8px;
}
.buttonRow,
.horizontalList {
display: flex;
@ -141,3 +178,76 @@
justify-content: flex-start;
gap: 8px;
}
.iconTextTop {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
gap: 8px;
}
.buttonLeft {
display: grid;
grid-template-columns: max-content 1fr;
justify-content: flex-start;
align-items: center;
gap: 16px;
padding-right: 8px;
}
.buttonRight {
display: grid;
grid-template-columns: 1fr max-content;
justify-content: flex-end;
align-items: center;
gap: 16px;
padding-left: 8px;
}
.sep {
width: 100%;
background-color: currentColor;
color: currentColor;
padding: 0;
margin: 8px 0;
border: none;
height: 1px;
}
.sepHeader {
width: 100%;
background-color: currentColor;
color: currentColor;
padding: 0;
margin: 0;
border: none;
height: 1px;
}
.invisep {
width: 100%;
background-color: transparent;
color: transparent;
padding: 0;
margin: 2px 0;
border: none;
height: 1px;
}
.invisepHeader {
width: 100%;
background-color: transparent;
color: transparent;
padding: 0;
margin: 0;
border: none;
height: 1px;
}
.signage {
filter: drop-shadow(1px 1px 0 currentcolor)
drop-shadow(-1px -1px 0 currentcolor)
drop-shadow(1px -1px 0 currentcolor)
drop-shadow(-1px 1px 0 currentcolor);
}

View file

@ -217,18 +217,19 @@ export const SwaySchema = yup.object({
export type SwayType = {
name: string;
description: string;
color: ColorTypes;
};
export const Sway: { [key: string]: SwayType } = {
Prospit: {
name: "Prospit",
description:
"Marked by a flexible optimism, the personalities of Prospit Dreamers are reactive and intuitive. They naturally exist in the present, rather than look to the future or obsess over the past. When making decisions Prospit Dreamers tend to rely on gut instinct and whatever emotions they are experiencing at the moment. This makes them quick to act and reliable in a crisis, but it also can make them capricious. They have trouble thinking things through, and their feelings toward specific situations and decisions can change from day to day. They solve problems with creativity rather than cold logic, often seeing multiple options with ease and clarity. Because they generally take things as they come, Prospit Dreamers are less rebellious than they are adaptable-instead of struggling against authority, they will find a way to coexist with it. Possibly because they are so instinctual and flexible, they like having a defined set of rules-a safety net for their passionate lives. Naturally trusting, they have trouble with deception or hiding their true selves, and will often worry about what others think of them. The self they project into the world is often not under their control."
description: "",
color: [1, 1, 0]
},
Derse: {
name: "Derse",
description:
"Derse Dreamers have personalities marked by a distinct and restless skepticism. Whatever their waking circumstances, chances are they will live in a state of dissatisfaction. Rebellion is in their blood, manifesting whether they are fighting back against a fascist dictatorship, or the most recent trend in casual footwear. Derse Dreamers are cerebral and self-aware; they have a far better grasp on the landscape of their own minds than on the world around them, which they can find alienating and confusing. But as so much of their identity is built on control, they will do their utmost to hide any insecurities, often with false humility or self-deprecating humor. They may be inflexible and pessimistic, but they are also great problem solvers, facing conflicts head-on with shrewd, calculating minds. They see one true path among an infinite snarl of wrong ones. They tend to be introverted, but if you win their trust Derse Dreamers are extremely powerful allies. However, they find sincere vulnerability difficult and will often keep people at arm's length. Letting go and living in the moment is hard for a Derse Dreamer; they constantly look toward the future and analyze the past."
description: "",
color: [1, 0, 1]
}
};
@ -243,68 +244,69 @@ export const AspectSchema = yup.object({
export type AspectType = {
name: string;
description: string;
color: ColorTypes;
};
export const Aspect: { [key: string]: AspectType } = {
Time: {
name: "Time",
description:
"Those bound to the aspect of Time are fighters, full stop. Their lives are often marked by struggle, not so much because fate has it in for them, but because they are fundamentally incapable of just accepting things as they come. They value action over passive acceptance, even if that may not be the wisest or safest choice. Don't try to tell a Time-bound to sit still and look pretty. They are very goal-focused, and tend to value the destination over the journey, and you won't find them making that journey in any traditional sort of way. To quote cheesy posters found on many a guidance counselor's wall-\"impossible is just a word\". If you need a miracle, they are who you call. At their best, the Time-bound are empathetic and relentless problem-solvers. At their worst they are ruthless, defensive, and impulsive. "
description: "",
color: [1, 0.125, 0]
},
Space: {
name: "Space",
description:
"Those bound to the aspect of Space are, as the name suggests, concerned with the big picture. They are patient, masters of the art of 'wait-and-see', and are inclined to take things as they come. That isn't to say that they're pushovers or willing to let injustice lie-they just choose their battles wisely, understanding that sometimes you have to let something burn to the ground in order to build it back better and stronger than before. To this effect, they tend to be innovators, concerned with creation and redemption. Catch them recycling the old to make the new, the fresh, and the beautiful. For the Space-bound, the journey is as, if not more, important than the destination; how they do something is as important as what they do. At their best, they are steady, impartial, and creative. At their worst, they can be detached, apathetic, and vague. "
description: "",
color: [0, 0, 0]
},
Heart: {
name: "Heart",
description:
"Those bound to the aspect of Heart are very concerned with their favorite subject: themselves. It wouldn't be a stretch to call them 'self-obsessed', but not necessarily in a negative way. They simply want to understand the one thing we all are stuck with for our entire lives, i.e. our own minds. Forging an identity is extremely important to the Heart-bound, and every decision and action goes toward building a coherent narrative of their own story. That isn't to say Heart-bound don't care deeply for their friends and allies; they just have a tendency to assume that everyone is as concerned with identity as they are. They are excellent at putting on and taking off masks as the situation calls for them. At their best, they are competent, imaginative, and steady. At their worst they can be overbearing, inflexible, and cold. "
description: "",
color: [0.75, 0, 0.25]
},
Mind: {
name: "Mind",
description:
"Those bound to the aspect of Mind are-you guessed it-the universe's great thinkers. But don't for a second think that means that they have all the answers. They are very concerned with remaining rational, and they have such a firm hold on the constant conjunction of their thinking that it's easy for them to see the multitudes of the choices laid out before them, which often leaves them frozen and unable to act. That said, when a Mind-bound finally launches into action, they can execute a plan with unbelievable grace and precision. Their identity is fluid-it can change from day-to-day, from thought-to-thought, from interaction-to-interaction. Remaining logical is more important to them than building up a solid foundation of \"self.\" At their best they are great innovators, architects, and creators. At their worst they can be nasty, inflexible, and indecisive. "
description: "",
color: [0, 1, 0.75]
},
Hope: {
name: "Hope",
description:
"Those bound to the aspect of Hope are driven first and foremost by their convictions. They do right for right's sake, and are quick to come to the aid of anyone they deem to be experiencing injustice. That said, their views of the world can be quite black and white, so what they see as the \"right\" thing may not always be the universally accepted view. They put great value in the power of the imagination, the ability to dream up a better and more beautiful future. If anyone could dream a better world into existence, it would be one of the Hope-bound. They may sound like all sunshine and rainbows, but they aren't adverse to a little destruction, especially if they think they can replace it with something better and more just. At their best, Hope-bound are positive, caring, and warm. At their worst they can be narrow-minded and selfish. "
description: "",
color: [1, 0.75, 0.25]
},
Rage: {
name: "Rage",
description:
"Those bound to the aspect of Rage are bringers of chaos. They posses great contempt for lies or false ideas, including the stability that false ideas can impart. To them, the true is far more important than the good; they would tear down a system just to destabilize it if, by their reckoning, it is built on faulty premises. Often the Rage-bound prefer anarchy to any of the alternate forms of civilization, which they believe to be riddled with lies and foolishness and obedient masses. They are bringers of confusion and doubt, and they can be frustratingly difficult to convince otherwise when they have attached themselves to an idea. If they sound dangerous, they are. The Rage-bound tend to be most volatile and unpredictable of the aspects. At their best they are original, revolutionary, and fearless. At their worst they are cruel, uncompromising, and vicious. "
description: "",
color: [0.5, 0.25, 0.75]
},
Light: {
name: "Light",
description:
"Those bound to the aspect of Light are the universe's knowledge-seekers. They are, above all, driven to learn and understand. They are great alchemists, able to take multiple sources of information and synthesize them into something useful. They are scholars and researchers, absolutely dedicated to knowledge for knowledge's sake. They are the ultimate students, and although that might conjure up the image of people sitting around peacefully waiting for knowledge to be brought to them, that couldn't be further from the truth. The Light-bound will go after knowledge with a fierce intensity that others may find distasteful. They aren't overly concerned with laws or norms, either. They often take rules as simple suggestions, instead searching for loopholes or work-arounds. At their best, the Light-bound are resourceful and driven. At their worst they can be fussy, pedantic, and insensitive."
description: "",
color: [1, 1, 0.25]
},
Void: {
name: "Void",
description:
"Those bound to the aspect of Void are the universe's secret-keepers. The unknown doesn't scare them-where others might see emptiness, they see potential. A blank page, an empty canvas, that's what the Void-bound live for. They value mystery and the unexplained, and are not particularly bothered by not having all the answers. Where others might be compelled to go out and seek answers, the Void-bound lean more toward casting doubt on what is already considered fully understood. They don't take much on faith and would rather live in a state of confusion than believe something that might be untrue or bow to intellectual authority. After all, in order for something new to be built, the old, rotting foundation must often be razed. At their best, Void-bound are wise, intuitive, and vibrant. At their worst they can be dismissive, indecisive, and apathetic. "
description: "",
color: [0, 0.125, 0.25]
},
Breath: {
name: "Breath",
description:
"Those bound to the aspect of Breath are, above all, expansive. Flexible and driven, they leave an impact wherever they go. Like the breeze itself, they are able to sweep others up to carry along in their wake, but also like the breeze, they can be difficult to catch hold of or tie down. Although Breath-bound do make very good leaders, breath tends to be a very personal aspect. Often, heroism comes along as an offshoot of them pursuing their own personal stories. They lead by example, and will routinely be surprised that others look up to or feel inspired by them. They have a tendency to underestimate themselves, and not always out of poor self-esteem. They were just doing their own thing. At their best Breath-bound are motivated, adaptable, and forward thinking, but at their worst they can be volatile, avoidant, and gullible."
description: "",
color: [0.25, 0.75, 1]
},
Blood: {
name: "Blood",
description:
'Those bound to the aspect of Blood draw their strength from bonds, from the trust and camaraderie that blooms among a group of people who all share a single vision. Blood-bound are absolutely leaders, but they inhabit more of an inspirational role than a commanding one. They are prophets, rather than generals, giving others the strength and motivation to keep fighting. The Blood-bound can dispense excellent advice even when their own lives and interpersonal relationships are disasters. They can be very "do as I say, not as I do" types. A Blood-bound can often be found on a sinking ship, forcing an endeavor forward with sheer stubborn force of will. No matter how bad things go, a Blood-bound can always count on friends and allies. At their best, they are charismatic, uplifting, and magnetic. At their worst they can be sullen, unkind, and set-in-their-ways. '
description: "",
color: [0.75, 0.125, 0.125]
},
Life: {
name: "Life",
description:
"Those bound to the aspect of Life are the universe's healers. They are concerned with the betterment of themselves and those around them, as well as the onward march of positive progress. Deeply empathetic, they have an intuitive understanding of other's suffering and the best way of righting those wrongs. If you're poisoned, chances are the Life-bound have something for what ails ya. This applies to both physical and mental suffering, though it might not be a cure you'll like. They also have the tendency to put other's needs before their own, which never ends well for anyone, because the Life-bound can grow bitter if they feel their own self-care has had to be shunted aside. At their best, they are great listeners, caretakers, and nurturers. At their worst, the Life-bound are passive aggressive, and pushy-they're certain they know best. "
description: "",
color: [0.5, 0.75, 0.25]
},
Doom: {
name: "Doom",
description:
"Those bound to the aspect of Doom are fate's chosen sufferers. It may not sound like an overly pleasant aspect to be aligned with, but it does come along with great wisdom and empathy. The Doom-bound understand that misery loves company, and they are ready and willing to provide said company. The Doom-bound won't fix you; they aren't healers. They are commiserators, aware that sometimes the only thing you can do for a person is let them know that they are not alone in their suffering. They are not the advice friend-they're the friend you go to when you need to vent about a rough day at work. They are not necessarily noble martyrs, either-the Doom-bound can become quite irate about their lot. At their best they are wise, kind, and non-judgemental. At their worst, bitter, resentful, and fatalistic."
description: "",
color: [0.5, 0.66, 0]
}
};
@ -334,98 +336,86 @@ export const SignColor: {
} = {
Rust: {
name: "Rust",
description:
"Adventure motivates Rust Signs more than anything else. They crave new experiences, the wilder and farther-from-home, the better. They are confident and energetic, ready to face the unknown. This dynamism makes them great leaders, but it can also make them foolhardy. Often, they don't posses the level of caution they should for someone so willing to jump into new things. Their willingness to trust can get them into trouble, but they are also incredibly resilient. Their ability to bounce back from trauma and injury leaves them as the toughest sign class on the spectrum. Rust Signs make great friends and traveling companions, but they also can be selfish and quick to anger. If what they deem to be an acceptable level of \"excitement\" isn't happening around them, they have a tendency to try to stir some up. They love the drama. They have incredibly high expectations for themselves and for romantic partners. If someone doesn't live up to these, they may deem them not worth their time. If they aren't careful, Rust Signs can end up in a cycle of excitement, followed by crushed expectations, followed by a quick recovery and new flush of excitement. ",
description: "",
sign: "Aries",
color: [255, 0, 0],
color: [1, 0, 0],
dates: ["March 21", "April 19"]
},
Bronze: {
name: "Bronze",
description:
"Bronze Signs have a warm and generous disposition, but you might not accuse them of it the first time you meet. They have a tendency toward being withdrawn and slow to open up with new people. This can make them come off as arrogant and cold, like they think they are too good for everyone, although the reality couldn't be further from the truth. In fact, they crave validation and companionship. They are very open-hearted, but if a Bronze Sign decides to dig their heels in, it can be like talking to a wall. More so than any of the other sign classes, Bronze Signs have a marked love of creature comforts. They crave stability and safety, and if they have the means, their homes will be full of beautiful things. Some might accuse them of being hedonistic; they would probably just claim to know what they like. As lovers they can be quite needy, wanting assurances that the affection they feel is reciprocated. Maybe because of this, they have a particular affinity for animals. Don't try to break a Bronze's Sign's routines-they'll resent you for it, even if oftentimes they are too polite to say so.",
description: "",
sign: "Taurus",
color: [255, 128, 0],
color: [1, 0.5, 0],
dates: ["April 20", "May 20"]
},
Gold: {
name: "Gold",
description:
"Gold Signs are the reigning geniuses of the sign class spectrum, and chances are they know it. Witty and widely read, they enjoy conversation and debate, even when that conversation gets a little one-sided. They can come off as preachy, and they have a tendency to railroad, just driving into their interlocutors with the force of their intellect. Their arguments make perfect sense to themselves, but not always to those around them. Gold Signs are interested in a wide variety of topics, so they tend to be Jacks-of-all-trade, and can have trouble dedicating themselves to just a single hobby or career. They have a tendency to be high-energy, and can stress people out, including themselves. Their anxiety is such that they often need quite a bit of time alone with their projects. They can talk circles around most people, and they aren't afraid to use their intelligence to manipulate others to get what they want. They are good at making money, and also good at spending it. They aren't great financial planners, tending toward impulse purchases. In romance they lean toward partners who can keep up with them, both with their intellect and their energy, which can both be hard to match. ",
description: "",
sign: "Gemini",
color: [255, 255, 0],
color: [1, 1, 0],
dates: ["May 21", "June 21"]
},
Lime: {
name: "Lime",
description:
"Lime Signs are tumultuous, bringing great emotion and creativity to their endeavors. They are resolute in their decisions; if they are going to do something, they do it. They have a tendency toward melodrama, especially when they feel passionately about something, and their bad moods are loud and usually difficult to conceal. Hiding their feelings does not come naturally to them, so many Lime Signs cultivate a hard outer shell to hide the passionate, caring person inside. Lime Signs tend to have a large group of friends-they draw people to them with allure and the promise of excitement, and are usually unaware that they are doing it. They tend to focus on their own flaws, rather than their good points. Although they are exceedingly kind and empathetic individuals, many Lime Signs posses a mean streak. If you catch them on a bad day, they can be incredibly vicious. But it they take care to use their power for good, they make very loyal companions. Romance is extremely important to Lime Signs, and when they fall, they fall hard. They don't take rejection well, and a breakup can send them into a tailspin requiring an extended period of recovery.",
description: "",
sign: "Cancer",
color: [127, 255, 0],
color: [0.5, 1, 0],
dates: ["June 22", "July 22"]
},
Olive: {
name: "Olive",
description:
"Olive Signs are, by and large, incredibly agreeable people. They are generous and enthusiastic, ready to offer help to anyone who needs it. Luck plays a large role in their lives; Olive Signs have a knack for being in the right place at the right time. And even in the case that their luck goes bad, they can ride rough patches out without falling too far into depression or hopelessness. That said, Olive Signs are most comfortable with things that they are familiar with; new places and ideas often alarm them, resulting in a dogmatic insistence that their way is the right way. They can be quite bossy and domineering, although that usually comes out of a genuine belief that they know best and can help the ones they care about. They are extremely faithful friends and lovers, ready to drop everything and go into helper mode. However, if their trust is breached, there's no going back. No one can hold a grudge like an Olive Sign, and they aren't afraid to just pick up and leave if they decide something isn't working for them. Romance and companionship are extremely important to them, so even if they get hurt, their hearts remain open.",
description: "",
sign: "Leo",
color: [0, 255, 0],
color: [0, 1, 0],
dates: ["July 23", "August 22"]
},
Jade: {
name: "Jade",
description:
"Jade Signs are the zodiac's caretakers. Intelligent and steady, they are excellent organizers and planners. They are detail-oriented, and can tend toward perfectionism, never satisfied with their endeavors. If you hire on a Jade Sign, be prepared for an excellent product, but also no peace until that project is flawless. They are fussy and particular, which can cause friction with those around them, although a Jade Sign holds no one to as high a standard as they hold themselves. Since they are shy with strangers and slow to open up, Jade Signs can often come off as timid or doormats, when really they just prefer to come at conflicts in a less combative way. Naturally loyal and loving, they make wonderful doctors, parents, and caretakers, whether they are taking care of people, pets, or plants. In relationships, they can be slow to open up, and need someone willing to be patient enough to go at their pace. If all of this makes Jade Signs sound soft and nurturing, they are, but keep in mind that they can also be fiercely destructive if those they care about are threatened. It takes a lot to make a Jade Sign snap, but if they do, take cover.",
description: "",
sign: "Virgo",
color: [0, 255, 127],
color: [0, 1, 0.5],
dates: ["August 23", "September 22"]
},
Teal: {
name: "Teal",
description:
"Teal Signs are natural charmers. Social and flirtatious, they are great at parties and public speaking events. Even though they aren't afraid to use their many engaging qualities in both personal and business ventures, they have a strong moral sense. Right and wrong are very obvious to a Teal Sign, and it can frustrate them that others don't see the world the same way they do. Their idealism can make them strong defenders of justice, but it can also result in them being incredibly let down. Their strict adherence to procedure can lead to errors in judgement; they can be gullible and too quick to trust. They have vibrant imaginations, and enjoy fiction and roleplaying, and often those games will resemble the lives they want to be living. Deep down, they often long for a hero, someone they can idolize and count on, with the smarts and charisma to keep up with them. Unfortunately, they have a tendency to get involved with people who are very obviously wrong for them out of a desire not to be alone. Many Teal Signs are better off being single, at least until someone really extraordinary comes along.",
description: "",
sign: "Libra",
color: [0, 255, 255],
color: [0, 1, 1],
dates: ["September 23", "October 23"]
},
Blue: {
name: "Blue",
description:
"Let's not mince words: Blue Signs are the ones to watch. Of all the sign classes, they have the potential to do the most good, but also cause the worse harm. They can be incredibly effective, and also incredibly destructive. Tell a Blue Sign this and chances are they would agree with you. They are magnetic and adaptive, able to adjust how they present themselves in any situation. They have a mask for every occasion. They are obsessively dedicated, willing to throw themselves into work, play, and everything in between. Because of this, Blue Signs are highly valuable allies and friends. However, they are very selective when it comes to who they let into their inner circle. You could be best friends with a Blue Sign and still never truly know them. They are powerful and successful, but they also tend toward jealousy. They often resent those they see as more well-positioned than they are. A well-adjusted Blue Sign is fantastically competent and inspiring, but a Blue Sign at their worst is a force for chaos. In love they can find themselves having to choose between their ambitions and their relationships, often with great difficulty.",
description: "",
sign: "Scorpio",
color: [0, 127, 255],
color: [0, 0.5, 1],
dates: ["October 24", "November 21"]
},
Indigo: {
name: "Indigo",
description:
"Indigo Signs are the enthusiasts of the sign classes. Friendly and cheerful, their optimism is contagious. Being around a well-adjusted Indigo Sign is always a good time. It's hard not to be drawn into their excitable orbit, just like they are drawn in by anything and everything that piques their interest. And those interests are liable to change at any time. Indigo Signs will often surprise their friends and family by declaring they are no longer interested in what just last week they were claiming was their jam. If you catch an Indigo Signs in a philosophical mood, they can be unexpectedly poignant and introspective. A downside of all this jovial enthusiasm is that Indigo Signs often don't know their own strength. They are known to be careless, both physically and emotionally, their conversations punctuated by jostling elbows and tactless comments. They don't usually mean to offend, and are often shocked to find out they upset anyone. When this happens, they can dig their heels in and insist they did nothing wrong. In romance, Indigo Signs need partners who can keep up with their expansive personalities, as well as forgive them for the occasional hurt feeling or two.",
description: "",
sign: "Sagittarius",
color: [0, 0, 255],
color: [0, 0, 1],
dates: ["November 22", "December 21"]
},
Purple: {
name: "Purple",
description:
"Purple Signs are the workaholics of the sign classes. Ambitious and driven, they have a very specific path in mind to reach the pinnacle of their field, and will work tirelessly toward it. However, if their practical brains convince them that their goal is unrealistic, they may be slow to trust anyone with the secret of their true desires. They are often very funny, their wit veering toward the dryly macabre. Their fatalism can be incredibly humorous or terrible, depending who you ask. Purple Signs are usually the people who will say out loud what everyone else was thinking but was too nervous to mention. They are very stubborn, and once they've made up their mind about something, whether it be a restaurant choice or a political affiliation, it is difficult to change. They have trouble admitting they were mistaken, and also that they are upset. An oft-repeated phrase of the Purple Signs is, \"It's fine, don't worry about it.\" They will let arguments fester rather than face them head on. In love they tend to be strictly monogamous and fiercely devoted, ready to pledge themselves to a person the same way they do their goals-utterly, and without reservation.",
description: "",
sign: "Capricorn",
color: [127, 0, 255],
color: [0.5, 0, 1],
dates: ["December 22", "January 19"]
},
Violet: {
name: "Violet",
description:
"Violet Signs are the universe's eccentrics. Forget marching to their own drummer-Violets built their own drum, and it's probably weird. A good deal of this is natural, but they also have a distinct bent toward contrariness. They are the sorts to give the popular thing a pass. Personable and outlandish, they are ready to make friends with anyone, although if they aren't careful their 'game for anything' attitude can come across as clingy or desperate. When their feelings are reciprocated, however, they are very loyal friends. Politics and humanitarian causes are often very important to Violet Signs, and they will turn their considerable inventive energy into a sort of noblesse oblige, happy to offer their nontraditional approaches to help others. At their very best Violet Signs are artistic and inspired, but they tread the fine line between genius and maniac. Too often their more esoteric interests can come across as perverse or untoward, and they can have a hard time holding their tempers, especially if they feel that they are being belittled or ignored. Intelligence is enormously attractive to Violet Signs, and often an intellectual connection is necessary for them to be attracted to a prospective partner.",
description: "",
sign: "Aquarius",
color: [255, 0, 255],
color: [1, 0, 1],
dates: ["January 20", "February 18"]
},
Fuchsia: {
name: "Fuchsia",
description:
"Fuchsia Signs are the final of the sign classes, fittingly, also the most enigmatic. Possessing a strong imagination, they have an otherworldly quality to them that draws others in. Often, it has more to do with what they don't tell you than what they do, giving them an air of mystery that would more than likely perplex a Fuchsia sign if you told them about it. They aren't usually trying to be alluring-they're just lost in thought. Highly emotional, Fuchsia signs are sensitive and anxious, and tend to spend a lot of time worrying-about the world, the future, and what others think of them. They are artistic and talented, but can suffer from crippling bouts of depression, holding themselves to impossibly high standards. They have rich fantasy lives, and can get so caught up in daydreams that they sometimes forget to actually do things. Many Fuchsia Signs have trouble with follow-through, and it can take a lot to kick them out of their inertia. As far as romance goes, they need partners who are willing to put in the time to go at their pace, and who can handle how sensitive and emotional they can be.",
description: "",
sign: "Pisces",
color: [255, 0, 127],
color: [1, 0, 0.5],
dates: ["February 19", "March 20"]
}
};

View file

@ -0,0 +1,8 @@
import { createContext } from "react";
const AuthContext = createContext({
TROLLCALL_NAME: "",
TROLLCALL_CODE: ""
});
export default AuthContext;

View file

@ -2,16 +2,16 @@ import { Color3 } from "@/types/assist/color";
import { createContext } from "react";
export default function Themer({
pri,
sec,
inverted,
pri,
sec,
inverted
}: {
pri: Color3;
sec: Color3;
inverted?: boolean;
pri: Color3;
sec: Color3;
inverted?: boolean;
}) {
return inverted ? (
<style>{`
return inverted ? (
<style>{`
/* If you are seeing this, congratulations! You now have ligma. */
:root {
--pri-bg: #${pri.lighten(70).toHex()};
@ -21,8 +21,8 @@ export default function Themer({
--sec-fg: #${sec.darken(70).toHex()};
}
`}</style>
) : (
<style>{`
) : (
<style>{`
/* If you are seeing this, congratulations! You now have ligma. */
:root {
--pri-bg: #${pri.darken(70).toHex()};
@ -32,7 +32,16 @@ export default function Themer({
--sec-fg: #${sec.lighten(70).toHex()};
}
`}</style>
);
);
}
export const ThemeModeContext = createContext(false as boolean | undefined);
export const defaultTheme: [Color3, Color3] = [
new Color3(0.9, 0.9, 0.8),
new Color3(0.7, 0.7, 0.6)
];
export const hiveswapTheme: [Color3, Color3] = [
new Color3(0.5, 0, 1),
new Color3(0.25, 0, 0.5)
];

View file

@ -8,6 +8,7 @@
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"noErrorTruncation": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,