diff --git a/index.html b/index.html new file mode 100644 index 0000000..d54feac --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +
Spineshatter
Item Level 73

Binds when picked up
Unique
Main HandMace
99 - 184 Damage Speed 2.60
(54.42 damage per second)
+9 Strength
+16 Stamina
Durability 105 / 105
Requires Level 60
Equip: Increased Defense +5.
Sell Price: 12 88 25
Dropped by: Razorgore the Untamed
\ No newline at end of file diff --git a/src/backend/Components/Item/ItemManager.ts b/src/backend/Components/Item/ItemManager.ts index 7caf9fd..f19f0ab 100644 --- a/src/backend/Components/Item/ItemManager.ts +++ b/src/backend/Components/Item/ItemManager.ts @@ -18,9 +18,9 @@ const parser = new xml2js.Parser(/* options */); @Injectable(IItemManager) export class ItemManager -implements FrontworkComponent, TableDefinitionExporter, IItemManager{ - name = "ItemManager" as "ItemManager"; - + implements FrontworkComponent, TableDefinitionExporter, IItemManager { + name = "ItemManager" as "ItemManager"; + @Inject(IAdmin) private admin: IAdmin @@ -52,16 +52,16 @@ implements FrontworkComponent, TableDefin this.setPriority, this.deletePriority ], - },{ + }, { name: 'reset' as 'reset', exportRPCs: () => [ this.wipeCurrencyAndItems ] }] - notifyRaid = async (raid:Raid | {id:number}) => { + notifyRaid = async (raid: Raid | { id: number }) => { const data = await this.raidManager.getRaidData(raid) - this.pubsub.publish(""+raid.id, data) + this.pubsub.publish("" + raid.id, data) await this.notifyRaids() } @@ -72,29 +72,30 @@ implements FrontworkComponent, TableDefin wipeCurrencyAndItems = async () => { await Promise.all([ this.userManager.wipeCurrency(), - Promise.all(_Tiers.map(tier => this.admin.knex(tier+'tokens').where(true).del())) + Promise.all(_Tiers.map(tier => this.admin.knex(tier + 'tokens').where(true).del())) ]) } - getItems = async () :Promise => await this.admin.knex.select('*').from('items') + getItems = async (): Promise => await this.admin.knex.select('*').from('items') - getItem = async(name:string):Promise => { - return await this.admin.knex('items').select('*').where('itemname','=',name).first() + getItem = async (name: string): Promise => { + return await this.admin.knex('items').select('*').where('itemname', '=', name).first() } - fetchItem = async (name:string):Promise => { - const res = await fetch('https://classic.wowhead.com/item='+name+'&xml'); - const txt = await res.text(); - const r = await parser.parseStringPromise(txt); + fetchItem = async (name: string): Promise => { + const res = await fetch('https://classic.wowhead.com/item=' + name + '&xml'); + const txt = await res.text(); + const r = await parser.parseStringPromise(txt); - try{ + try { return { itemname: r.wowhead.item[0].name[0], iconname: r.wowhead.item[0].icon[0]._, url: r.wowhead.item[0].link[0], quality: r.wowhead.item[0].quality[0]._, - } - }catch (e){ + tooltip: r.wowhead.item[0].htmlTooltip[0] + } + } catch (e) { console.log(name) throw e } @@ -102,9 +103,9 @@ implements FrontworkComponent, TableDefin getTableDefinitions(): TableDefiniton[] { return [ - ...['null',..._Tiers].map(tier => { + ...['null', ..._Tiers].map(tier => { return { - name: tier+'tokens', + name: tier + 'tokens', tableBuilder: (table) => { table.primary(['characterid', 'itemname']) table.integer("characterid") @@ -116,7 +117,7 @@ implements FrontworkComponent, TableDefin table.integer("level").defaultTo(1) } } - }),{ + }), { name: 'priorities', tableBuilder: (table) => { table.increments('id').primary() @@ -128,7 +129,7 @@ implements FrontworkComponent, TableDefin table.integer('modifier') table.string('description').nullable() } - },{ + }, { name: 'items', tableBuilder: (table) => { table.string('itemname').unique().notNullable().primary() @@ -136,52 +137,53 @@ implements FrontworkComponent, TableDefin table.string('url').notNullable() table.string('quality').defaultTo('Epic').notNullable() table.boolean('hidden').defaultTo(false).notNullable() + table.string('tooltip').notNullable() table.enu('tier', _Tiers).notNullable() } }] } - buyToken = async (usertoken: string, charactername:string, itemname:string, signup: Signup): Promise<(SRToken & Character & Item) | undefined> => { + buyToken = async (usertoken: string, charactername: string, itemname: string, signup: Signup): Promise<(SRToken & Character & Item) | undefined> => { const record = this.userManager.getUserRecordByToken(usertoken) const character = await this.character.getCharacterByName(charactername) - if(!record || !character || record.user.username !== character.username) return - + if (!record || !character || record.user.username !== character.username) return + const item = await this.getItem(itemname) - if(!item) return + if (!item) return const currency = await this.userManager.getCurrency(record.user, item.tier) - if(currency < 1) return + if (currency < 1) return const streaks = await this.getTokens(character, [item.tier], false) const activeTokens = await this.getTokens(character, [item.tier], true) await this.userManager.decrementCurrency(record.user, item.tier, 1) const modifier = await this.calculatePriorities(itemname, character) - + const tx = await this.admin.knex.transaction() - if(streaks.length > 0){ + if (streaks.length > 0) { const myStreak = streaks.find(token => token.itemname === itemname) - if(myStreak){ + if (myStreak) { //getLogger('ItemManager').debug('update signupid and increment level') await this.admin - .knex(item.tier+'tokens') - .transacting(tx) - .where({ - characterid: character.id, - itemname: item.itemname - }) - .update({ - signupid: signup.id, - level: myStreak.level+1 - }) + .knex(item.tier + 'tokens') + .transacting(tx) + .where({ + characterid: character.id, + itemname: item.itemname + }) + .update({ + signupid: signup.id, + level: myStreak.level + 1 + }) } //getLogger('ItemManager').debug('delete streaks') await Promise.all(streaks.map(async s => await this.admin - .knex(item.tier+'tokens') + .knex(item.tier + 'tokens') .transacting(tx) .where({ itemname: s.itemname, @@ -191,179 +193,179 @@ implements FrontworkComponent, TableDefin .del() )) - if(myStreak){ + if (myStreak) { await tx.commit() - await this.notifyRaid({id: signup.raidid}) + await this.notifyRaid({ id: signup.raidid }) return await this.getToken(character, item) } } const matchingReserve = activeTokens.find(token => token.itemname === itemname) - if(matchingReserve){ + if (matchingReserve) { //getLogger('ItemManager').debug('upgrade reserve') await this.admin - .knex(item.tier+'tokens') - .transacting(tx) - .increment('level') - .where({ - signupid: signup.id, - characterid: character.id, - itemname: item.itemname - }) - }else{ + .knex(item.tier + 'tokens') + .transacting(tx) + .increment('level') + .where({ + signupid: signup.id, + characterid: character.id, + itemname: item.itemname + }) + } else { //getLogger('ItemManager').debug('new reserve') await this.admin - .knex(item.tier+'tokens') - .transacting(tx) - .insert({ - characterid: character.id, - itemname: item.itemname, - level: 1+modifier, - signupid: signup.id - }) + .knex(item.tier + 'tokens') + .transacting(tx) + .insert({ + characterid: character.id, + itemname: item.itemname, + level: 1 + modifier, + signupid: signup.id + }) } await tx.commit() - await this.notifyRaid({id: signup.raidid}) + await this.notifyRaid({ id: signup.raidid }) return await this.getToken(character, item) } - getAllPriorities = async() :Promise<(SRPriority & Spec & Item)[]> => this.admin - .knex('priorities as p') - .join('items as i', 'p.itemname', '=', 'i.itemname') - .leftJoin('specs as s', 'p.specid', '=', 's.id') - .select('*') + getAllPriorities = async (): Promise<(SRPriority & Spec & Item)[]> => this.admin + .knex('priorities as p') + .join('items as i', 'p.itemname', '=', 'i.itemname') + .leftJoin('specs as s', 'p.specid', '=', 's.id') + .select('*') - deletePriority = async(priority:SRPriority) : Promise => { + deletePriority = async (priority: SRPriority): Promise => { await this.admin.knex('priorities') - .where(priority) - .del() + .where(priority) + .del() } - setPriority = async(itemname:string, priority: SRPriority) : Promise => { + setPriority = async (itemname: string, priority: SRPriority): Promise => { const item = await this.getItem(itemname) - + await this.admin - .knex('priorities') - .insert({ - itemname: item.itemname, - ...priority - }) + .knex('priorities') + .insert({ + itemname: item.itemname, + ...priority + }) } - getPriorities = async(itemname:string) : Promise => { + getPriorities = async (itemname: string): Promise => { return await this.admin - .knex('priorities as p') - .where('p.itemname', '=', itemname) - .select('*') + .knex('priorities as p') + .where('p.itemname', '=', itemname) + .select('*') } - calculatePriorities = async (itemname: string, character:Character):Promise=> { - const rules : SRPriority[] = await this.admin - .knex('priorities as p') - .select('*') - .join('items as i', 'i.itemname', '=', 'p.itemname') - .where('p.itemname', '=', itemname) + calculatePriorities = async (itemname: string, character: Character): Promise => { + const rules: SRPriority[] = await this.admin + .knex('priorities as p') + .select('*') + .join('items as i', 'i.itemname', '=', 'p.itemname') + .where('p.itemname', '=', itemname) return rules.map(rule => { - if(rule.specid && rule.race){ - if(rule.specid === character.specid && rule.race === character.race) + if (rule.specid && rule.race) { + if (rule.specid === character.specid && rule.race === character.race) return rule.modifier else return 0 } - if(rule.specid){ - if(rule.specid === character.specid) + if (rule.specid) { + if (rule.specid === character.specid) return rule.modifier else return 0 } - if(rule.race){ - if(rule.race === character.race) + if (rule.race) { + if (rule.race === character.race) return rule.modifier else return 0 } return 0 - }).reduce((prev, curr) => prev+curr, 0) + }).reduce((prev, curr) => prev + curr, 0) } - getToken = async (character:Character, item:Item, valid=true): Promise<(SRToken & Character & Item) | undefined>=> { + getToken = async (character: Character, item: Item, valid = true): Promise<(SRToken & Character & Item) | undefined> => { return await this.admin - .knex(item.tier+'tokens as t') - .select('*') - .join('characters as c', 'c.id', '=', 't.characterid') - .join('items as i', 'i.itemname', '=', 't.itemname') - .where({ - characterid: character.id, - "i.itemname": item.itemname - }) - .andWhere(function(){ - if(valid){ - this.whereNotNull('t.signupid') - }else{ - this.whereNull('t.signupid') - } - }) - .first() - } - - getTokens = async (character:Character, tiers:Tiers[], valid=true) : Promise<(SRToken & Character & Item)[]> => { - const ret = await Promise.all(tiers.map(async tier => { - return await this.admin - .knex(tier+'tokens as t') + .knex(item.tier + 'tokens as t') .select('*') .join('characters as c', 'c.id', '=', 't.characterid') .join('items as i', 'i.itemname', '=', 't.itemname') .where({ characterid: character.id, + "i.itemname": item.itemname }) - .andWhere(function(){ - if(valid){ + .andWhere(function () { + if (valid) { this.whereNotNull('t.signupid') - }else{ + } else { this.whereNull('t.signupid') } }) + .first() + } + + getTokens = async (character: Character, tiers: Tiers[], valid = true): Promise<(SRToken & Character & Item)[]> => { + const ret = await Promise.all(tiers.map(async tier => { + return await this.admin + .knex(tier + 'tokens as t') + .select('*') + .join('characters as c', 'c.id', '=', 't.characterid') + .join('items as i', 'i.itemname', '=', 't.itemname') + .where({ + characterid: character.id, + }) + .andWhere(function () { + if (valid) { + this.whereNotNull('t.signupid') + } else { + this.whereNull('t.signupid') + } + }) })) return ret.flat() } - countItems = async() :Promise => { + countItems = async (): Promise => { const count = await this.admin - .knex('items') - .count('*'); - + .knex('items') + .count('*'); + return count[0]['count(*)'] } private initialized = false initialize = async () => { - if(this.initialized) return - this.initialized = true - + if (this.initialized) return + this.initialized = true + const itemTiers = allItems const countCache = await this.countItems() - if(countCache != Object.values(itemTiers).flat().length){ + if (countCache != Object.values(itemTiers).flat().length) { await Promise.all( Object.entries(itemTiers) - .map((kv) => Promise.all( - kv[1].map(i => this.fetchItem(i) - .then(item => - this.admin - .knex('items') - .insert({ - tier: kv[0], - ...item - }).catch(() => {}) + .map((kv) => Promise.all( + kv[1].map(i => this.fetchItem(i) + .then(item => + this.admin + .knex('items') + .insert({ + tier: kv[0], + ...item + }).catch(() => { }) + ) ) - ) - )) + )) ) } } diff --git a/src/backend/Types/Types.ts b/src/backend/Types/Types.ts index e5cebba..271b6c3 100644 --- a/src/backend/Types/Types.ts +++ b/src/backend/Types/Types.ts @@ -87,6 +87,7 @@ export type Item = { url:string quality:string hidden:boolean + tooltip: string tier: Tiers } diff --git a/src/frontend/src/app/frontcraft/pages/character/character.component.ts b/src/frontend/src/app/frontcraft/pages/character/character.component.ts index 66ea5d7..997e999 100644 --- a/src/frontend/src/app/frontcraft/pages/character/character.component.ts +++ b/src/frontend/src/app/frontcraft/pages/character/character.component.ts @@ -25,7 +25,7 @@ export class FrontcraftCharacterComponent implements OnInit{ gear1:string[] = [] boss2= {} - gear2:string[] = [] + gear2:Item[] = [] constructor( private api: ApiService, @@ -50,7 +50,7 @@ export class FrontcraftCharacterComponent implements OnInit{ - fetch(this.dataLink).then(raw => raw.json().then((json) => { + fetch(this.dataLink).then(raw => raw.json().then(async (json) => { if(json.length < 1) return const data = json[0] @@ -58,18 +58,14 @@ export class FrontcraftCharacterComponent implements OnInit{ name: data.encounterName, date: data.startTime } - this.gear2 = data.gear.map(item => {return { - itemname: item.name, - iconname: item.icon.replace('.jpg', ''), - quality: item.quality.replace(/^\w/, c => c.toUpperCase()), - url: "https://classic.wowhead.com/item="+item.id - }}) + + this.gear2 = await Promise.all(data.gear.map(i => i.name).map(itemName => this.api.get('ItemManager').getItem(itemName))) + this.gear2 = this.gear2.filter(i => i!=null) + })) - fetch(this.dataLink).then(raw => raw.json().then((json) => { + fetch(this.dataLink).then(raw => raw.json().then(async (json) => { if(json.length < 2) return - console.log(json); - const data = json[1] this.boss1 = { @@ -77,12 +73,9 @@ export class FrontcraftCharacterComponent implements OnInit{ date: data.startTime } - this.gear1 = data.gear.map(item => {return { - itemname: item.name, - iconname: item.icon.replace('.jpg', ''), - quality: item.quality.replace(/^\w/, c => c.toUpperCase()), - url: "https://classic.wowhead.com/item="+item.id - }}) + + this.gear1 = await Promise.all(data.gear.map(i => i.name).map(itemName => this.api.get('ItemManager').getItem(itemName))) + this.gear1 = this.gear1.filter(i => i!=null) })) } }) diff --git a/src/frontend/src/app/frontcraft/pages/shop/item.component.ts b/src/frontend/src/app/frontcraft/pages/shop/item.component.ts index c7da5b5..21b1ccd 100644 --- a/src/frontend/src/app/frontcraft/pages/shop/item.component.ts +++ b/src/frontend/src/app/frontcraft/pages/shop/item.component.ts @@ -1,35 +1,37 @@ -import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit, Input, } from '@angular/core'; import { ApiService as ApiService } from '../../services/login-api'; -import { FrontcraftItemSelectComponent } from './itemselector.component'; -import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme'; -import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types'; -import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs'; -import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items'; +import { NbToastrService, } from '@nebular/theme'; +import { Item, } from '../../../../../../backend/Types/Types'; +import { _Tiers, } from '../../../../../../backend/Types/Items'; @Component({ - selector: 'item', - template: ` - - -   - {{item.itemname}} - + selector: 'item', + template: ` + +
Spineshatter
Item Level 73

Binds when picked up
Unique
Main HandMace
99 - 184 Damage Speed 2.60
(54.42 damage per second)
+9 Strength
+16 Stamina
Durability 105 / 105
Requires Level 60
Equip: Increased Defense +5.
Sell Price: 12 88 25
Dropped by: Razorgore the Untamed
+
+ + +   + {{item.itemname}} + `, - }) - export class FrontcraftItemComponent implements OnInit{ - @Input() item: Item - - constructor( - private toastr: NbToastrService, - private api : ApiService - ){} - - async ngOnInit() { - } - } \ No newline at end of file +}) +export class FrontcraftItemComponent implements OnInit { + @Input() item: Item + + constructor( + private toastr: NbToastrService, + private api: ApiService + ) { } + + async ngOnInit() { + } +} \ No newline at end of file diff --git a/src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts b/src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts index 1511831..3937706 100644 --- a/src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts +++ b/src/frontend/src/app/frontcraft/pages/shop/wowhead.component.ts @@ -1,26 +1,40 @@ -import { Component, OnInit, ContentChild, AfterContentInit, ViewChild, AfterViewInit, Input, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit, Input } from '@angular/core'; import { ApiService as ApiService } from '../../services/login-api'; -import { NbWindowService, NbWindowRef, NbToastrService, NbDialogService, NbDialogRef } from '@nebular/theme'; -import { Item, Character, SRToken, Signup } from '../../../../../../backend/Types/Types'; -import { _Tiers, allItems, Tiers } from '../../../../../../backend/Types/Items'; +import { NbToastrService } from '@nebular/theme'; +import { Item } from '../../../../../../backend/Types/Types'; +import { _Tiers } from '../../../../../../backend/Types/Items'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; @Component({ - selector: 'wowhead', - template: ` - - - - + selector: 'wowhead', + template: ` + +
+
+
+ + + + + + + `, - }) - export class FrontcraftWowheadComponent implements OnInit{ - @Input() item: Item - - constructor( - private toastr: NbToastrService, - private api : ApiService - ){} - - async ngOnInit() { - } - } \ No newline at end of file +}) +export class FrontcraftWowheadComponent implements OnInit { + @Input() item: Item + tooltipHtml : SafeHtml + + constructor( + private sanitizer: DomSanitizer, + private toastr: NbToastrService, + private api: ApiService + ) { } + + async ngOnInit() { + this.tooltipHtml = this.sanitizer.bypassSecurityTrustHtml(this.item.tooltip) + } +} \ No newline at end of file