forked from spacebar/SplatNet-Backend
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0368d8dedc |
18 changed files with 116 additions and 360 deletions
|
|
@ -7,9 +7,9 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
runs-on: ${{ vars.RUNNER_LABEL }}
|
runs-on: debian-bookworm
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: install docker???
|
- name: install docker???
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,12 @@
|
||||||
|
|
||||||
# SplatNet
|
# SplatNet
|
||||||
|
|
||||||

|
[](https://git.crafterpika.cc/kittentm/splatnet-backend/commits/branch/main)
|
||||||
[](https://git.crafterpika.cc/kittentm/splatnet-backend/actions)
|
[](https://git.crafterpika.cc/kittentm/splatnet-backend/actions)
|
||||||
[](https://git.crafterpika.cc/kittentm/splatnet-backend)
|
[](https://git.crafterpika.cc/kittentm/splatnet-backend)
|
||||||
[](https://git.crafterpika.cc/kittentm/splatnet-backend/src/branch/main/LICENSE)
|
[](https://git.crafterpika.cc/kittentm/splatnet-backend/src/branch/main/LICENSE)
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
This is the backend for the [SplatNet](https://git.crafterpika.cc/kittentm/splatnet) Revival frontend.
|
This is the backend for the [SplatNet](https://git.crafterpika.cc/kittentm/splatnet) Revival frontend. It is a combination of Python & JS.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment include:
|
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
|
||||||
* Being respectful of differing viewpoints and experiences
|
|
||||||
* Gracefully accepting constructive criticism
|
|
||||||
* Focusing on what is best for the community
|
|
||||||
* Showing empathy towards other community members
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
||||||
|
|
||||||
## Our Responsibilities
|
|
||||||
|
|
||||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
|
|
||||||
|
|
||||||
[homepage]: https://contributor-covenant.org
|
|
||||||
[version]: https://contributor-covenant.org/version/1/4/
|
|
||||||
|
|
@ -18,7 +18,6 @@ class Settings(BaseSettings):
|
||||||
twitter_client_id: str
|
twitter_client_id: str
|
||||||
twitter_client_secret: str
|
twitter_client_secret: str
|
||||||
twitter_redirect_uri: str
|
twitter_redirect_uri: str
|
||||||
account_client_secret: str
|
|
||||||
|
|
||||||
model_config = SettingsConfigDict(
|
model_config = SettingsConfigDict(
|
||||||
env_file=[
|
env_file=[
|
||||||
|
|
|
||||||
173
judd/package-lock.json
generated
173
judd/package-lock.json
generated
|
|
@ -336,41 +336,6 @@
|
||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/agent-base/node_modules/debug": {
|
|
||||||
"version": "4.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
|
||||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ms": "^2.1.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"supports-color": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/agent-base/node_modules/ms": {
|
|
||||||
"version": "2.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/append-field": {
|
"node_modules/append-field": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
|
||||||
|
|
@ -384,14 +349,13 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.18.0",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
|
||||||
"integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==",
|
"integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.16.0",
|
"follow-redirects": "^1.15.11",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
"https-proxy-agent": "^5.0.1",
|
|
||||||
"proxy-from-env": "^2.1.0"
|
"proxy-from-env": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -667,9 +631,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/discord.js": {
|
"node_modules/discord.js": {
|
||||||
"version": "14.26.4",
|
"version": "14.26.3",
|
||||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.26.4.tgz",
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.26.3.tgz",
|
||||||
"integrity": "sha512-4oBp8tc6Kf8IDBwAHhbsMaAqx1b5fob9SNasZT7V6yyyUydoO5i5fGuX7TmvRtR+q/WgKRnRViRoAWnG7fNyvA==",
|
"integrity": "sha512-XEKtYn28YFsiJ5l4fLRyikdbo6RD5oFyqfVHQlvXz2104JhH/E8slN28dbky05w3DCrJcNVWvhVvcJCTSl/KIg==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^1.14.1",
|
"@discordjs/builders": "^1.14.1",
|
||||||
|
|
@ -833,12 +797,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/express-rate-limit": {
|
"node_modules/express-rate-limit": {
|
||||||
"version": "8.5.2",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.3.2.tgz",
|
||||||
"integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==",
|
"integrity": "sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ip-address": "^10.2.0"
|
"ip-address": "10.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
|
|
@ -1148,42 +1112,6 @@
|
||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "6",
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/https-proxy-agent/node_modules/debug": {
|
|
||||||
"version": "4.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
|
||||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ms": "^2.1.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"supports-color": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/https-proxy-agent/node_modules/ms": {
|
|
||||||
"version": "2.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.7.2",
|
"version": "0.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
||||||
|
|
@ -1216,9 +1144,9 @@
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/ip-address": {
|
"node_modules/ip-address": {
|
||||||
"version": "10.2.0",
|
"version": "10.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
||||||
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
|
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12"
|
"node": ">= 12"
|
||||||
|
|
@ -1240,9 +1168,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/joi": {
|
"node_modules/joi": {
|
||||||
"version": "18.2.3",
|
"version": "18.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/joi/-/joi-18.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/joi/-/joi-18.1.2.tgz",
|
||||||
"integrity": "sha512-N5A3KTWQpPWT4ExxxPlUx7WmykGXRzhNidWhV41d6Abu9YfI2NyWCJuxdPnslJCPWtbRpSVOWSnSS6GakLM/Rg==",
|
"integrity": "sha512-rF5MAmps5esSlhCA+N1b6IYHDw9j/btzGaqfgie522jS02Ju/HXBxamlXVlKEHAxoMKQL77HWI8jlqWsFuekZA==",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/address": "^5.1.1",
|
"@hapi/address": "^5.1.1",
|
||||||
|
|
@ -1348,23 +1276,31 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/morgan": {
|
"node_modules/morgan": {
|
||||||
"version": "1.11.0",
|
"version": "1.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz",
|
||||||
"integrity": "sha512-zSkVu3t18r39pw4ixfBKvfZi3y2UOqr7d4WYwcj3m8nXpEQK4rPO6GLzs/CExoRgmX3y9EjmmcXqv6jq0SK46g==",
|
"integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"basic-auth": "~2.0.1",
|
"basic-auth": "~2.0.1",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "~2.0.0",
|
"depd": "~2.0.0",
|
||||||
"on-finished": "~2.4.1",
|
"on-finished": "~2.3.0",
|
||||||
"on-headers": "~1.1.0"
|
"on-headers": "~1.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/morgan/node_modules/on-finished": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ee-first": "1.1.1"
|
||||||
},
|
},
|
||||||
"funding": {
|
"engines": {
|
||||||
"type": "opencollective",
|
"node": ">= 0.8"
|
||||||
"url": "https://opencollective.com/express"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
|
|
@ -1374,9 +1310,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/multer": {
|
"node_modules/multer": {
|
||||||
"version": "2.2.0",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/multer/-/multer-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz",
|
||||||
"integrity": "sha512-6rdyFg2kLrMh9Jee7/BMPuV9lEAd7lLW2YUpF9/YxR7njyoUwwQ0ZPh3TaIY50Sw6vlyD2HW3wGOkTS4P79xrQ==",
|
"integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"append-field": "^1.0.0",
|
"append-field": "^1.0.0",
|
||||||
|
|
@ -1463,14 +1399,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pg": {
|
"node_modules/pg": {
|
||||||
"version": "8.21.0",
|
"version": "8.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz",
|
||||||
"integrity": "sha512-AUP1EYJuHraQGsVoCQVIcM7TEJVGtDzxWtGFZd8rds9d+CCXlU5Js1rYgfLNvxy9iJrpHjGrRjoi/3BT9fRyiA==",
|
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pg-connection-string": "^2.13.0",
|
"pg-connection-string": "^2.12.0",
|
||||||
"pg-pool": "^3.14.0",
|
"pg-pool": "^3.13.0",
|
||||||
"pg-protocol": "^1.14.0",
|
"pg-protocol": "^1.13.0",
|
||||||
"pg-types": "2.2.0",
|
"pg-types": "2.2.0",
|
||||||
"pgpass": "1.0.5"
|
"pgpass": "1.0.5"
|
||||||
},
|
},
|
||||||
|
|
@ -1478,7 +1415,7 @@
|
||||||
"node": ">= 16.0.0"
|
"node": ">= 16.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"pg-cloudflare": "^1.4.0"
|
"pg-cloudflare": "^1.3.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"pg-native": ">=3.0.1"
|
"pg-native": ">=3.0.1"
|
||||||
|
|
@ -1490,16 +1427,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pg-cloudflare": {
|
"node_modules/pg-cloudflare": {
|
||||||
"version": "1.4.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
|
||||||
"integrity": "sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==",
|
"integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/pg-connection-string": {
|
"node_modules/pg-connection-string": {
|
||||||
"version": "2.13.0",
|
"version": "2.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.12.0.tgz",
|
||||||
"integrity": "sha512-EMnU9E2fSULdsbErBbMaXJvFeD9B4+nPcM3f+4lsiCR0BHLPrLVjv3DbyM2hgQQviKJaTWIRRTjKjWlHg3p2ig==",
|
"integrity": "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/pg-hstore": {
|
"node_modules/pg-hstore": {
|
||||||
|
|
@ -1524,18 +1461,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pg-pool": {
|
"node_modules/pg-pool": {
|
||||||
"version": "3.14.0",
|
"version": "3.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.13.0.tgz",
|
||||||
"integrity": "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==",
|
"integrity": "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"pg": ">=8.0"
|
"pg": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pg-protocol": {
|
"node_modules/pg-protocol": {
|
||||||
"version": "1.14.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz",
|
||||||
"integrity": "sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA==",
|
"integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/pg-types": {
|
"node_modules/pg-types": {
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,7 @@ router.post('/post', postLimiter, async (request, response, next) => {
|
||||||
isPidValid = false;
|
isPidValid = false;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Caught error when validating ${pid}:`, err.message || err);
|
isPidValid = false;
|
||||||
isPidValid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isPidValid) {
|
if (!isPidValid) {
|
||||||
|
|
|
||||||
83
main.py
83
main.py
|
|
@ -14,13 +14,11 @@ from routes.equipment import equipment_history
|
||||||
from routes.equipment import equipment
|
from routes.equipment import equipment
|
||||||
from services.boss_retrieval import process_boss_file
|
from services.boss_retrieval import process_boss_file
|
||||||
from routes import Ranking
|
from routes import Ranking
|
||||||
from routes import ranking_grabstats
|
|
||||||
from routes import twitter_link
|
from routes import twitter_link
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta
|
||||||
from sqlalchemy import delete
|
from sqlalchemy import delete
|
||||||
from config import BASE_DIR
|
from config import BASE_DIR
|
||||||
import yaml
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import subprocess
|
import subprocess
|
||||||
import signal
|
import signal
|
||||||
|
|
@ -33,7 +31,6 @@ JUDD_SERVER_JS = os.path.join(JUDD_CWD, "server.js")
|
||||||
JUDD_CMD = ["node", JUDD_SERVER_JS]
|
JUDD_CMD = ["node", JUDD_SERVER_JS]
|
||||||
|
|
||||||
judd_process = None
|
judd_process = None
|
||||||
skip_upcoming_reset = False
|
|
||||||
|
|
||||||
async def boss_worker_loop():
|
async def boss_worker_loop():
|
||||||
print("background worker started")
|
print("background worker started")
|
||||||
|
|
@ -46,78 +43,29 @@ async def boss_worker_loop():
|
||||||
await asyncio.sleep(3600)
|
await asyncio.sleep(3600)
|
||||||
|
|
||||||
async def weekly_rank_reset_loop():
|
async def weekly_rank_reset_loop():
|
||||||
global skip_upcoming_reset
|
|
||||||
print("weekly_rank_reset worker started")
|
print("weekly_rank_reset worker started")
|
||||||
|
while True:
|
||||||
FES_BOSS_PATH = os.path.join(BASE_DIR, "fes_boss.yaml")
|
now = datetime.now()
|
||||||
|
days_ahead = 6 - now.weekday()
|
||||||
def get_next_sunday_reset_time_utc():
|
|
||||||
now_utc = datetime.now(timezone.utc)
|
|
||||||
days_ahead = 6 - now_utc.weekday()
|
|
||||||
if days_ahead <= 0:
|
if days_ahead <= 0:
|
||||||
days_ahead += 7
|
days_ahead += 7
|
||||||
next_sunday_utc = now_utc + timedelta(days=days_ahead)
|
|
||||||
return next_sunday_utc.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
||||||
|
|
||||||
async def check_splatfest_schedule_loop():
|
next_sunday = now + timedelta(days=days_ahead)
|
||||||
global skip_upcoming_reset
|
next_run = next_sunday.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
target_reset_utc = get_next_sunday_reset_time_utc()
|
|
||||||
print(f"checking if a splatfest will be active at: {target_reset_utc.isoformat()}")
|
|
||||||
|
|
||||||
if os.path.exists(FES_BOSS_PATH):
|
wait_seconds = (next_run - now).total_seconds()
|
||||||
with open(FES_BOSS_PATH, "r", encoding="utf-8") as f:
|
print(f"Next ranking reset scheduled for: {next_run} (in {wait_seconds:.0f} seconds)")
|
||||||
fes_data = yaml.safe_load(f)
|
|
||||||
|
|
||||||
if fes_data and "Time" in fes_data:
|
|
||||||
start_time = datetime.fromisoformat(fes_data["Time"]["Start"])
|
|
||||||
end_time = datetime.fromisoformat(fes_data["Time"]["End"])
|
|
||||||
|
|
||||||
start_time_utc = start_time.astimezone(timezone.utc)
|
|
||||||
end_time_utc = end_time.astimezone(timezone.utc)
|
|
||||||
|
|
||||||
print(f"detected splatfest schedule: {start_time_utc.isoformat()} to {end_time_utc.isoformat()}")
|
|
||||||
|
|
||||||
if start_time_utc <= target_reset_utc <= end_time_utc:
|
|
||||||
skip_upcoming_reset = True
|
|
||||||
print("Splatfest detected in reset window")
|
|
||||||
else:
|
|
||||||
skip_upcoming_reset = False
|
|
||||||
print("No splatfest active in reset window, yay!!!")
|
|
||||||
else:
|
|
||||||
print("could not find yaml, defaulted to no fest")
|
|
||||||
skip_upcoming_reset = False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"failed to check fest schedule: {e}")
|
|
||||||
|
|
||||||
await asyncio.sleep(7200)
|
|
||||||
|
|
||||||
asyncio.create_task(check_splatfest_schedule_loop())
|
|
||||||
|
|
||||||
while True:
|
|
||||||
now_utc = datetime.now(timezone.utc)
|
|
||||||
next_run_utc = get_next_sunday_reset_time_utc()
|
|
||||||
wait_seconds = (next_run_utc - now_utc).total_seconds()
|
|
||||||
|
|
||||||
print(f"Next ranking reset scheduled for: {next_run_utc.isoformat()} (in {wait_seconds:.0f} seconds)")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await asyncio.sleep(wait_seconds)
|
await asyncio.sleep(wait_seconds)
|
||||||
|
|
||||||
print("ranking reset triggerred!")
|
print("Executing weekly ranking reset...")
|
||||||
|
with SessionLocal() as db:
|
||||||
if skip_upcoming_reset:
|
db.execute(delete(PlayerRank))
|
||||||
print("Reset skipped due to active splatfest")
|
db.commit()
|
||||||
else:
|
print("Ranking table cleared successfully.")
|
||||||
print("Executing weekly ranking reset...")
|
await FastAPICache.clear()
|
||||||
with SessionLocal() as db:
|
print("Cache cleared")
|
||||||
db.execute(delete(PlayerRank))
|
|
||||||
db.commit()
|
|
||||||
print("Ranking table cleared successfully.")
|
|
||||||
await FastAPICache.clear()
|
|
||||||
print("Cache cleared")
|
|
||||||
|
|
||||||
await asyncio.sleep(60)
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
|
|
@ -188,7 +136,6 @@ app.include_router(equipment_history.router, prefix="/api/v1")
|
||||||
app.include_router(equipment.router, prefix="/api/v1")
|
app.include_router(equipment.router, prefix="/api/v1")
|
||||||
app.include_router(Ranking.router, prefix="/api/v1")
|
app.include_router(Ranking.router, prefix="/api/v1")
|
||||||
app.include_router(twitter_link.router, prefix="/api/v1")
|
app.include_router(twitter_link.router, prefix="/api/v1")
|
||||||
app.include_router(ranking_grabstats.router, prefix="/api/v1")
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
uvicorn.run("main:app", host="0.0.0.0", port=settings.port, reload=False)
|
uvicorn.run("main:app", host="0.0.0.0", port=settings.port, reload=False)
|
||||||
|
|
|
||||||
|
|
@ -7,45 +7,45 @@ requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotated-doc==0.0.4",
|
"annotated-doc==0.0.4",
|
||||||
"annotated-types==0.7.0",
|
"annotated-types==0.7.0",
|
||||||
"anyio==4.14.0",
|
"anyio==4.13.0",
|
||||||
"argon2-cffi==25.1.0",
|
"argon2-cffi==25.1.0",
|
||||||
"argon2-cffi-bindings==25.1.0",
|
"argon2-cffi-bindings==25.1.0",
|
||||||
"certifi==2026.6.17",
|
"certifi==2026.4.22",
|
||||||
"cffi==2.0.0",
|
"cffi==2.0.0",
|
||||||
"charset-normalizer==3.4.7",
|
"charset-normalizer==3.4.7",
|
||||||
"click==8.4.1",
|
"click==8.3.3",
|
||||||
"colorama==0.4.6",
|
"colorama==0.4.6",
|
||||||
"cryptography==49.0.0",
|
"cryptography==46.0.7",
|
||||||
"fastapi==0.137.1",
|
"fastapi==0.136.1",
|
||||||
"fastapi-cache2==0.2.2",
|
"fastapi-cache2==0.2.2",
|
||||||
"greenlet==3.5.2",
|
"greenlet==3.4.0",
|
||||||
"h11==0.16.0",
|
"h11==0.16.0",
|
||||||
"httpcore==1.0.9",
|
"httpcore==1.0.9",
|
||||||
"httpx==0.28.1",
|
"httpx==0.28.1",
|
||||||
"idna==3.18",
|
"idna==3.13",
|
||||||
"oauthlib==3.3.1",
|
"oauthlib==3.3.1",
|
||||||
"oead==1.2.9.post4",
|
"oead==1.2.9.post4",
|
||||||
"pendulum==3.2.0",
|
"pendulum==3.2.0",
|
||||||
"psycopg2-binary==2.9.12",
|
"psycopg2-binary==2.9.12",
|
||||||
"pycparser==3.0",
|
"pycparser==3.0",
|
||||||
"pydantic==2.13.4",
|
"pydantic==2.13.3",
|
||||||
"pydantic-core==2.46.4",
|
"pydantic-core==2.46.4",
|
||||||
"pydantic-settings==2.14.1",
|
"pydantic-settings==2.14.0",
|
||||||
"python-dateutil==2.9.0.post0",
|
"python-dateutil==2.9.0.post0",
|
||||||
"python-dotenv==1.2.2",
|
"python-dotenv==1.2.2",
|
||||||
"python-multipart==0.0.32",
|
"python-multipart==0.0.27",
|
||||||
"pyyaml==6.0.3",
|
"pyyaml==6.0.3",
|
||||||
"requests==2.34.2",
|
"requests==2.33.1",
|
||||||
"requests-oauthlib==2.0.0",
|
"requests-oauthlib==2.0.0",
|
||||||
"six==1.17.0",
|
"six==1.17.0",
|
||||||
"sqlalchemy==2.0.51",
|
"sqlalchemy==2.0.49",
|
||||||
"starlette==1.3.1",
|
"starlette==1.0.0",
|
||||||
"tweepy==4.16.0",
|
"tweepy==4.16.0",
|
||||||
"typing-extensions==4.15.0",
|
"typing-extensions==4.15.0",
|
||||||
"typing-inspection==0.4.2",
|
"typing-inspection==0.4.2",
|
||||||
"tzdata==2026.2",
|
"tzdata==2026.2",
|
||||||
"urllib3==2.7.0",
|
"urllib3==2.6.3",
|
||||||
"uvicorn==0.49.0",
|
"uvicorn==0.46.0",
|
||||||
"jinja2==3.1.6",
|
"jinja2==3.1.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
"matchUpdateTypes": ["minor", "patch"],
|
||||||
"automerge": false
|
"automerge": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": ["major"],
|
"matchUpdateTypes": ["major"],
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ async def get_equipment_composite(request: Request, db: DBSession = Depends(get_
|
||||||
try:
|
try:
|
||||||
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
||||||
token_data = auth.get_token(user.username, decrypted_pass)
|
token_data = auth.get_token(user.username, decrypted_pass)
|
||||||
profile = auth.get_profile(token_data["access_token"])
|
profile = json.loads(auth.get_profile(token_data["token"]))
|
||||||
pid_val = int(profile.get("pid"))
|
pid_val = int(profile.get("pid"))
|
||||||
mii_name = profile.get("name", user.username)
|
mii_name = profile.get("name", user.username)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ async def get_history(request: Request, db: DBSession = Depends(get_db)):
|
||||||
try:
|
try:
|
||||||
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
||||||
token_data = auth.get_token(user.username, decrypted_pass)
|
token_data = auth.get_token(user.username, decrypted_pass)
|
||||||
profile = auth.get_profile(token_data["access_token"])
|
profile = json.loads(auth.get_profile(token_data["token"]))
|
||||||
pid_val = int(profile.get("pid"))
|
pid_val = int(profile.get("pid"))
|
||||||
print(f"Fetching History for PID: {pid_val}")
|
print(f"Fetching History for PID: {pid_val}")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@ async def get_my_profile(request: Request, db: DBSession = Depends(get_db)):
|
||||||
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
||||||
|
|
||||||
token_data = auth.get_token(user.username, decrypted_pass)
|
token_data = auth.get_token(user.username, decrypted_pass)
|
||||||
if not token_data or "access_token" not in token_data:
|
if not token_data or "token" not in token_data:
|
||||||
return RedirectResponse(url="/sign_in/")
|
return RedirectResponse(url="/sign_in/")
|
||||||
|
|
||||||
profile_data = auth.get_profile(token_data["access_token"])
|
profile_data = auth.get_profile(token_data["token"])
|
||||||
if not profile_data:
|
if not profile_data:
|
||||||
raise HTTPException(status_code=404, detail="Profile not found")
|
raise HTTPException(status_code=404, detail="Profile not found")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
|
||||||
from sqlalchemy.orm import Session as DBSession
|
|
||||||
from sqlalchemy import desc
|
|
||||||
from database import SessionLocal, PlayerRank, EquipmentLast
|
|
||||||
from fastapi_cache.decorator import cache
|
|
||||||
|
|
||||||
router = APIRouter()
|
|
||||||
|
|
||||||
def get_db():
|
|
||||||
db = SessionLocal()
|
|
||||||
try:
|
|
||||||
yield db
|
|
||||||
finally:
|
|
||||||
db.close()
|
|
||||||
|
|
||||||
@router.get("/leaderboard/getplayerstats/{pid}")
|
|
||||||
@cache(expire=60)
|
|
||||||
async def get_player_stats(pid: int, mode: int | None = None, db: DBSession = Depends(get_db)):
|
|
||||||
try:
|
|
||||||
query = (
|
|
||||||
db.query(PlayerRank, EquipmentLast)
|
|
||||||
.outerjoin(EquipmentLast, PlayerRank.PId == EquipmentLast.PId)
|
|
||||||
.filter(PlayerRank.PId == pid)
|
|
||||||
)
|
|
||||||
|
|
||||||
if mode is not None:
|
|
||||||
query = query.filter(PlayerRank.GameMode == mode)
|
|
||||||
|
|
||||||
result = query.first()
|
|
||||||
|
|
||||||
if not result:
|
|
||||||
raise HTTPException(status_code=404, detail="Player not found")
|
|
||||||
|
|
||||||
player, gear = result
|
|
||||||
|
|
||||||
player_data = {
|
|
||||||
"PId": player.PId,
|
|
||||||
"MiiName": player.MiiName,
|
|
||||||
"Rank": player.Rank,
|
|
||||||
"GameMode": player.GameMode,
|
|
||||||
"WinSum": player.WinSum,
|
|
||||||
"LoseSum": player.LoseSum,
|
|
||||||
"RankingScore": round(player.RankingScore, 2),
|
|
||||||
"weapon": gear.weapon if gear else None,
|
|
||||||
"headgear": gear.Gear_Head if gear else None,
|
|
||||||
"clothes": gear.Gear_Clothes if gear else None,
|
|
||||||
"shoes": gear.Gear_Shoes if gear else None,
|
|
||||||
}
|
|
||||||
|
|
||||||
if player.GameMode == 2:
|
|
||||||
top_100_query = (
|
|
||||||
db.query(PlayerRank.PId)
|
|
||||||
.order_by(desc(PlayerRank.FesPower))
|
|
||||||
.limit(100)
|
|
||||||
.all()
|
|
||||||
)
|
|
||||||
top_100_tuples = set(top_100_query)
|
|
||||||
|
|
||||||
is_top_100 = (player.PId,) in top_100_tuples
|
|
||||||
player_data["FesPower"] = player.FesPower
|
|
||||||
player_data["is_top_100_fes"] = is_top_100
|
|
||||||
else:
|
|
||||||
player_data["FesPower"] = None
|
|
||||||
player_data["is_top_100_fes"] = False
|
|
||||||
|
|
||||||
return player_data
|
|
||||||
|
|
||||||
except HTTPException as http_ex:
|
|
||||||
raise http_ex
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error fetching stats for player {pid}: {e}")
|
|
||||||
return {"error": str(e)}
|
|
||||||
|
|
@ -37,7 +37,7 @@ async def login(
|
||||||
try:
|
try:
|
||||||
print("fetching spfn token")
|
print("fetching spfn token")
|
||||||
data = auth.get_token(username, password)
|
data = auth.get_token(username, password)
|
||||||
if not data or "access_token" not in data:
|
if not data or "token" not in data:
|
||||||
print("auth failed")
|
print("auth failed")
|
||||||
return RedirectResponse(f"{auth_path}{sep}error=auth&username={username}", 303)
|
return RedirectResponse(f"{auth_path}{sep}error=auth&username={username}", 303)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ async def confirm_twitter(state: str, code: str, db: DBSession = Depends(get_db)
|
||||||
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
||||||
profile_auth = auth.get_token(user.username, decrypted_pass)
|
profile_auth = auth.get_token(user.username, decrypted_pass)
|
||||||
|
|
||||||
profile_response = auth.get_profile(profile_auth["access_token"])
|
profile_response = auth.get_profile(profile_auth["token"])
|
||||||
|
|
||||||
if isinstance(profile_response, str):
|
if isinstance(profile_response, str):
|
||||||
try:
|
try:
|
||||||
|
|
@ -149,7 +149,7 @@ async def get_twitter_status(request: Request, db: DBSession = Depends(get_db)):
|
||||||
try:
|
try:
|
||||||
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
||||||
profile_auth = auth.get_token(user.username, decrypted_pass)
|
profile_auth = auth.get_token(user.username, decrypted_pass)
|
||||||
profile_res = auth.get_profile(profile_auth["access_token"])
|
profile_res = auth.get_profile(profile_auth["token"])
|
||||||
|
|
||||||
if isinstance(profile_res, str):
|
if isinstance(profile_res, str):
|
||||||
profile_data = json.loads(profile_res)
|
profile_data = json.loads(profile_res)
|
||||||
|
|
@ -183,7 +183,7 @@ async def unlink_twitter(request: Request, db: DBSession = Depends(get_db)):
|
||||||
user = db.query(User).filter(User.username == db_session.username).first()
|
user = db.query(User).filter(User.username == db_session.username).first()
|
||||||
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
decrypted_pass = cipher.decrypt(user.spfn_pass_enc.encode()).decode()
|
||||||
profile_auth = auth.get_token(user.username, decrypted_pass)
|
profile_auth = auth.get_token(user.username, decrypted_pass)
|
||||||
profile_data = auth.get_profile(profile_auth["access_token"])
|
profile_data = auth.get_profile(profile_auth["token"])
|
||||||
|
|
||||||
if isinstance(profile_data, str):
|
if isinstance(profile_data, str):
|
||||||
profile_data = json.loads(profile_data)
|
profile_data = json.loads(profile_data)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
# Security Policy
|
|
||||||
|
|
||||||
Report security vulnerabilities through the security tab on this repo. Only vulnerabilities on the latest commit of any branch will be considered.
|
|
||||||
|
|
@ -1,41 +1,35 @@
|
||||||
import requests
|
import requests
|
||||||
from config import settings
|
import base64
|
||||||
from argon2 import PasswordHasher
|
from argon2 import PasswordHasher
|
||||||
|
|
||||||
API_URL = "https://account.spfn.net/api/v2"
|
API_URL = "https://account.spfn.net/api/v2"
|
||||||
CLIENT_ID = "splatnet"
|
|
||||||
CLIENT_SECRET = settings.account_client_secret
|
|
||||||
ph = PasswordHasher()
|
ph = PasswordHasher()
|
||||||
|
|
||||||
def hash_password(password: str):
|
def hash_password(password: str):
|
||||||
return ph.hash(password)
|
return ph.hash(password)
|
||||||
|
|
||||||
def get_token(username, password):
|
def verify_password(hashed: str, password: str):
|
||||||
url = f"{API_URL}/oauth2/generate_token"
|
try:
|
||||||
|
return ph.verify(hashed, password)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
payload = {
|
def get_token(username, password):
|
||||||
"grant_type": "password",
|
creds = f"{username} {password}"
|
||||||
"username": username,
|
encoded = base64.b64encode(creds.encode()).decode()
|
||||||
"password": password,
|
|
||||||
"client_id": CLIENT_ID,
|
|
||||||
"client_secret": CLIENT_SECRET
|
|
||||||
}
|
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"User-Agent": "chiyo & eri should lwk kiss..."
|
"Authorization": f"Basic {encoded}",
|
||||||
|
"User-Agent": "saturday & allison should lwk kiss..."
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.post(url, data=payload, headers=headers, timeout=10)
|
response = requests.get(f"{API_URL}/oauth2/generate_token", headers=headers, timeout=10)
|
||||||
return response.json() if response.ok else None
|
return response.json() if response.ok else None
|
||||||
|
|
||||||
def get_profile(token):
|
def get_profile(token):
|
||||||
url = f"{API_URL}/users/@me/profile"
|
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {token}",
|
"Authorization": f"Bearer {token}",
|
||||||
"User-Agent": "lets make the most of the night like were gonna die young!!"
|
"User-Agent": "every update im going to change this user agent because im bored!!"
|
||||||
}
|
}
|
||||||
|
response = requests.get(f"{API_URL}/users/@me/profile", headers=headers, timeout=10)
|
||||||
response = requests.get(url, headers=headers, timeout=10)
|
return response.text if response.ok else None
|
||||||
|
|
||||||
return response.json() if response.ok else None
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
# Support
|
|
||||||
|
|
||||||
For support, join [our discord](https://discord.gg/splatfestival).
|
|
||||||
Loading…
Reference in a new issue