diff --git a/.gitignore b/.gitignore index d3fed47..e939f62 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,4 @@ package-lock.json pnpm-lock.yaml .env data/* +ddnss/* \ No newline at end of file diff --git a/index.js b/index.js index d551f09..44b6e75 100644 --- a/index.js +++ b/index.js @@ -49,4 +49,4 @@ Server.use('/assets', express.static('static')) const elapsed = Date.now() - start log(`Took ${elapsed/1000} seconds to start the server!`) -Server.listen(process.env.PORT ?? 12345, () => log(`Server started and listening on port ${process.env.PORT}.`)) +Server.listen(process.env.PORT ?? 12345, () => log(`Server started and listening on port ${process.env.PORT}.`)) \ No newline at end of file diff --git a/libs/database/generate.js b/libs/database/generate.js index e843a5f..81251d8 100644 --- a/libs/database/generate.js +++ b/libs/database/generate.js @@ -166,13 +166,13 @@ export function generateDB() { `CREATE INDEX IF NOT EXISTS "idx_maps_categoryMap" ON "maps" ("category", "map")` ]) - skinDB.exec(` CREATE TABLE IF NOT EXISTS "skindata" ( "timestamp" INTEGER NOT NULL, "player" varchar(16) NOT NULL, "clan" varchar(12) NOT NULL, - "flag" INTEGER NOT NULL, + "flag" varchar(16) NOT NULL DEFAULT 'default', + "twFlag" INTEGER NOT NULL, "skin" varchar(16) NOT NULL, "useColor" INTEGER NOT NULL, "colorBodyRaw" INTEGER NOT NULL, diff --git a/libs/ddnss/countrycodes.json b/libs/ddnss/countrycodes.json new file mode 100644 index 0000000..f644362 --- /dev/null +++ b/libs/ddnss/countrycodes.json @@ -0,0 +1,257 @@ +{ + "-1":"default", + "901":"XEN", + "902":"XNI", + "903":"XSC", + "904":"XWA", + "905":"XEU", + "906":"XCA", + "737":"SS", + "4":"AF", + "248":"AX", + "8":"AL", + "12":"DZ", + "16":"AS", + "20":"AD", + "24":"AO", + "660":"AI", + "28":"AG", + "32":"AR", + "51":"AM", + "533":"AW", + "36":"AU", + "40":"AT", + "31":"AZ", + "44":"BS", + "48":"BH", + "50":"BD", + "52":"BB", + "112":"BY", + "56":"BE", + "84":"BZ", + "204":"BJ", + "60":"BM", + "64":"BT", + "68":"BO", + "535":"BQ", + "70":"BA", + "72":"BW", + "74":"BV", + "76":"BR", + "86":"IO", + "96":"BN", + "100":"BG", + "854":"BF", + "108":"BI", + "116":"KH", + "120":"CM", + "124":"CA", + "132":"CV", + "136":"KY", + "140":"CF", + "148":"TD", + "152":"CL", + "156":"CN", + "162":"CX", + "166":"CC", + "170":"CO", + "174":"KM", + "178":"CG", + "180":"CD", + "184":"CK", + "188":"CR", + "384":"CI", + "191":"HR", + "192":"CU", + "531":"CW", + "196":"CY", + "203":"CZ", + "208":"DK", + "262":"DJ", + "212":"DM", + "214":"DO", + "218":"EC", + "818":"EG", + "222":"SV", + "226":"GQ", + "232":"ER", + "233":"EE", + "231":"ET", + "238":"FK", + "234":"FO", + "242":"FJ", + "246":"FI", + "250":"FR", + "254":"GF", + "258":"PF", + "260":"TF", + "266":"GA", + "270":"GM", + "268":"GE", + "276":"DE", + "288":"GH", + "292":"GI", + "300":"GR", + "304":"GL", + "308":"GD", + "312":"GP", + "316":"GU", + "320":"GT", + "831":"GG", + "324":"GN", + "624":"GW", + "328":"GY", + "332":"HT", + "334":"HM", + "336":"VA", + "340":"HN", + "344":"HK", + "348":"HU", + "352":"IS", + "356":"IN", + "360":"ID", + "364":"IR", + "368":"IQ", + "372":"IE", + "833":"IM", + "376":"IL", + "380":"IT", + "388":"JM", + "392":"JP", + "832":"JE", + "400":"JO", + "398":"KZ", + "404":"KE", + "296":"KI", + "408":"KP", + "410":"KR", + "414":"KW", + "417":"KG", + "418":"LA", + "428":"LV", + "422":"LB", + "426":"LS", + "430":"LR", + "434":"LY", + "438":"LI", + "440":"LT", + "442":"LU", + "446":"MO", + "807":"MK", + "450":"MG", + "454":"MW", + "458":"MY", + "462":"MV", + "466":"ML", + "470":"MT", + "584":"MH", + "474":"MQ", + "478":"MR", + "480":"MU", + "175":"YT", + "484":"MX", + "583":"FM", + "498":"MD", + "492":"MC", + "496":"MN", + "499":"ME", + "500":"MS", + "504":"MA", + "508":"MZ", + "104":"MM", + "516":"NA", + "520":"NR", + "524":"NP", + "528":"NL", + "540":"NC", + "554":"NZ", + "558":"NI", + "562":"NE", + "566":"NG", + "570":"NU", + "574":"NF", + "580":"MP", + "578":"NO", + "512":"OM", + "586":"PK", + "585":"PW", + "275":"PS", + "591":"PA", + "598":"PG", + "600":"PY", + "604":"PE", + "608":"PH", + "612":"PN", + "616":"PL", + "620":"PT", + "630":"PR", + "634":"QA", + "638":"RE", + "642":"RO", + "643":"RU", + "646":"RW", + "652":"BL", + "654":"SH", + "659":"KN", + "662":"LC", + "663":"MF", + "666":"PM", + "670":"VC", + "882":"WS", + "674":"SM", + "678":"ST", + "682":"SA", + "686":"SN", + "688":"RS", + "690":"SC", + "694":"SL", + "702":"SG", + "534":"SX", + "703":"SK", + "705":"SI", + "90":"SB", + "706":"SO", + "710":"ZA", + "239":"GS", + "724":"ES", + "144":"LK", + "736":"SD", + "740":"SR", + "744":"SJ", + "748":"SZ", + "752":"SE", + "756":"CH", + "760":"SY", + "158":"TW", + "762":"TJ", + "834":"TZ", + "764":"TH", + "626":"TL", + "768":"TG", + "772":"TK", + "776":"TO", + "780":"TT", + "788":"TN", + "792":"TR", + "795":"TM", + "796":"TC", + "798":"TV", + "800":"UG", + "804":"UA", + "784":"AE", + "826":"GB", + "840":"US", + "581":"UM", + "858":"UY", + "860":"UZ", + "548":"VU", + "862":"VE", + "704":"VN", + "92":"VG", + "850":"VI", + "876":"WF", + "732":"EH", + "887":"YE", + "894":"ZM", + "716":"ZW" + } \ No newline at end of file diff --git a/libs/ddnss/handler.js b/libs/ddnss/handler.js index d105d32..5388a75 100644 --- a/libs/ddnss/handler.js +++ b/libs/ddnss/handler.js @@ -1,3 +1,5 @@ +import fs from 'fs' + import { exec } from 'child_process' import { skinDB } from '../database/init.js' import initLog from '../utils/log.js' @@ -5,10 +7,30 @@ import { download } from '../download/dowload.js' const log = initLog("DDNSS") +/** + * This function takes a Teeworlds coutry code and + * maps it to a two letter country code instead + * + * @param number Teeworlds country code + * + * @returns Two letter country code + */ +export function mapCountryCode(code) { + const codes = fs.readFileSync('./libs/ddnss/countrycodes.json') + const json = JSON.parse(codes) + + for (const country in json) { + if(country == code) + return json[country] + } + /* If none is found, just return default */ + return "default" +} + export async function ddnssStart() { const getServers = await download('https://ddnet.tw/status/index.json', "_RETURN_VALUE_") - const servers = await getServers.json() - + const servers = await JSON.parse(getServers) + log(`Found ${servers.length} online servers!`) for (const server of servers) { @@ -26,9 +48,6 @@ export async function ddnssStart() { log(`Connecting to server >> ${connection}`) await scrapeServer(`${connection}`) } - - // PLEASE!! - exec(`pkill -9 -f ddnss`) } function scrapeServer(server) { @@ -41,42 +60,43 @@ function scrapeServer(server) { try { const skinData = JSON.parse(stdout) - if (skinData === null) { - resolve() - return - } - + if (skinData === null) + return resolve() + + const stmt = skinDB.prepare + (` + INSERT INTO "skindata" VALUES + ( + $timestamp, + $player, + $clan, + $flag, + $twFlag, + $skin, + $useColor, + $colorBodyRaw, + $colorBodyHex, + $colorFeetRaw, + $colorFeetHex + ) + `) const currentTime = Date.now() - // TODO: Store statement once and reuse same statment. (whatever that means) - for (const entry of skinData) - skinDB.prepare(` - INSERT INTO "skindata" - ( - $timestamp, - $player, - $clan, - $flag, - $skin, - $useColor, - $colorBodyRaw, - $colorBodyHex, - $colorFeetRaw, - $ColorFeetHex - ) - `) - .run({ + + for (const entry of skinData) { + stmt.run({ timestamp: currentTime, player: entry.player, clan: entry.clan, - flag: entry.flag, + flag: mapCountryCode(entry.flag), + twFlag: entry.flag, skin: entry.skindata.skin, useColor: entry.skindata.useColor, colorBodyRaw: entry.skindata.colorBody.raw, colorBodyHex: entry.skindata.colorBody.hex, colorFeetRaw: entry.skindata.colorFeet.raw, - colorFeetHex: entry.skindata.colorFeet.hex, - }) - + colorFeetHex: entry.skindata.colorFeet.hex + }) + } } catch (e) { log(`Failed to handle ${server}!`) } diff --git a/libs/download/dowload.js b/libs/download/dowload.js index f3bebb1..e27fe2b 100644 --- a/libs/download/dowload.js +++ b/libs/download/dowload.js @@ -24,28 +24,30 @@ export function download(url, target) { url, data => { if (target === "_RETURN_VALUE_") { - let result + let result = "" data.on( 'data', chunk => result += chunk ) - + data.on( 'end', () => resolve(result) ) } - - const file = fs.createWriteStream(target) - - data.pipe(file) - + else { + const file = fs.createWriteStream(target) + data.pipe(file) + } data.on( 'end', () => { log(`Done with a download >> ${url}`) - file.close() + + if (!target === "_RETURN_VALUE_") + file.close() + resolve() } )