{"version":3,"sources":["../../../src/utils/api/server.ts"],"sourcesContent":["import { type APIDefaults } from \".\";\nimport type { Get, Post } from \"./basic\";\n\nimport chalk from \"chalk\";\n\nexport namespace Server {\n  export interface Signature {\n    version: string;\n    countdown: boolean;\n    novault: boolean;\n    noceriad: boolean;\n    norichpresence: boolean;\n    noreplaydispute: boolean;\n    supporter_specialthanks_goal: number;\n    xp_multiplier: number;\n    catalog: {\n      supporter: {\n        price: number;\n        price_bulk: number;\n        price_gift: number;\n        price_gift_bulk: number;\n        bulk_after: number;\n        normal_price: number;\n        normal_price_bulk: number;\n        normal_price_gift: number;\n        normal_price_gift_bulk: number;\n        normal_bulk_after: number;\n      };\n      \"zenith-tower-ost\": {\n        price: number;\n        normal_price: number;\n      };\n    };\n    league_mm_roundtime_min: number;\n    league_mm_roundtime_max: number;\n    league_additional_settings: Record<string, any>;\n    league_season: {\n      current: string;\n      prev: string;\n      next: string | null;\n      next_at: string | null;\n      ranked: boolean;\n    };\n    zenith_duoisfree: boolean;\n    zenith_freemod: boolean;\n    zenith_cpu_count: number;\n    zenith_additional_settings: {\n      TEMP_zenith_grace: string;\n      messiness_timeout: number;\n    };\n    domain: string;\n    ch_domain: string;\n    mode: string;\n    sentry_enabled: boolean;\n    serverCycle: string;\n    domain_hash: string;\n    client: {\n      commit: {\n        id: string;\n        time: number;\n      };\n      branch: string;\n      build: {\n        id: string;\n        time: number;\n      };\n    };\n  }\n\n  export interface Environment {\n    stats: {\n      players: number;\n      users: number;\n      gamesplayed: number;\n      gametime: number;\n    };\n    signature: Signature;\n    vx: string;\n  }\n}\n\nexport const server = (get: Get, _: Post, options: APIDefaults) => {\n  const getDespool = async (endpoint: string, index: string) => {\n    const req = await fetch(\n      encodeURI(\n        `https://${endpoint}/spool?${Date.now()}-${index}-${Math.floor(1e6 * Math.random())}`\n      ),\n      {\n        method: \"GET\",\n        headers: {\n          // Authorization: `Bearer ${options.token}`,\n          \"User-Agent\": options.userAgent\n        }\n      }\n    );\n    const res = new Uint8Array(await req.arrayBuffer());\n\n    const parseSpoolData = (binary: Uint8Array) => {\n      const version = binary[0];\n      const flags = {\n        online: binary[1] & 0b10000000,\n        avoidDueToHighLoad: binary[1] & 0b01000000,\n        recentlyRestarted: binary[1] & 0b00100000,\n        backhaulDisrupted: binary[1] & 0b00010000,\n        unused5: binary[1] & 0b00001000,\n        unused6: binary[1] & 0b00000100,\n        unused7: binary[1] & 0b00000010,\n        unused8: binary[1] & 0b00000001\n      } as const;\n      const load = [0, 0, 0];\n      const latency = binary[5] * 2;\n\n      load[0] = (binary[2] / 0x100) * 4;\n      load[1] = (binary[3] / 0x100) * 4;\n      load[2] = (binary[4] / 0x100) * 4;\n\n      return {\n        version,\n        flags,\n        load,\n        latency,\n        str: `v${version} /${flags.avoidDueToHighLoad ? \"Av\" : \"\"}${flags.recentlyRestarted ? \"Rr\" : \"\"}${flags.backhaulDisrupted ? \"Bd\" : \"\"}/ ${load[0]}, ${load[1]}, ${load[2]}`\n      };\n    };\n\n    return parseSpoolData(res);\n  };\n\n  const findFastestAvailableSpool = async (\n    spools: { name: string; host: string; flag: string; location: string }[]\n  ): Promise<{\n    name: string;\n    host: string;\n    flag: string;\n    location: string;\n  }> => {\n    try {\n      return await Promise.any(\n        spools.map(async (s, index) => {\n          const spool = await getDespool(s.host, index.toString());\n          if (spool.flags.avoidDueToHighLoad || spool.flags.recentlyRestarted)\n            throw new Error(\"Spool is unstable\");\n          return s;\n        })\n      );\n    } catch {\n      console.log(\n        `${chalk.yellow(\"[🎀\\u2009Ribbon]\")}: All spools down or recently restarted (unstable). Falling back to root TETR.IO host.`\n      );\n    }\n    return {\n      name: \"tetr.io\",\n      host: \"tetr.io\",\n      flag: \"NL\",\n      location: \"osk\"\n    };\n  };\n\n  return {\n    environment: async (): Promise<Server.Environment> => {\n      const result = await get<Server.Environment>({\n        uri: \"server/environment\"\n      });\n\n      if (result.success === false) throw new Error(result.error.msg);\n      return result;\n    },\n    spool: async (useSpools: boolean) => {\n      const res = await get<{\n        endpoint: string;\n        spools: {\n          token: string;\n          spools: {\n            name: string;\n            host: string;\n            flag: string;\n            location: string;\n          }[];\n        } | null;\n      }>({\n        uri: \"server/ribbon\"\n      });\n\n      if (res.success === false) {\n        throw new Error(res.error.msg);\n      }\n\n      if (!useSpools || res.spools === null)\n        return {\n          host: \"tetr.io\",\n          endpoint: res.endpoint.replace(\"/ribbon/\", \"\"),\n          token: \"\"\n        };\n      else {\n        const lowestPingSpool = await findFastestAvailableSpool(\n          res.spools.spools\n        );\n        return {\n          host: lowestPingSpool.host,\n          endpoint: res.endpoint.replace(\"/ribbon/\", \"\"),\n          token: res.spools.token\n        };\n      }\n    }\n  };\n};\n"],"names":["chalk","server","get","_","options","getDespool","endpoint","index","req","fetch","encodeURI","Date","now","Math","floor","random","method","headers","userAgent","res","Uint8Array","arrayBuffer","parseSpoolData","binary","version","flags","online","avoidDueToHighLoad","recentlyRestarted","backhaulDisrupted","unused5","unused6","unused7","unused8","load","latency","str","findFastestAvailableSpool","spools","Promise","any","map","s","spool","host","toString","Error","console","log","yellow","name","flag","location","environment","result","uri","success","error","msg","useSpools","replace","token","lowestPingSpool"],"mappings":"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"}