Skip to content

Commit

Permalink
make parse methods
Browse files Browse the repository at this point in the history
Owen3H committed Oct 3, 2023
1 parent dbb0b26 commit 516d4d8
Showing 6 changed files with 111 additions and 52 deletions.
12 changes: 7 additions & 5 deletions src/classes/Nations.ts
Original file line number Diff line number Diff line change
@@ -14,11 +14,11 @@ class Nations implements Base {
}

/** @internal */
private mergeIfAurora = async (nation: Nation) => {
private mergeIfAurora = async (nation: any) => {
if (this.map.name === 'aurora') {
return { ...nation, ...await OfficialAPI.nation(nation.name) }
}

return nation
}

@@ -29,9 +29,11 @@ class Nations implements Base {
const existing = fn.getExisting(nations, nationList, 'name') as Nation[] | Nation
const isArr = existing instanceof Array

return isArr ?
Promise.all(existing.map(async n => await this.mergeIfAurora(n))) :
Promise.resolve(await this.mergeIfAurora(existing))
if (isArr) {
return await Promise.all(existing.map(async n => await this.mergeIfAurora(n)))
}

return await Promise.resolve(await this.mergeIfAurora(existing))
}

readonly all = async (towns?: Town[]) => {
118 changes: 77 additions & 41 deletions src/classes/OAPI.ts
Original file line number Diff line number Diff line change
@@ -11,49 +11,90 @@ import {
import { townyData } from '../utils/endpoint.js'
import { FetchError } from '../utils/errors.js'

class OfficialAPI {
static serverInfo = async () => await townyData('', 'v2') as RawServerInfo
const parseResident = (res: RawResident) => {
const obj: any = {}

obj.online = res.status.isOnline

static resident = async (name: string) => {
// TODO: Properly handle this case and implement an error.
if (!name) return
if (res.stats?.balance)
obj.balance = res.stats.balance

const res = await townyData(`/residents/${name}`) as RawResident
if (!res) throw new FetchError(`Could not fetch resident '${name}'. Received invalid response.`)
if (res.timestamps)
obj.timestamps = res.timestamps

const obj: any = {}
if (res.status?.isOnline)
obj.online = res.status.isOnline
if (res.strings?.username) obj.name = res.strings.username
if (res.strings?.title) obj.title = res.strings.title
if (res.strings?.surname) obj.surname = res.strings.surname

if (res.stats?.balance)
obj.balance = res.stats.balance
const affiliation = res.affiliation
if (affiliation?.town) obj.town = affiliation.town
if (affiliation?.nation) obj.nation = affiliation.nation

if (res.timestamps) obj.timestamps = res.timestamps
if (res.strings?.username) obj.name = res.strings.username
if (res.strings?.title) obj.title = res.strings.title
if (res.strings?.surname) obj.surname = res.strings.surname
if (res.ranks?.townRanks) obj.townRanks = res.ranks.townRanks
if (res.ranks?.nationRanks) obj.nationRanks = res.ranks.nationRanks

const affiliation = res.affiliation
if (affiliation?.town) obj.town = affiliation.town
if (affiliation?.nation) obj.nation = affiliation.nation
if (res.perms) {
const perms = res.perms
const rnaoPerms = perms.rnaoPerms

obj.perms = {
build: rnaoPerms.buildPerms,
destroy: rnaoPerms.destroyPerms,
switch: rnaoPerms.switchPerms,
itemUse: rnaoPerms.itemUsePerms,
flags: perms.flagPerms
}
}

if (res.ranks?.townRanks) obj.townRanks = res.ranks.townRanks
if (res.ranks?.nationRanks) obj.nationRanks = res.ranks.nationRanks
if (res.friends)
obj.friends = res.friends

const perms = res.perms
if (perms) {
const rnaoPerms = perms.rnaoPerms

obj.perms = {
build: rnaoPerms.buildPerms,
destroy: rnaoPerms.destroyPerms,
switch: rnaoPerms.switchPerms,
itemUse: rnaoPerms.itemUsePerms,
flags: perms.flagPerms
}
return obj as OAPIResident
}

const parseTown = (town: RawTown) => {
const rnao = town.perms.rnaoPerms
const flags = town.perms.flagPerms

const obj: any = {
...town,
name: town.strings.town,
nation: town.affiliation.nation,
founder: town.strings.founder,
created: town.timestamps?.registered,
joinedNation: town.timestamps?.joinedNationAt,
perms: {
build: rnao.buildPerms,
destroy: rnao.destroyPerms,
switch: rnao.switchPerms,
itemUse: rnao.itemUsePerms,
flags
}
}

delete obj.affiliation.nation
delete obj.timestamps

return obj as OAPIResident
delete obj.strings.town
delete obj.strings.founder

delete obj.perms.rnaoPerms
delete obj.perms.flagPerms

return obj as OAPITown
}

class OfficialAPI {
static serverInfo = async () => await townyData('', 'v2') as RawServerInfo

static resident = async (name: string) => {
// TODO: Properly handle this case and implement an error.
if (!name) return

const res = await townyData(`/residents/${name}`) as RawResident
if (!res) throw new FetchError(`Could not fetch resident '${name}'. Received invalid response.`)

return parseResident(res)
}

static town = async (name: string) => {
@@ -62,13 +103,7 @@ class OfficialAPI {
const town = await townyData(`/towns/${name}`) as RawTown
if (!town) return // TODO: Implement a proper error

return {
name: town.strings.town,
founder: town.strings.founder,
created: town.timestamps?.registered,
joinedNation: town.timestamps?.joinedNationAt,
...town
} as OAPITown
return parseTown(town)
}

static nation = async (name: string) => {
@@ -79,7 +114,8 @@ class OfficialAPI {

return {
name: nation.strings.nation,
created: nation.timestamps.registered
created: nation.timestamps.registered,
...nation
} as OAPINation
}
}
2 changes: 1 addition & 1 deletion src/classes/Residents.ts
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ class Residents implements Base {
}

/** @internal */
private mergeIfAurora = async (res: Resident) => {
private mergeIfAurora = async (res: any) => {
if (this.map.name === 'aurora') {
return { ...res, ...await OfficialAPI.resident(res.name) }
}
2 changes: 1 addition & 1 deletion src/classes/Towns.ts
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ class Towns implements Base {
}

/** @internal */
private mergeIfAurora = async (town: Town) => {
private mergeIfAurora = async (town: any) => {
if (this.map.name === 'aurora') {
return { ...town, ...await OfficialAPI.town(town.name) }
}
15 changes: 13 additions & 2 deletions src/types/oapi_v1.ts
Original file line number Diff line number Diff line change
@@ -5,17 +5,28 @@ type NestedOmit<T, K extends PropertyKey> = {
NestedOmit<T[P], K extends `${Exclude<P, symbol>}.${infer R}` ? R : never>
} extends infer O ? { [P in keyof O]: O[P] } : never;

export type ValidateShape<T, Shape> = T extends Shape ? Exclude<keyof T, keyof Shape> extends never ? T : never : never;

//#region Parsed
export type OAPITown = NestedOmit<RawTown,
"strings.town" |
"strings.founder" |
"timestamps.registered" |
"timestamps"
"timestamps" |
"perms.rnaoPerms" |
"perms.flagPerms"
> & {
name: string
nation: string
founder: string
created: number
joinedNation: number
perms: {
build: RawTownPerms
destroy: RawTownPerms
switch: RawTownPerms
itemUse: RawTownPerms
flags: RawFlagPerms
}
}

export type OAPINation = NestedOmit<RawNation,
14 changes: 12 additions & 2 deletions tests/oapi.test.ts
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import {
} from 'vitest'

import { OfficialAPI } from '../src/main'
import { OAPINation, OAPIResident, RawServerInfo } from '../src/types'
import { OAPINation, OAPIResident, OAPITown, RawServerInfo } from '../src/types'

describe('OfficialAPI', async () => {
it('can get valid towny/server info (v2)', async () => {
@@ -39,6 +39,16 @@ describe('OfficialAPI', async () => {
assertType<OAPINation>(nation)

expect(nation.name).toBe("Venice")
console.log(nation)
//console.log(nation)
})

it('can get valid nation (v1)', async () => {
const town = await OfficialAPI.town('venice')

expect(town).toBeDefined()
assertType<OAPITown>(town)

expect(town.name).toBe("Venice")
console.log(town)
})
})

0 comments on commit 516d4d8

Please sign in to comment.