Initial commit
34
.gitignore
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
package-lock.json
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
59
README.md
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
Endpoints
|
||||||
|
|
||||||
|
/api/v1/codm/build Get details about a build
|
||||||
|
|
||||||
|
/api/v1/codm/melee Get details about a melee
|
||||||
|
|
||||||
|
api/v1/codm/perk Get details about a perk
|
||||||
|
|
||||||
|
/api/v1/codm/scorestreak Get details about a scorestreak
|
||||||
|
|
||||||
|
/api/v1/fun/8ball 8ball a question
|
||||||
|
|
||||||
|
/api/v1/fun/doublestruck Doublestruck a text
|
||||||
|
|
||||||
|
/api/v1/fun/fractur Fractur a text
|
||||||
|
|
||||||
|
/api/v1/fun/reverse Reverse a text
|
||||||
|
|
||||||
|
/api/v1/fun/superscript Superscript a text
|
||||||
|
|
||||||
|
/api/v1/image/alone Create a alone meme
|
||||||
|
|
||||||
|
/api/v1/image/awesome Create a awesome meme
|
||||||
|
|
||||||
|
/api/v1/image/bestmeme Create a bestmeme meme
|
||||||
|
|
||||||
|
/api/v1/image/busted Create a busted meme
|
||||||
|
|
||||||
|
/api/v1/image/communism Create a communism meme
|
||||||
|
|
||||||
|
/api/v1/image/gun Create a gun meme
|
||||||
|
|
||||||
|
/api/v1/image/mask Create a mask meme
|
||||||
|
|
||||||
|
/api/v1/image/moment Create a moment meme
|
||||||
|
|
||||||
|
/api/v1/image/pray Create a pray meme
|
||||||
|
|
||||||
|
/api/v1/image/pressplay Create a pressplay meme
|
||||||
|
|
||||||
|
/api/v1/image/rifleshoot Create a rifleshoot meme
|
||||||
|
|
||||||
|
/api/v1/image/robert Create a robert meme
|
||||||
|
|
||||||
|
/api/v1/image/saveonlyone Create a saveonlyone meme
|
||||||
|
|
||||||
|
/api/v1/image/toilet Create a toilet meme
|
||||||
|
|
||||||
|
/api/v1/image/vr Create a vr meme
|
||||||
|
|
||||||
|
/api/v1/image/whodidthis Create a whodidthis meme
|
||||||
|
|
||||||
|
/api/v1/rpc/json/[id] Get rich presence of user with json
|
||||||
|
|
||||||
|
/api/v1/rpc/[id] Get rich presence of user with image
|
||||||
|
|
||||||
|
/api/v1/server/[invite] Get server information based on invite code
|
||||||
|
|
||||||
|
/api/v1/shield/[user] Get user shield using shield.io
|
2504
db/codm/builds.json
Normal file
197
db/codm/melees.json
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Base Melee",
|
||||||
|
"value": "basemelee",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Knife",
|
||||||
|
"value": "knife",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Glow Stick",
|
||||||
|
"value": "glow Stick",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Karambit",
|
||||||
|
"value": "karambit",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Folding Knife",
|
||||||
|
"value": "foldingknife",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ice Axe",
|
||||||
|
"value": "iceaxe",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Wrench",
|
||||||
|
"value": "wrench",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sickle",
|
||||||
|
"value": "sickle",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "68",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chainsaw",
|
||||||
|
"value": "chainsaw",
|
||||||
|
"range": "1.2",
|
||||||
|
"swingsPerMin": "70",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Prizefighters",
|
||||||
|
"value": "prizefighters",
|
||||||
|
"range": "1.3",
|
||||||
|
"swingsPerMin": "96 (48 x2)",
|
||||||
|
"hitRegDelay": "183 (+200)",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Kali Sticks",
|
||||||
|
"value": "kalisticks",
|
||||||
|
"range": "1.5",
|
||||||
|
"swingsPerMin": "000 (00 x2)",
|
||||||
|
"hitRegDelay": "",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "650",
|
||||||
|
"dropTime": "267",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Machete",
|
||||||
|
"value": "machete",
|
||||||
|
"range": "1.6",
|
||||||
|
"swingsPerMin": "56",
|
||||||
|
"hitRegDelay": "267",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nunchucks",
|
||||||
|
"value": "nunchucks",
|
||||||
|
"range": "1.6",
|
||||||
|
"swingsPerMin": "51",
|
||||||
|
"hitRegDelay": "167",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Assault Knife",
|
||||||
|
"value": "assaultknife",
|
||||||
|
"range": "1.6",
|
||||||
|
"swingsPerMin": "43",
|
||||||
|
"hitRegDelay": "183",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Katana",
|
||||||
|
"value": "katana",
|
||||||
|
"range": "1.7",
|
||||||
|
"swingsPerMin": "55",
|
||||||
|
"hitRegDelay": "250",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Axe",
|
||||||
|
"value": "axe",
|
||||||
|
"range": "1.9",
|
||||||
|
"swingsPerMin": "45",
|
||||||
|
"hitRegDelay": "283",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bat",
|
||||||
|
"value": "bat",
|
||||||
|
"range": "1.9",
|
||||||
|
"swingsPerMin": "51",
|
||||||
|
"hitRegDelay": "400",
|
||||||
|
"sprintSpeed": "7.26",
|
||||||
|
"raiseTime": "",
|
||||||
|
"dropTime": "",
|
||||||
|
"image": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shovel",
|
||||||
|
"value": "shovel",
|
||||||
|
"range": "2",
|
||||||
|
"swingsPerMin": "55",
|
||||||
|
"hitRegDelay": "500",
|
||||||
|
"sprintSpeed": "7.26"
|
||||||
|
}
|
||||||
|
]
|
182
db/codm/perks.json
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "fastrecover",
|
||||||
|
"perk": "Fast Recover",
|
||||||
|
"effects": "\nReduces healing delay from 5 seconds to 3.3 seconds, Increases healing power from 20 per tick to 27 per tick but healing rate remains at 1 tick / second.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "persistence",
|
||||||
|
"perk": "Persistence",
|
||||||
|
"effects": "\nScorestreak progression no longer resets upon being killed. Applies to each scorestreak once per match.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flakjacket",
|
||||||
|
"perk": "Flak Jacket",
|
||||||
|
"effects": "\nReduce explosion and continous damage received by 35%.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skulker",
|
||||||
|
"perk": "Skulker",
|
||||||
|
"effects": "\nIncrease walking and strafing speed by 12%.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "agile",
|
||||||
|
"perk": "Agile",
|
||||||
|
"effects": "\nCurrently bugged so the advantage is insignificant, Previously, it reduces ADS time after sprinting by ?%. Reduce object vaulting time by ?%.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lightweight",
|
||||||
|
"perk": "Lightweight",
|
||||||
|
"effects": "\nIncrease sprinting speed by 5%. Nullify fall damage.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "restock",
|
||||||
|
"perk": "Restock",
|
||||||
|
"effects": "\nReplenishes all equipment every 25 seconds after use.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tactician",
|
||||||
|
"perk": "Tactician",
|
||||||
|
"effects": "\nSpawn with 1 extra piece of tactical equipment.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "overclock",
|
||||||
|
"perk": "Overclock",
|
||||||
|
"effects": "\nIncreases the charging speed of the Operator Skill.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "martydom",
|
||||||
|
"perk": "Martyrdom",
|
||||||
|
"effects": "\nDrops a live Frag Grenade upon death.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ironlungs",
|
||||||
|
"perk": "Iron Lungs",
|
||||||
|
"effects": "\nIncreases the breath hold time while using a sniper rifle.",
|
||||||
|
"type": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vulture",
|
||||||
|
"perk": "Vulture",
|
||||||
|
"effects": "\nCollect ammo equivalent to one magazine of weapon in hand from enemies killed.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "toughness",
|
||||||
|
"perk": "Toughness",
|
||||||
|
"effects": "\nReduce hit flinch by 60%.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tracker",
|
||||||
|
"perk": "Tracker",
|
||||||
|
"effects": "\nReveal enemy footsteps within the recent 4 seconds on the ground in bright red marks.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ghost",
|
||||||
|
"perk": "Ghost",
|
||||||
|
"effects": "\nCompletely invisible against Enemy UAVs, Advance UAVs will not reveal direction, Unmarked on enemy VTOLs & Predator Missile, Will not alert enemies using Hight Alert.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "coldblooded",
|
||||||
|
"perk": "Cold Blooded",
|
||||||
|
"effects": "\nGrant invisibility towards AI operated enemy scorestreaks.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hardwired",
|
||||||
|
"perk": "Hard Wired",
|
||||||
|
"effects": "\nDoes not trigger enemy tripmines, Provides immunity against enemy Counter UAVs and EMP effects. Reduce footstep mark duration for enemy Tracker users.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "quickfix",
|
||||||
|
"perk": "Quick Fix",
|
||||||
|
"effects": "\nWeapon kills and objective captures instantly activate health regeneration. Does not effect regeneration rate",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "amped",
|
||||||
|
"perk": "Amped",
|
||||||
|
"effects": "\nReduce drop and raise time of all weapons and equipment. (Weapon drop 250ms, raise 350ms).\nIncreased throwing spped of lethal and tactical equipment\nFaster reload speed for launchers.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "recon",
|
||||||
|
"perk": "Recon",
|
||||||
|
"effects": "\nAfter killing enemy, nearby enemies will be scanned & displayed on the minimap.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gungho",
|
||||||
|
"perk": "Gung-Ho",
|
||||||
|
"effects": "\nAllows sprinting while Hip Firing, Reloading & using Utilites.",
|
||||||
|
"type": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hardline",
|
||||||
|
"perk": "Hardline",
|
||||||
|
"effects": "\nIncrease all score income earned from kills by 25%.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "demoexpert",
|
||||||
|
"perk": "Demo Expert",
|
||||||
|
"effects": "\nIncrease all explosive damage dealt by 25%.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tacticalmask",
|
||||||
|
"perk": "Tactical Mask",
|
||||||
|
"effects": "\nReduce the duration of tactical equipment effects by 40%.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "alert",
|
||||||
|
"perk": "Alert",
|
||||||
|
"effects": "\nAmplify enemy footstep audio. Enemies moving within 3m radius will be shown with general direction on minimap.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "engineer",
|
||||||
|
"perk": "Engineer",
|
||||||
|
"effects": "\nReveals enemy equipment and scorestreaks. Grant ability to re-roll and sabotage care packages.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "deadsilence",
|
||||||
|
"perk": "Dead Silence",
|
||||||
|
"effects": "\nProvide silent movement when walking, crouching, strafing & proning. Reduce footstep audio towards Alert users by 50%.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel",
|
||||||
|
"perk": "Shrapnel",
|
||||||
|
"effects": "\nSpawn with 1 extra piece of lethal equipment. Explosive damage delays enemy health regeneration.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "highalert",
|
||||||
|
"perk": "High Alert",
|
||||||
|
"effects": "\nScreen will flash bright orange if spotted by enemies outside of your FOV. Grant ability to ping and reveal enemy positions in direct lines of sight by ADSing and aiming in their general direction.",
|
||||||
|
"type": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "launcherplus",
|
||||||
|
"perk": "Launcher Plus",
|
||||||
|
"effects": "\nSpawn with 1 extra round of reserve ammo for equipped launchers.",
|
||||||
|
"type": "blue"
|
||||||
|
}
|
||||||
|
]
|
244
db/codm/scorestreaks.json
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Shield Turret",
|
||||||
|
"value": "shieldturret",
|
||||||
|
"description": "A manual shielded turret that can be deployed on most surfaces.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 300,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936101283939643442/252.png",
|
||||||
|
"preview_video": "https://youtu.be/eXGgOqHHiRU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "UAV",
|
||||||
|
"value": "uav",
|
||||||
|
"description": "Unmanned Aerial Vehicle that reveals enemy locations on the minimap.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 400,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936101547983654963/240.png",
|
||||||
|
"preview_video": "https://youtu.be/ZAxzUCJ79SY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shock RC",
|
||||||
|
"value": "shockrc",
|
||||||
|
"description": "Detects nerby enemies and paralyzes them in a continous eletric shock.",
|
||||||
|
"special": "Immobilize Enemies for x Seconds",
|
||||||
|
"cost": 450,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936102080274366525/241.png",
|
||||||
|
"preview_video": "https://youtu.be/qJaB0sjVs_E"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hunter Killer Drone",
|
||||||
|
"value": "hunterkillerdrone",
|
||||||
|
"description": "Infantry deployed drone that seeks out an enemy vehicle.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 500,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936102287905013780/242.png",
|
||||||
|
"preview_video": "https://youtu.be/B1srk2tL_IQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Care Package",
|
||||||
|
"value": "carepackage",
|
||||||
|
"description": "Call in a care package containing one random scorestreak.",
|
||||||
|
"special": "Can be lethal if lands directly on enemies.",
|
||||||
|
"cost": 550,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936102675240587304/546.png",
|
||||||
|
"preview_video": "https://youtu.be/5GXfShLuqsE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Counter UAV",
|
||||||
|
"value": "cuav",
|
||||||
|
"description": "Jams enemy reconnaissance by temporarily disabiling the enemy minimap.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 600,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936102817473646683/243.png",
|
||||||
|
"preview_video": "https://youtu.be/E4u-R7-VYl0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "MQ-27 Dragonfire",
|
||||||
|
"value": "mq27dragonfire",
|
||||||
|
"description": "Use a drone to detect and eliminate enemies while it has power and ammo. It carries 3 infrared explosive probes.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 650,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936102962403639357/241.png",
|
||||||
|
"preview_video": "https://youtu.be/6hqXKctuVaw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SAM Turret",
|
||||||
|
"value": "samturret",
|
||||||
|
"description": "The SAM Turret is an unmanned weapon which automaticaly locks onto any aircraft scorestreaks and fires missiles to destroy them.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 660,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936103140695081010/582.png",
|
||||||
|
"preview_video": "https://youtu.be/z3_R47ojWm8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Predator Missile",
|
||||||
|
"value": "predatormissile",
|
||||||
|
"description": "Remote-controlled Predator Missile with a cluster bomb payload.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 700,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936103410552426506/238.png",
|
||||||
|
"preview_video": "https://youtu.be/NmXL8O1WZSg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hawk X3",
|
||||||
|
"value": "hawkx3",
|
||||||
|
"description": "Manually controlled drone with a machine gun as the weapon.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 750,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936103603872096266/latest.png",
|
||||||
|
"preview_video": "https://youtu.be/bV0h1lFWr50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sentry Gun",
|
||||||
|
"value": "sentrygun",
|
||||||
|
"description": "An unmanned weapon capable of autonomously acquiring and firing upon enemy targets through thermal detection.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 800,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936103868645920798/274.png",
|
||||||
|
"preview_video": "https://youtu.be/PU1YryF2hKo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Lightning Strike",
|
||||||
|
"value": "lightningstrike",
|
||||||
|
"description": "Launch a coordinated airstrike on three locations.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 850,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936103990578524200/239.png",
|
||||||
|
"preview_video": "https://youtu.be/3nXO_5TqfIY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Orbital Laser",
|
||||||
|
"value": "orbitallaser",
|
||||||
|
"description": "A powerful orbital laser that shoots down from the sky and moves along the route specified by the player. The laser can penetrate roofed structures and buildings if enemies try to hide inside.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 890,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936104097147396106/248.png",
|
||||||
|
"preview_video": "https://youtu.be"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "XS1 Goliath",
|
||||||
|
"value": "xs1goliath",
|
||||||
|
"description": "Call on an XS1 Goliath to equip powerful armor and a minigun with limitless ammo.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 900,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936104192454565898/279.png",
|
||||||
|
"preview_video": "https://youtu.be/EvEI7rzages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cluster Strike",
|
||||||
|
"value": "clusterstrike",
|
||||||
|
"description": "Bears down continous missile bombardment to a designated location.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 950,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936109477453778994/642.png",
|
||||||
|
"preview_video": "https://youtu.be/TIAsmBp5h0w"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chopper Gunner",
|
||||||
|
"value": "choppergunner",
|
||||||
|
"description": "Fire from the skies in a chopper with a gun that has unlimited ammo. Careful not to overheat!",
|
||||||
|
"special": "",
|
||||||
|
"cost": 980,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936106738686505031/Chopper_Gunner_model_CoDMobile.png",
|
||||||
|
"preview_video": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Stealth Chopper",
|
||||||
|
"value": "stealthchopper",
|
||||||
|
"description": "Call in an attacking helicopter to the battlefiled for armed support.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 1000,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936104637596053545/256.png",
|
||||||
|
"preview_video": "https://youtu.be/1FzfpScAA-o"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Swarm",
|
||||||
|
"value": "swarm",
|
||||||
|
"description": "Call in a swarm of lethal Hunter Killer drones.",
|
||||||
|
"special": "It calls in 3 Hunter Killer Drones at the same time.",
|
||||||
|
"cost": 1100,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936118754457292810/237.png",
|
||||||
|
"preview_video": "https://youtu.be/5OveS1_eH5Q"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Napalm",
|
||||||
|
"value": "napalm",
|
||||||
|
"description": "Scorch nearby enemies and fill the battlefield with smoke.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 1190,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936126606970351626/Napalm_model_CoDMobile.png",
|
||||||
|
"preview_video": "https://youtu.be/qy846hZx3bI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Advance UAV",
|
||||||
|
"value": "auav",
|
||||||
|
"description": "Orbital UAV that reveals the enemy's direction on the mini-map.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 1200,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936128249107460146/imgbin_northrop-grumman-b-2-spirit-canada-png.png",
|
||||||
|
"preview_video": "https://youtu.be/-I4LeQTmy3w"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "EMP Systems",
|
||||||
|
"value": "empsystems",
|
||||||
|
"description": "Disables all enemy electronics. All items in enemy HUD will be removed and field of vision will be affected. Enemies affected cannot use throwables, Scorestreaks of Operator Skills.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 1300,
|
||||||
|
"type": "assist",
|
||||||
|
"manual": false,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936128472181534780/256.png",
|
||||||
|
"preview_video": "https://youtu.be/gciYYZ1pZ1Y"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VTOL",
|
||||||
|
"value": "vtol",
|
||||||
|
"description": "Call in a VTOL gunship to provide air support.",
|
||||||
|
"special": "",
|
||||||
|
"cost": 1600,
|
||||||
|
"type": "lethal",
|
||||||
|
"manual": true,
|
||||||
|
"preview": "https://media.discordapp.net/attachments/936100721328275506/936128641446838312/1000.png",
|
||||||
|
"preview_video": "https://youtu.be/NADOtqFmXzI"
|
||||||
|
}
|
||||||
|
]
|
5954
db/codm/stats.json
Normal file
7
jsconfig.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
next.config.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
if (
|
||||||
|
process.env.LD_LIBRARY_PATH == null ||
|
||||||
|
!process.env.LD_LIBRARY_PATH.includes(
|
||||||
|
`${process.env.PWD}/node_modules/canvas/build/Release:`
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
process.env.LD_LIBRARY_PATH = `${
|
||||||
|
process.env.PWD
|
||||||
|
}/node_modules/canvas/build/Release:${process.env.LD_LIBRARY_PATH || ""}`;
|
||||||
|
}
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = nextConfig;
|
19
package.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "cath-api",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"canvas": "^2.6.1",
|
||||||
|
"discord.js": "^14.9.0",
|
||||||
|
"mongodb": "^5.1.0",
|
||||||
|
"next": "13.2.4",
|
||||||
|
"node-fetch": "^2.6.9",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
}
|
||||||
|
}
|
BIN
public/image/alone.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
public/image/bestmeme.jpg
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
public/image/busted.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
public/image/communism.jpg
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/image/gun.jpg
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
public/image/mask.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
public/image/moment.jpg
Normal file
After Width: | Height: | Size: 848 B |
BIN
public/image/pray.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
public/image/pressplay.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
public/image/rifleshoot.jpg
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
public/image/robert.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
public/image/saveonlyone.jpg
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
public/image/toilet.jpg
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
public/image/vr.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
public/image/whodidthis.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
3
src/pages/_app.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function App({ Component, pageProps }) {
|
||||||
|
return <Component {...pageProps} />;
|
||||||
|
}
|
13
src/pages/_document.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { Html, Head, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
26
src/pages/api/v1/codm/build.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import builds from "../../../../../db/codm/builds.json";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function melee(req, res) {
|
||||||
|
const cwts = req.query.cwts;
|
||||||
|
const cc = req.query.cc;
|
||||||
|
const tag = req.query.tag;
|
||||||
|
const auth = req.headers.authorization;
|
||||||
|
if (auth !== process.env.auth || !auth)
|
||||||
|
return res.status(401).send({ error: "Unauthorized", code: 401 });
|
||||||
|
else {
|
||||||
|
const obj = builds.find(
|
||||||
|
p =>
|
||||||
|
p.cwts == cwts &&
|
||||||
|
p.author.toLowerCase() == cc.toLowerCase() &&
|
||||||
|
p.tags.map(x => x.toLowerCase()).includes(tag.toLowerCase())
|
||||||
|
);
|
||||||
|
if (!obj)
|
||||||
|
return res.status(404).send({ error: "Build Not Found", code: 404 });
|
||||||
|
res.status(200).send(obj);
|
||||||
|
}
|
||||||
|
}
|
19
src/pages/api/v1/codm/melee.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import melees from "../../../../../db/codm/melees.json";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function melee(req, res) {
|
||||||
|
const name = req.query.name;
|
||||||
|
const auth = req.headers.authorization;
|
||||||
|
if (auth !== process.env.auth || !auth)
|
||||||
|
return res.status(401).send({ error: "Unauthorized", code: 401 });
|
||||||
|
else {
|
||||||
|
const obj = melees.find(p => p.value == name.toLowerCase());
|
||||||
|
if (!obj)
|
||||||
|
return res.status(404).send({ error: "Unknown Melee", code: 404 });
|
||||||
|
res.status(200).send(obj);
|
||||||
|
}
|
||||||
|
}
|
18
src/pages/api/v1/codm/perk.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import perks from "../../../../../db/codm/perks.json";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function perk(req, res) {
|
||||||
|
const name = req.query.name;
|
||||||
|
const auth = req.headers.authorization;
|
||||||
|
if (auth !== process.env.auth || !auth)
|
||||||
|
return res.status(401).send({ error: "Unauthorized", code: 401 });
|
||||||
|
else {
|
||||||
|
const obj = perks.find(p => p.name == name);
|
||||||
|
if (!obj) return res.status(404).send({ error: "Unknown Perk", code: 404 });
|
||||||
|
res.status(200).send(obj);
|
||||||
|
}
|
||||||
|
}
|
19
src/pages/api/v1/codm/scorestreak.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import scorestreaks from "../../../../../db/codm/scorestreaks.json";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function scorestreak(req, res) {
|
||||||
|
const name = req.query.name;
|
||||||
|
const auth = req.headers.authorization;
|
||||||
|
if (auth !== process.env.auth || !auth)
|
||||||
|
return res.status(401).send({ error: "Unauthorized", code: 401 });
|
||||||
|
else {
|
||||||
|
const obj = scorestreaks.find(p => p.value == name.toLowerCase());
|
||||||
|
if (!obj)
|
||||||
|
return res.status(404).send({ error: "Unknown Scorestreak", code: 404 });
|
||||||
|
res.status(200).send(obj);
|
||||||
|
}
|
||||||
|
}
|
36
src/pages/api/v1/fun/8ball.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function random8ball(req, res) {
|
||||||
|
const answers = [
|
||||||
|
"Maybe.",
|
||||||
|
"Certainly not.",
|
||||||
|
"I hope so.",
|
||||||
|
"Not in your wildest dreams.",
|
||||||
|
"There is a good chance.",
|
||||||
|
"Quite likely.",
|
||||||
|
"I think so.",
|
||||||
|
"I hope not.",
|
||||||
|
"I hope so.",
|
||||||
|
"Never!",
|
||||||
|
"Fuhgeddaboudit.",
|
||||||
|
"Ahaha! Really?!?",
|
||||||
|
"Pfft.",
|
||||||
|
"Sorry, bucko.",
|
||||||
|
"Hell, yes.",
|
||||||
|
"Hell to the no.",
|
||||||
|
"The future is bleak.",
|
||||||
|
"The future is uncertain.",
|
||||||
|
"I would rather not say.",
|
||||||
|
"Who cares?",
|
||||||
|
"Possibly.",
|
||||||
|
"Never, ever, ever.",
|
||||||
|
"There is a small chance.",
|
||||||
|
"Yes!",
|
||||||
|
];
|
||||||
|
const answered = answers[Math.floor(Math.random() * answers.length)];
|
||||||
|
res.status(200).send({ answer: answered });
|
||||||
|
}
|
61
src/pages/api/v1/fun/doublestruck.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function doublestruck(req, res) {
|
||||||
|
const texts = req.query.text;
|
||||||
|
if (!texts) return res.status(400).send({ error: "Missing Text", code: 400 });
|
||||||
|
var w = {
|
||||||
|
" ": " ",
|
||||||
|
0: "𝟘",
|
||||||
|
1: "𝟙",
|
||||||
|
2: "𝟚",
|
||||||
|
3: "𝟛",
|
||||||
|
4: "𝟜",
|
||||||
|
5: "𝟝",
|
||||||
|
6: "𝟞",
|
||||||
|
7: "𝟟",
|
||||||
|
8: "𝟠",
|
||||||
|
9: "𝟡",
|
||||||
|
"+": "+",
|
||||||
|
"-": "-",
|
||||||
|
a: "𝕒",
|
||||||
|
b: "𝕓",
|
||||||
|
c: "𝕔",
|
||||||
|
d: "𝕕",
|
||||||
|
e: "𝕖",
|
||||||
|
f: "𝕗",
|
||||||
|
g: "𝕘",
|
||||||
|
h: "𝕙",
|
||||||
|
i: "𝕚",
|
||||||
|
j: "𝕛",
|
||||||
|
k: "𝕜",
|
||||||
|
l: "𝕝",
|
||||||
|
m: "𝕞",
|
||||||
|
n: "𝕠",
|
||||||
|
o: "𝕡",
|
||||||
|
p: "𝕢",
|
||||||
|
r: "𝕣",
|
||||||
|
s: "𝕤",
|
||||||
|
t: "𝕥",
|
||||||
|
u: "𝕦",
|
||||||
|
v: "𝕧",
|
||||||
|
w: "𝕨",
|
||||||
|
x: "𝕩",
|
||||||
|
y: "𝕪",
|
||||||
|
z: "𝕫",
|
||||||
|
};
|
||||||
|
|
||||||
|
function toDoubleStruck(x) {
|
||||||
|
return x
|
||||||
|
.split("")
|
||||||
|
.map(c => {
|
||||||
|
if (c in w) return w[c];
|
||||||
|
return "";
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
res.status(200).send({ text: toDoubleStruck(texts) });
|
||||||
|
}
|
61
src/pages/api/v1/fun/fractur.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function fractur(req, res) {
|
||||||
|
const texts = req.query.text;
|
||||||
|
if (!texts) return res.status(400).send({ error: "Missing Text", code: 400 });
|
||||||
|
var w = {
|
||||||
|
" ": " ",
|
||||||
|
0: "օ",
|
||||||
|
1: "յ",
|
||||||
|
2: "շ",
|
||||||
|
3: "Յ",
|
||||||
|
4: "կ",
|
||||||
|
5: "Տ",
|
||||||
|
6: "ճ",
|
||||||
|
7: "Դ",
|
||||||
|
8: "Ց",
|
||||||
|
9: "գ",
|
||||||
|
"+": "+",
|
||||||
|
"-": "-",
|
||||||
|
a: "𝖆",
|
||||||
|
b: "𝖇",
|
||||||
|
c: "𝖈",
|
||||||
|
d: "𝖉",
|
||||||
|
e: "𝖊",
|
||||||
|
f: "𝖋",
|
||||||
|
g: "𝖌",
|
||||||
|
h: "𝖍",
|
||||||
|
i: "𝖎",
|
||||||
|
j: "𝖏",
|
||||||
|
k: "𝖐",
|
||||||
|
l: "𝖑",
|
||||||
|
m: "𝖒",
|
||||||
|
n: "𝖔",
|
||||||
|
o: "𝖕",
|
||||||
|
p: "𝖖",
|
||||||
|
r: "𝖗",
|
||||||
|
s: "𝖘",
|
||||||
|
t: "𝖙",
|
||||||
|
u: "𝖚",
|
||||||
|
v: "𝖛",
|
||||||
|
w: "𝖜",
|
||||||
|
x: "𝖝",
|
||||||
|
y: "𝖞",
|
||||||
|
z: "𝖟",
|
||||||
|
};
|
||||||
|
|
||||||
|
function tofractur(x) {
|
||||||
|
return x
|
||||||
|
.split("")
|
||||||
|
.map(c => {
|
||||||
|
if (c in w) return w[c];
|
||||||
|
return "";
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
res.status(200).send({ text: tofractur(texts) });
|
||||||
|
}
|
12
src/pages/api/v1/fun/reverse.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function reverse(req, res) {
|
||||||
|
const texts = req.query.text;
|
||||||
|
if (!texts) return res.status(400).send({ error: "Missing Text", code: 400 });
|
||||||
|
const reversed = texts.split("").reverse().join("");
|
||||||
|
res.status(200).send({ text: reversed });
|
||||||
|
}
|
61
src/pages/api/v1/fun/superscript.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default function superscript(req, res) {
|
||||||
|
const texts = req.query.text;
|
||||||
|
if (!texts) return res.status(400).send({ error: "Missing Text", code: 400 });
|
||||||
|
var w = {
|
||||||
|
" ": " ",
|
||||||
|
0: "⁰",
|
||||||
|
1: "¹",
|
||||||
|
2: "²",
|
||||||
|
3: "³",
|
||||||
|
4: "⁴",
|
||||||
|
5: "⁵",
|
||||||
|
6: "⁶",
|
||||||
|
7: "⁷",
|
||||||
|
8: "⁸",
|
||||||
|
9: "⁹",
|
||||||
|
"+": "⁺",
|
||||||
|
"-": "⁻",
|
||||||
|
a: "ᵃ",
|
||||||
|
b: "ᵇ",
|
||||||
|
c: "ᶜ",
|
||||||
|
d: "ᵈ",
|
||||||
|
e: "ᵉ",
|
||||||
|
f: "ᶠ",
|
||||||
|
g: "ᵍ",
|
||||||
|
h: "ʰ",
|
||||||
|
i: "ⁱ",
|
||||||
|
j: "ʲ",
|
||||||
|
k: "ᵏ",
|
||||||
|
l: "ˡ",
|
||||||
|
m: "ᵐ",
|
||||||
|
n: "ⁿ",
|
||||||
|
o: "ᵒ",
|
||||||
|
p: "ᵖ",
|
||||||
|
r: "ʳ",
|
||||||
|
s: "ˢ",
|
||||||
|
t: "ᵗ",
|
||||||
|
u: "ᵘ",
|
||||||
|
v: "ᵛ",
|
||||||
|
w: "ʷ",
|
||||||
|
x: "ˣ",
|
||||||
|
y: "ʸ",
|
||||||
|
z: "ᶻ",
|
||||||
|
};
|
||||||
|
|
||||||
|
function toSuperScript(x) {
|
||||||
|
return x
|
||||||
|
.split("")
|
||||||
|
.map(c => {
|
||||||
|
if (c in w) return w[c];
|
||||||
|
return "";
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
res.status(200).send({ text: toSuperScript(texts) });
|
||||||
|
}
|
25
src/pages/api/v1/image/alone.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function alone(req, res) {
|
||||||
|
try {
|
||||||
|
const query = req.query.image;
|
||||||
|
if (!query)
|
||||||
|
return res.json({ error: "Missing 'Image' Property", code: 400 });
|
||||||
|
const avatar = await loadImage(query);
|
||||||
|
const canvas = createCanvas(1100, 892);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
const background = await loadImage("public/image/alone.jpg");
|
||||||
|
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.drawImage(avatar, 480, 350, 205, 205);
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send({ error: e.stack, code: 400 });
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
28
src/pages/api/v1/image/bestmeme.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function bestmeme(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/bestmeme.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(966, 1145);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 693, 970, 127, 127);
|
||||||
|
ctx.drawImage(img, 114, 734, 239, 239);
|
||||||
|
ctx.drawImage(bg, 0, 0, 966, 1145);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
25
src/pages/api/v1/image/busted.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function busted(req, res) {
|
||||||
|
try {
|
||||||
|
const query = req.query.image;
|
||||||
|
if (!query)
|
||||||
|
return res.json({ error: "Missing 'Image' Property", code: 400 });
|
||||||
|
const avatar = await loadImage(query);
|
||||||
|
let bg = await loadImage("public/image/busted.jpg");
|
||||||
|
const canvas = createCanvas(1000, 1000);
|
||||||
|
const ctx = canvas.getContext(`2d`);
|
||||||
|
ctx.drawImage(avatar, 0, 0, 1000, 1000);
|
||||||
|
ctx.drawImage(bg, 0, 0, 1000, 1000);
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send({ error: e.stack, code: 400 });
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
26
src/pages/api/v1/image/communism.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function communism(req, res) {
|
||||||
|
try {
|
||||||
|
const query = req.query.image;
|
||||||
|
if (!query)
|
||||||
|
return res.json({ error: "Missing 'Image' Property", code: 400 });
|
||||||
|
const baseAvatar = await loadImage(query);
|
||||||
|
const overlayAvatar = await loadImage("public/image/communism.jpg");
|
||||||
|
const canvas = createCanvas(1024, 1024);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.globalAlpha = 0.3;
|
||||||
|
ctx.drawImage(baseAvatar, 0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.drawImage(overlayAvatar, 0, 0, 1024, 1024);
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send({ error: e.stack, code: 400 });
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/gun.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function gun(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/gun.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(550, 550);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 0, 0, 550, 550);
|
||||||
|
ctx.drawImage(bg, -70, 190, 350, 350);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/mask.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function mask(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/mask.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(1080, 960);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 64, 571, 269, 269);
|
||||||
|
ctx.drawImage(bg, 0, 0, 1080, 960);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
25
src/pages/api/v1/image/moment.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function moment(req, res) {
|
||||||
|
try {
|
||||||
|
const query = req.query.image;
|
||||||
|
if (!query)
|
||||||
|
return res.json({ error: "Missing 'Image' Property", code: 400 });
|
||||||
|
const canvas = createCanvas(500, 670);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
const background = await loadImage("public/image/moment.jpg");
|
||||||
|
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
|
||||||
|
const avatar = await loadImage(query);
|
||||||
|
ctx.drawImage(avatar, 150, 100, 205, 205);
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send({ error: e.stack, code: 400 });
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/pray.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function pray(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/pray.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(396, 275);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 214, 10, 143, 136);
|
||||||
|
ctx.drawImage(bg, 0, 0, 396, 275);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/pressplay.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function pressplay(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/pressplay.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(474, 474);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 218, 208, 228, 228);
|
||||||
|
ctx.drawImage(bg, 0, 0, 474, 474);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/rifleshoot.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function rifleshoot(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/rifleshoot.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(318, 299);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 55, 28, 118, 118);
|
||||||
|
ctx.drawImage(bg, 0, 0, 318, 299);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
30
src/pages/api/v1/image/robert.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function robert(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/robert.jpg");
|
||||||
|
const glasses = await loadImage("public/image/glasses.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(295, 406);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 50, 115, 53, 53);
|
||||||
|
ctx.drawImage(img, 218, 115, 53, 53);
|
||||||
|
ctx.drawImage(glasses, 62, 130, 36, 19);
|
||||||
|
ctx.drawImage(bg, 0, 0, 295, 406);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
39
src/pages/api/v1/image/saveonlyone.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function saveonlyone(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ message: "Missing 'Image' Property", error: 400 });
|
||||||
|
if (!req.query.image2)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ message: "Missing 'Image' Property", error: 400 });
|
||||||
|
if (!req.query.image3)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ message: "Missing 'Image' Property", error: 400 });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/saveonlyone.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const img2 = await loadImage(req.query.image2);
|
||||||
|
const img3 = await loadImage(req.query.image3);
|
||||||
|
const canvas = createCanvas(910, 799);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(img, 465, 135, 158, 158);
|
||||||
|
ctx.drawImage(img2, 729, 107, 158, 158);
|
||||||
|
ctx.drawImage(img3, 170, 478, 104, 104);
|
||||||
|
ctx.drawImage(bg, 0, 0, 910, 799);
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send({ error: e.stack, code: 400 });
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
25
src/pages/api/v1/image/toilet.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function toilet(req, res) {
|
||||||
|
try {
|
||||||
|
const query = req.query.image;
|
||||||
|
if (!query)
|
||||||
|
return res.json({ error: "Missing 'Image' Property", code: 400 });
|
||||||
|
const canvas = createCanvas(500, 670);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
const background = await loadImage("public/image/toilet.jpg");
|
||||||
|
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
|
||||||
|
const avatar = await loadImage(query);
|
||||||
|
ctx.drawImage(avatar, 135, 350, 205, 205);
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
res.status(400).send({ error: e.stack, code: 400 });
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/vr.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function vr(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/vr.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(780, 768);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 46, 409, 305, 305);
|
||||||
|
ctx.drawImage(bg, 0, 0, 780, 768);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
27
src/pages/api/v1/image/whodidthis.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next/dist/shared/lib/utils";
|
||||||
|
import { createCanvas, loadImage } from "canvas";
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {NextApiRequest} req
|
||||||
|
* @param {NextApiResponse} res
|
||||||
|
*/
|
||||||
|
export default async function whodidthis(req, res) {
|
||||||
|
if (!req.query.image)
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: true, message: "Missing 'Image' Property" });
|
||||||
|
try {
|
||||||
|
const bg = await loadImage("public/image/whodidthis.jpg");
|
||||||
|
const img = await loadImage(req.query.image);
|
||||||
|
const canvas = createCanvas(512, 512);
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
ctx.drawImage(img, 0, 109, 512, 295);
|
||||||
|
ctx.drawImage(bg, 0, 0, 512, 512);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/jpg");
|
||||||
|
return res.status(200).send(canvas.toBuffer());
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(400).send({ error: true, message: e.message });
|
||||||
|
}
|
||||||
|
}
|
371
src/pages/api/v1/rpc/[id].js
Normal file
|
@ -0,0 +1,371 @@
|
||||||
|
const {
|
||||||
|
DiscordAPIError,
|
||||||
|
Client,
|
||||||
|
Partials,
|
||||||
|
GatewayIntentBits,
|
||||||
|
} = require("discord.js");
|
||||||
|
const fetch = require("node-fetch");
|
||||||
|
const allowlistGames = [
|
||||||
|
"visual studio code",
|
||||||
|
"visual studio",
|
||||||
|
"atom",
|
||||||
|
"sublime text",
|
||||||
|
"adobe illustrator",
|
||||||
|
"adobe photoshop",
|
||||||
|
"adobe xd",
|
||||||
|
"adobe dimension",
|
||||||
|
"adobe after effects",
|
||||||
|
"vim",
|
||||||
|
"neovim",
|
||||||
|
"blender",
|
||||||
|
"autodesk 3ds max",
|
||||||
|
"aseprite",
|
||||||
|
"intellij idea ultimate",
|
||||||
|
"intellij idea community",
|
||||||
|
"phpstorm",
|
||||||
|
"jetbrains ide",
|
||||||
|
"youtube music",
|
||||||
|
"code",
|
||||||
|
];
|
||||||
|
const statusColors = {
|
||||||
|
online: "#43b581",
|
||||||
|
idle: "#faa61a",
|
||||||
|
dnd: "#f04747",
|
||||||
|
streaming: "#6441a5",
|
||||||
|
offline: "#555555",
|
||||||
|
};
|
||||||
|
|
||||||
|
const statusNames = {
|
||||||
|
online: "Online",
|
||||||
|
idle: "Away",
|
||||||
|
dnd: "Do Not Disturb",
|
||||||
|
streaming: "Streaming",
|
||||||
|
offline: "Offline",
|
||||||
|
};
|
||||||
|
function processText(input) {
|
||||||
|
input = input.length > 32 ? `${input.substring(0, 32)}...` : input;
|
||||||
|
return input
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function parsePresence(user) {
|
||||||
|
const username = processText(user.user.username);
|
||||||
|
let pfpImage =
|
||||||
|
"data:image/png;base64," +
|
||||||
|
(await fetch(
|
||||||
|
user.displayAvatarURL({
|
||||||
|
format: "jpg",
|
||||||
|
dynamic: true,
|
||||||
|
size: 512,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(res => res.buffer())
|
||||||
|
.then(buffer => buffer.toString("base64")));
|
||||||
|
|
||||||
|
const statuses = user.presence?.clientStatus;
|
||||||
|
if (!statuses) {
|
||||||
|
return {
|
||||||
|
username,
|
||||||
|
pfpImage,
|
||||||
|
status: "offline",
|
||||||
|
gameType: "Offline",
|
||||||
|
game: "",
|
||||||
|
details: "",
|
||||||
|
detailsImage: false,
|
||||||
|
state: "",
|
||||||
|
height: 97,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const status = statuses?.desktop || statuses?.mobile || statuses?.web;
|
||||||
|
const playingRichGame = user.presence.activities
|
||||||
|
.reverse()
|
||||||
|
.find(
|
||||||
|
e =>
|
||||||
|
allowlistGames.includes(e.name.toLowerCase()) && (e.details || e.state)
|
||||||
|
);
|
||||||
|
const playingGame = user.presence.activities
|
||||||
|
.reverse()
|
||||||
|
.find(
|
||||||
|
e =>
|
||||||
|
allowlistGames.includes(e.name.toLowerCase()) && !e.details && !e.state
|
||||||
|
);
|
||||||
|
const spotifyGame = user.presence.activities.find(
|
||||||
|
e => e.type == 2 && e.name == "Spotify"
|
||||||
|
);
|
||||||
|
const gameObject = spotifyGame || playingRichGame || playingGame;
|
||||||
|
|
||||||
|
if (!gameObject) {
|
||||||
|
return {
|
||||||
|
username,
|
||||||
|
pfpImage,
|
||||||
|
status,
|
||||||
|
gameType: "",
|
||||||
|
game: "",
|
||||||
|
details: "",
|
||||||
|
detailsImage: false,
|
||||||
|
state: "",
|
||||||
|
height: 97,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const game = processText(gameObject.name);
|
||||||
|
let gameType = game == "Spotify" ? "Listening to" : "Playing";
|
||||||
|
|
||||||
|
if (!gameObject.details && !gameObject.state) {
|
||||||
|
return {
|
||||||
|
username,
|
||||||
|
pfpImage,
|
||||||
|
status,
|
||||||
|
gameType,
|
||||||
|
game,
|
||||||
|
details: "",
|
||||||
|
detailsImage: false,
|
||||||
|
state: "",
|
||||||
|
height: 97,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var details = gameObject.details ? processText(gameObject.details) : "";
|
||||||
|
if (game == "IntelliJ IDEA Ultimate" || game == "IntelliJ IDEA Community")
|
||||||
|
details = game;
|
||||||
|
let detailsImage = false;
|
||||||
|
let detialsURL = "";
|
||||||
|
if (gameObject.assets && gameObject.assets.largeImage) {
|
||||||
|
if (gameObject.assets.largeImage.startsWith("mp:")) {
|
||||||
|
detialsURL = `https://media.discordapp.net/${gameObject.assets.largeImage.substring(
|
||||||
|
3
|
||||||
|
)}`;
|
||||||
|
} else {
|
||||||
|
detialsURL = `https://cdn.discordapp.com/app-assets/${gameObject.applicationId}/${gameObject.assets.largeImage}.png`;
|
||||||
|
if (game == "Spotify")
|
||||||
|
detialsURL = `https://i.scdn.co/image/${gameObject.assets.largeImage.replace(
|
||||||
|
"spotify:",
|
||||||
|
""
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
if (detialsURL)
|
||||||
|
detailsImage =
|
||||||
|
"data:image/png;base64," +
|
||||||
|
(await fetch(detialsURL)
|
||||||
|
.then(res => res.buffer())
|
||||||
|
.then(buffer => buffer.toString("base64")));
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = gameObject.state ? processText(gameObject.state) : "";
|
||||||
|
|
||||||
|
return {
|
||||||
|
username,
|
||||||
|
pfpImage,
|
||||||
|
status,
|
||||||
|
game,
|
||||||
|
gameType,
|
||||||
|
details,
|
||||||
|
detailsImage,
|
||||||
|
state,
|
||||||
|
height: 187,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
class Card {
|
||||||
|
constructor({
|
||||||
|
username,
|
||||||
|
pfpImage,
|
||||||
|
status,
|
||||||
|
game,
|
||||||
|
gameType,
|
||||||
|
details,
|
||||||
|
detailsImage,
|
||||||
|
state,
|
||||||
|
height,
|
||||||
|
}) {
|
||||||
|
this.username = username;
|
||||||
|
this.pfpImage = pfpImage;
|
||||||
|
this.status = status;
|
||||||
|
this.game = game;
|
||||||
|
this.gameType = gameType;
|
||||||
|
this.details = details;
|
||||||
|
this.detailsImage = detailsImage;
|
||||||
|
this.state = state;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
this.statusColor = statusColors[status];
|
||||||
|
|
||||||
|
if (!this.game) {
|
||||||
|
this.gameType = statusNames[status];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return `
|
||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="382" height="${
|
||||||
|
this.height
|
||||||
|
}" viewBox="0 0 382 ${this.height}">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.cls-1{
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-2 {
|
||||||
|
fill: #202225;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-3 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-11, .cls-3 {
|
||||||
|
fill: #fff;
|
||||||
|
font-family: SegoeUI-Bold, Segoe UI;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-4 {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-14, .cls-4 {
|
||||||
|
fill: #b3b5b8;
|
||||||
|
font-family: SegoeUI, Segoe UI;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-5 {
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-6 {
|
||||||
|
letter-spacing: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-7 {
|
||||||
|
clip-path: url(#clip-path);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-8 {
|
||||||
|
fill: ${this.statusColor};
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-9 {
|
||||||
|
fill: #2f3136;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-10 {
|
||||||
|
clip-path: url(#clip-path-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cls-11, .cls-14 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<clipPath id="clip-path">
|
||||||
|
<circle id="pfp-clip-shape" class="cls-1" cx="51" cy="48" r="31"/>
|
||||||
|
</clipPath>
|
||||||
|
<clipPath id="clip-path-2">
|
||||||
|
<rect id="details-image-clip-shape" class="cls-1" x="34" y="106" width="52" height="52" rx="8" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<rect id="base-shape" class="cls-2" width="382" height="${
|
||||||
|
this.height
|
||||||
|
}" rx="4"/>
|
||||||
|
<text id="username-text" class="cls-3" transform="translate(94.66 43.89)">${
|
||||||
|
this.username
|
||||||
|
}</text>
|
||||||
|
<g id="game-text">
|
||||||
|
<text class="cls-4" transform="translate(94.66 67.11)">${
|
||||||
|
this.gameType
|
||||||
|
} ${this.game}</text>
|
||||||
|
</g>
|
||||||
|
<g id="pfp-group">
|
||||||
|
<g id="pfp-clip-group">
|
||||||
|
<g class="cls-7">
|
||||||
|
<image id="pfp-image" width="481" height="481" transform="translate(20 17) scale(0.13)" xlink:href="${
|
||||||
|
this.pfpImage
|
||||||
|
}"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<circle id="status-outline" class="cls-2" cx="71.54" cy="68.54" r="10.46"/>
|
||||||
|
<circle id="status-color" class="cls-8" cx="71.5" cy="68.5" r="6.5"/>
|
||||||
|
</g>
|
||||||
|
<g id="details-group" ${
|
||||||
|
this.status == "offline" || !this.game || (!this.details && !this.state)
|
||||||
|
? 'display="none"'
|
||||||
|
: ""
|
||||||
|
}>
|
||||||
|
<rect id="base-details-shape" class="cls-9" x="20" y="94" width="342" height="76" rx="4"/>
|
||||||
|
<g id="details-image-clip-group">
|
||||||
|
<g class="cls-10">
|
||||||
|
${
|
||||||
|
this.detailsImage
|
||||||
|
? `<image id="details-image" width="128" height="128" transform="translate(34 106) scale(0.41)" xlink:href="${this.detailsImage}"/>`
|
||||||
|
: '<rect id="details-image" width="128" height="128" transform="translate(34 106) scale(0.41)" fill="#7289da" />'
|
||||||
|
}
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="details-top-text">
|
||||||
|
<text class="cls-11" transform="translate(95.66 126.57)">${
|
||||||
|
this.details
|
||||||
|
}</text>
|
||||||
|
</g>
|
||||||
|
<g id="details-bottom-text">
|
||||||
|
<text class="cls-14" transform="translate(95.66 144.57)">${
|
||||||
|
this.state
|
||||||
|
}</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>`;
|
||||||
|
}
|
||||||
|
// <image width="128" height="128" transform="translate(318 25) scale(0.35)" xlink:href="${this.gameImage}"/>
|
||||||
|
}
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
res.setHeader("Cache-Control", "public, max-age=30");
|
||||||
|
const client = new Client({
|
||||||
|
shards: "auto",
|
||||||
|
partials: [Partials.GuildMember],
|
||||||
|
intents: [
|
||||||
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildMembers,
|
||||||
|
GatewayIntentBits.GuildPresences,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
client.login(process.env.TOKEN).then(async () => {
|
||||||
|
const member = await client.guilds
|
||||||
|
.fetch(process.env.GUILD_ID)
|
||||||
|
.then(async guild => {
|
||||||
|
return await guild.members
|
||||||
|
.fetch({
|
||||||
|
user: req.query.id,
|
||||||
|
cache: false,
|
||||||
|
force: true,
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
client.destroy();
|
||||||
|
|
||||||
|
let card;
|
||||||
|
if (member instanceof DiscordAPIError) {
|
||||||
|
card = new Card({
|
||||||
|
username: "Error",
|
||||||
|
pfpImage:
|
||||||
|
"https://sparkcdnwus2.azureedge.net/sparkimageassets/XPDC2RH70K22MN-08afd558-a61c-4a63-9171-d3f199738e9f",
|
||||||
|
status: "online",
|
||||||
|
game: "Discord",
|
||||||
|
gameType: "Playing",
|
||||||
|
details: "Member Not Found",
|
||||||
|
detailsImage:
|
||||||
|
"https://sparkcdnwus2.azureedge.net/sparkimageassets/XPDC2RH70K22MN-08afd558-a61c-4a63-9171-d3f199738e9f",
|
||||||
|
state: "Join discord.gg/SbQHChmGcp",
|
||||||
|
height: 187,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
card = new Card(await parsePresence(member));
|
||||||
|
}
|
||||||
|
res.status(200).send(card.render());
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
148
src/pages/api/v1/rpc/json/[id].js
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
const {
|
||||||
|
DiscordAPIError,
|
||||||
|
Client,
|
||||||
|
Partials,
|
||||||
|
GatewayIntentBits,
|
||||||
|
} = require("discord.js");
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
const client = new Client({
|
||||||
|
shards: "auto",
|
||||||
|
partials: [Partials.GuildMember],
|
||||||
|
intents: [
|
||||||
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildMembers,
|
||||||
|
GatewayIntentBits.GuildPresences,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
client.login(process.env.TOKEN).then(async () => {
|
||||||
|
const member = await client.guilds
|
||||||
|
.fetch(process.env.GUILD_ID)
|
||||||
|
.then(async guild => {
|
||||||
|
return await guild.members
|
||||||
|
.fetch({
|
||||||
|
user: req.query.id,
|
||||||
|
cache: false,
|
||||||
|
force: true,
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return error;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
client.destroy();
|
||||||
|
const discord_user = {
|
||||||
|
username: member.user.username,
|
||||||
|
public_flags: member.user.flags,
|
||||||
|
id: member.user.id,
|
||||||
|
discriminator: member.user.discriminator,
|
||||||
|
avatar: member.user.avatar,
|
||||||
|
};
|
||||||
|
const discord_status = member?.presence?.status || "offline";
|
||||||
|
const spo_activity = member?.presence?.activities.find(
|
||||||
|
activity => activity.name == "Spotify"
|
||||||
|
);
|
||||||
|
let spotify = null;
|
||||||
|
if (spo_activity) {
|
||||||
|
spotify = {
|
||||||
|
timestamps: {
|
||||||
|
start: Date.parse(spo_activity.timestamps.start),
|
||||||
|
end: Date.parse(spo_activity.timestamps.end),
|
||||||
|
},
|
||||||
|
song: spo_activity.details,
|
||||||
|
artist: spo_activity.state,
|
||||||
|
album_art_url: `https://i.scdn.co/image/${spo_activity.assets.largeImage.slice(
|
||||||
|
8
|
||||||
|
)}`,
|
||||||
|
album: spo_activity.assets.largeText,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const activities = member?.presence?.activities.map(activity => {
|
||||||
|
if (activity.name == "Spotify") {
|
||||||
|
return {
|
||||||
|
type: activity.type,
|
||||||
|
timestamps: {
|
||||||
|
start: Date.parse(activity.timestamps.start),
|
||||||
|
end: Date.parse(activity.timestamps.end),
|
||||||
|
},
|
||||||
|
state: activity.state,
|
||||||
|
party: {
|
||||||
|
id: activity.party?.id,
|
||||||
|
},
|
||||||
|
name: activity.name,
|
||||||
|
id: activity.id,
|
||||||
|
flags: activity.flags,
|
||||||
|
details: activity.details,
|
||||||
|
created_at: activity.createdTimestamp,
|
||||||
|
assets: {
|
||||||
|
large_text: activity.assets?.largeText,
|
||||||
|
large_image: activity.assets?.largeImage,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let activity_obj = {};
|
||||||
|
activity.type != null ? (activity_obj["type"] = activity.type) : "";
|
||||||
|
activity.state ? (activity_obj["state"] = activity.state) : "";
|
||||||
|
activity.details ? (activity_obj["details"] = activity.details) : "";
|
||||||
|
activity.flags ? (activity_obj["flags"] = activity.flags) : "";
|
||||||
|
activity.name ? (activity_obj["name"] = activity.name) : "";
|
||||||
|
activity.id ? (activity_obj["id"] = activity.id) : "";
|
||||||
|
activity.createdTimestamp
|
||||||
|
? (activity_obj["timestamps"] = { start: activity.createdTimestamp })
|
||||||
|
: "";
|
||||||
|
activity.buttons.length != 0
|
||||||
|
? (activity_obj["buttons"] = activity.buttons)
|
||||||
|
: "";
|
||||||
|
activity.emoji
|
||||||
|
? (activity_obj["emoji"] = {
|
||||||
|
name: activity.emoji?.name,
|
||||||
|
id: activity.emoji?.id,
|
||||||
|
animated: activity.emoji?.animated,
|
||||||
|
})
|
||||||
|
: "";
|
||||||
|
activity.assets
|
||||||
|
? (activity_obj["assets"] = {
|
||||||
|
small_text: activity.assets?.smallText,
|
||||||
|
small_image: activity.assets?.smallImage,
|
||||||
|
large_text: activity.assets?.largeText,
|
||||||
|
large_image: activity.assets?.largeImage,
|
||||||
|
})
|
||||||
|
: "";
|
||||||
|
activity.applicationId
|
||||||
|
? (activity_obj["application_id"] = activity.applicationId)
|
||||||
|
: "";
|
||||||
|
|
||||||
|
return activity_obj;
|
||||||
|
});
|
||||||
|
const active_on_discord_web = member?.presence?.clientStatus?.web
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
const active_on_discord_mobile = member?.presence?.clientStatus?.mobile
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
const active_on_discord_desktop = member?.presence?.clientStatus?.desktop
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
if (member instanceof DiscordAPIError) {
|
||||||
|
resolve();
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.json({ success: false, message: "User not found" });
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
return res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
spotify,
|
||||||
|
discord_user,
|
||||||
|
discord_status,
|
||||||
|
activities,
|
||||||
|
active_on_discord_web,
|
||||||
|
active_on_discord_mobile,
|
||||||
|
active_on_discord_desktop,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
105
src/pages/api/v1/server/[invite].js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
// return a promise to avoid stalled requests
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let { logoColor, style, theme, presenceTheme, compact, invite } = req.query;
|
||||||
|
|
||||||
|
theme = theme || presenceTheme;
|
||||||
|
style = style || "for-the-badge";
|
||||||
|
|
||||||
|
async function getServerInfo() {
|
||||||
|
const apiResult = await fetch(
|
||||||
|
`https://discord.com/api/v10/invites/${invite}?with_counts=true&with_expiration=true`,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
}
|
||||||
|
).catch(e => console.error("[err]", e, Date.now()));
|
||||||
|
const serverInfo = await apiResult.json();
|
||||||
|
|
||||||
|
let renderData = {};
|
||||||
|
if (serverInfo.code === 10006) {
|
||||||
|
renderData = {
|
||||||
|
t: "Error",
|
||||||
|
p: "Unknown invite",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
renderData = {
|
||||||
|
t: serverInfo.guild.name,
|
||||||
|
p: `${serverInfo.approximate_member_count} members`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the shield from shields.io and returns it
|
||||||
|
async function makeShield() {
|
||||||
|
let { t, p } = await getServerInfo();
|
||||||
|
|
||||||
|
// a lookup table for the presence colors
|
||||||
|
const presenceColors = {
|
||||||
|
online: "43b581",
|
||||||
|
idle: "faa81a",
|
||||||
|
"do not disturb": "ed4245",
|
||||||
|
offline: "555",
|
||||||
|
};
|
||||||
|
|
||||||
|
// a lookup table for the themes
|
||||||
|
const themes = {
|
||||||
|
default: ["555", "5865F2"],
|
||||||
|
"default-inverted": ["5865F2", "555"],
|
||||||
|
clean: ["555", presenceColors[p]],
|
||||||
|
"clean-inverted": [`${presenceColors[p]}`, "555"],
|
||||||
|
discord: ["5865F2", presenceColors[p]],
|
||||||
|
"discord-inverted": [presenceColors[p], "5865F2"],
|
||||||
|
"full-presence": [presenceColors[p], presenceColors[p]],
|
||||||
|
gray: ["555", "555"],
|
||||||
|
grey: ["555", "555"],
|
||||||
|
blurple: ["5865F2", "5865F2"],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (logoColor) {
|
||||||
|
logoColor = logoColor === "presence" ? presenceColors[p] : logoColor;
|
||||||
|
} else {
|
||||||
|
logoColor = style === "social" ? "#5865F2" : "white";
|
||||||
|
}
|
||||||
|
|
||||||
|
const colors = themes[theme] || themes["default"];
|
||||||
|
|
||||||
|
let text;
|
||||||
|
// if compact is true, we set the text accordingly
|
||||||
|
if (compact) {
|
||||||
|
text = {
|
||||||
|
label: "",
|
||||||
|
message: encodeURIComponent(t),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
text = {
|
||||||
|
label: encodeURIComponent(t),
|
||||||
|
message: encodeURIComponent(p),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const shieldURL = `https://img.shields.io/static/v1?label=${text.label}&message=${text.message}&style=${style}&color=${colors[0]}&labelColor=${colors[1]}&logo=discord&logoColor=${logoColor}`;
|
||||||
|
const rawShield = await fetch(shieldURL);
|
||||||
|
const svgShield = await rawShield.text();
|
||||||
|
|
||||||
|
// fix the server name being capitalized
|
||||||
|
let svgShieldFix = svgShield.replace(new RegExp(t.toUpperCase(), "g"), t);
|
||||||
|
|
||||||
|
// make the server name bold
|
||||||
|
svgShieldFix = svgShieldFix.replace(
|
||||||
|
new RegExp(`fill="#fff">${t}</text>`, "g"),
|
||||||
|
`fill="#fff" font-weight="bold">${t}</text>`
|
||||||
|
);
|
||||||
|
|
||||||
|
res.setHeader("Cache-Control", "s-maxage=1200");
|
||||||
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
res.status(200).send(svgShieldFix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the function and resolve the promise
|
||||||
|
makeShield().then(() => {
|
||||||
|
resolve;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
142
src/pages/api/v1/shield/[user].js
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
const {
|
||||||
|
DiscordAPIError,
|
||||||
|
Client,
|
||||||
|
Partials,
|
||||||
|
GatewayIntentBits,
|
||||||
|
} = require("discord.js");
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
// return a promise to avoid stalled requests
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let { logoColor, style, theme, presenceTheme, compact, user, bot } =
|
||||||
|
req.query;
|
||||||
|
|
||||||
|
// presenceTheme is present for legacy purposes, theme should be used instead
|
||||||
|
theme = theme || presenceTheme;
|
||||||
|
style = style || "for-the-badge";
|
||||||
|
const client = new Client({
|
||||||
|
shards: "auto",
|
||||||
|
partials: [Partials.GuildMember],
|
||||||
|
intents: [
|
||||||
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildMembers,
|
||||||
|
GatewayIntentBits.GuildPresences,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
async function getUserInfo() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
client.login(process.env.TOKEN).then(async () => {
|
||||||
|
const member = await client.guilds
|
||||||
|
.fetch(process.env.GUILD_ID)
|
||||||
|
.then(async guild => {
|
||||||
|
return await guild.members
|
||||||
|
.fetch({
|
||||||
|
user: req.query.user,
|
||||||
|
cache: false,
|
||||||
|
force: true,
|
||||||
|
})
|
||||||
|
.catch(_ => {
|
||||||
|
return resolve({
|
||||||
|
t: "Error",
|
||||||
|
p: "Join discord.gg/SbQHChmGcp",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
client.destroy();
|
||||||
|
if (member instanceof DiscordAPIError) {
|
||||||
|
return resolve({
|
||||||
|
t: "Error",
|
||||||
|
p: "Join discord.gg/SbQHChmGcp",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let presence = member?.presence?.status || "offline";
|
||||||
|
const tag = member.user.tag;
|
||||||
|
if (presence == "dnd") {
|
||||||
|
presence = "do not disturb";
|
||||||
|
}
|
||||||
|
return resolve({ t: tag, p: presence });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the shield from shields.io and returns it
|
||||||
|
async function makeShield() {
|
||||||
|
let { t, p } = await getUserInfo();
|
||||||
|
|
||||||
|
// Quick temp overwrite
|
||||||
|
if (t === "Error") {
|
||||||
|
p = "Join discord.gg/SbQHChmGcp";
|
||||||
|
}
|
||||||
|
|
||||||
|
// a lookup table for the presence colors
|
||||||
|
const presenceColors = {
|
||||||
|
online: "3ba55d",
|
||||||
|
idle: "faa81a",
|
||||||
|
"do not disturb": "ed4245",
|
||||||
|
offline: "555",
|
||||||
|
};
|
||||||
|
|
||||||
|
// a lookup table for the themes
|
||||||
|
const themes = {
|
||||||
|
default: ["555", "5865F2"],
|
||||||
|
"default-inverted": ["5865F2", "555"],
|
||||||
|
clean: ["555", presenceColors[p]],
|
||||||
|
"clean-inverted": [`${presenceColors[p]}`, "555"],
|
||||||
|
discord: ["5865F2", presenceColors[p]],
|
||||||
|
"discord-inverted": [presenceColors[p], "5865F2"],
|
||||||
|
"full-presence": [presenceColors[p], presenceColors[p]],
|
||||||
|
gray: ["555", "555"],
|
||||||
|
grey: ["555", "555"],
|
||||||
|
blurple: ["5865F2", "5865F2"],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (logoColor) {
|
||||||
|
logoColor = logoColor === "presence" ? presenceColors[p] : logoColor;
|
||||||
|
} else {
|
||||||
|
logoColor = style === "social" ? "#5865F2" : "white";
|
||||||
|
}
|
||||||
|
|
||||||
|
const colors = themes[theme] || themes["default"];
|
||||||
|
|
||||||
|
let text;
|
||||||
|
// if compact is true, we set the text accordingly
|
||||||
|
if (compact) {
|
||||||
|
text = {
|
||||||
|
label: "",
|
||||||
|
message: encodeURIComponent(t),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
text = {
|
||||||
|
label: encodeURIComponent(t),
|
||||||
|
message: encodeURIComponent(p),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const shieldURL = `https://img.shields.io/static/v1?label=${text.label}&message=${text.message}&style=${style}&color=${colors[0]}&labelColor=${colors[1]}&logo=discord&logoColor=${logoColor}`;
|
||||||
|
const rawShield = await fetch(shieldURL);
|
||||||
|
const svgShield = await rawShield.text();
|
||||||
|
|
||||||
|
// fix the username and invite url being capitalized
|
||||||
|
let svgShieldFix = svgShield.replace(new RegExp(t.toUpperCase(), "g"), t);
|
||||||
|
svgShieldFix = svgShieldFix.replace(
|
||||||
|
new RegExp("HTTPS://DISCORD.GG/ZKSPFFWQDG", "g"),
|
||||||
|
"https://discord.gg/zkspfFwqDg"
|
||||||
|
);
|
||||||
|
|
||||||
|
// make the username bold
|
||||||
|
svgShieldFix = svgShieldFix.replace(
|
||||||
|
new RegExp(`fill="#fff">${t}</text>`, "g"),
|
||||||
|
`fill="#fff" font-weight="bold">${t}</text>`
|
||||||
|
);
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "image/svg+xml");
|
||||||
|
res.status(200).send(svgShieldFix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the function and resolve the promise
|
||||||
|
makeShield().then(() => {
|
||||||
|
resolve;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
33
src/pages/api/v1/skyblock.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
const { getItemNetworth } = require("skyhelper-networth");
|
||||||
|
const nbt = require("prismarine-nbt");
|
||||||
|
const parseNbt = require("util").promisify(nbt.parse);
|
||||||
|
async function decodeData(buffer) {
|
||||||
|
const parsedNbt = await parseNbt(Buffer.from(buffer, "base64"));
|
||||||
|
return nbt.simplify(parsedNbt);
|
||||||
|
}
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
if (req.method == "POST" || req.method == "GET" || req.method == "PUT") {
|
||||||
|
if (req.body == "") {
|
||||||
|
res.status(400).json({ error: "No body was provided" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(req.body);
|
||||||
|
let dat = req.body;
|
||||||
|
if (typeof dat !== "string" || typeof dat == "undefined") {
|
||||||
|
res.status(400).json({ error: "ByteData is not a string or undefined" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = await getItemNetworth((await decodeData(dat)).i[0], {
|
||||||
|
cache: true,
|
||||||
|
});
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch {
|
||||||
|
res.status(400).json({ error: "Invalid ByteData" });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res
|
||||||
|
.status(400)
|
||||||
|
.json({ error: "This endpoint only accepts GET, POST and PUT requests" });
|
||||||
|
}
|
||||||
|
}
|
41
src/pages/index.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import Head from "next/head";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>API</title>
|
||||||
|
</Head>
|
||||||
|
<p>Endpoints</p>
|
||||||
|
<p>/api/v1/codm/build Get details about a build</p>
|
||||||
|
<p>/api/v1/codm/melee Get details about a melee</p>
|
||||||
|
<p>api/v1/codm/perk Get details about a perk</p>
|
||||||
|
<p>/api/v1/codm/scorestreak Get details about a scorestreak</p>
|
||||||
|
<p>/api/v1/fun/8ball 8ball a question</p>
|
||||||
|
<p>/api/v1/fun/doublestruck Doublestruck a text</p>
|
||||||
|
<p>/api/v1/fun/fractur Fractur a text</p>
|
||||||
|
<p>/api/v1/fun/reverse Reverse a text</p>
|
||||||
|
<p>/api/v1/fun/superscript Superscript a text</p>
|
||||||
|
<p>/api/v1/image/alone Create a alone meme</p>
|
||||||
|
<p>/api/v1/image/awesome Create a awesome meme</p>
|
||||||
|
<p>/api/v1/image/bestmeme Create a bestmeme meme</p>
|
||||||
|
<p>/api/v1/image/busted Create a busted meme</p>
|
||||||
|
<p>/api/v1/image/communism Create a communism meme</p>
|
||||||
|
<p>/api/v1/image/gun Create a gun meme</p>
|
||||||
|
<p>/api/v1/image/mask Create a mask meme</p>
|
||||||
|
<p>/api/v1/image/moment Create a moment meme</p>
|
||||||
|
<p>/api/v1/image/pray Create a pray meme</p>
|
||||||
|
<p>/api/v1/image/pressplay Create a pressplay meme</p>
|
||||||
|
<p>/api/v1/image/rifleshoot Create a rifleshoot meme</p>
|
||||||
|
<p>/api/v1/image/robert Create a robert meme</p>
|
||||||
|
<p>/api/v1/image/saveonlyone Create a saveonlyone meme</p>
|
||||||
|
<p>/api/v1/image/toilet Create a toilet meme</p>
|
||||||
|
<p>/api/v1/image/vr Create a vr meme</p>
|
||||||
|
<p>/api/v1/image/whodidthis Create a whodidthis meme</p>
|
||||||
|
<p>/api/v1/rpc/json/[id] Get rich presence of user with json</p>
|
||||||
|
<p>/api/v1/rpc/[id] Get rich presence of user with image</p>
|
||||||
|
<p>/api/v1/server/[invite] Get server information based on invite code</p>
|
||||||
|
<p>/api/v1/shield/[user] Get user shield using shield.io</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|