Dependencies:
npm install --save-dev @types/ws
npm install reconnecting-websocket ws
import ReconnectingWebSocket from 'reconnecting-websocket'; | |
import WS from 'ws'; | |
import * as Events from 'reconnecting-websocket/events'; | |
export default class BackpackSocketManager { | |
private ws: ReconnectingWebSocket; | |
constructor() { | |
this.ws = new ReconnectingWebSocket('wss://ws.backpack.tf/events', [], { | |
WebSocket: WS, | |
maxEnqueuedMessages: 0, | |
startClosed: true | |
}) | |
this.ws.addEventListener('open', this.socketConnect()); | |
this.ws.addEventListener('error', err => { | |
console.log(err); | |
}); | |
this.ws.addEventListener('close', this.socketDisconnected()); | |
} | |
private socketDisconnected() { | |
return () => { | |
console.debug('Disconnected from socket server'); | |
}; | |
} | |
private socketConnect() { | |
return () => { | |
console.debug('Connected to socket server'); | |
}; | |
} | |
connect(): void { | |
this.ws.reconnect(); | |
} | |
on<T extends keyof Events.WebSocketEventListenerMap>(name: T, handler: Events.WebSocketEventListenerMap[T]): void { | |
this.ws.addEventListener(name, handler); | |
} | |
} |
import BackpackSocketManager from "./BackpackSocketManager"; | |
export interface UserAgent { | |
client: string; | |
lastPulse: number; | |
} | |
export interface User { | |
id: string; | |
name: string; | |
avatar: string; | |
avatarFull: string; | |
premium: boolean; | |
online: boolean; | |
banned: boolean; | |
customNameStyle: string; | |
acceptedSuggestions: number; | |
class: string; | |
style: string; | |
tradeOfferUrl: string; | |
isMarketplaceSeller: boolean; | |
flagImpersonated?: any; | |
bans: any[]; | |
} | |
export interface Currencies { | |
metal?: number; | |
keys?: number; | |
usd?: number; | |
} | |
export interface KillEater2 { | |
name: string; | |
} | |
export interface KillEater { | |
score: number; | |
killEater: KillEater2; | |
} | |
export interface Origin { | |
id: number; | |
name: string; | |
} | |
export interface Steam { | |
currency: string; | |
short: string; | |
long: string; | |
raw: number; | |
value: number; | |
} | |
export interface Metadata { | |
appid: number; | |
quality: number; | |
defindexes: number[]; | |
item_name: string; | |
base_item_name: string; | |
priceindex: string; | |
tradable: boolean; | |
craftable: boolean; | |
value_raw: number; | |
used_by_classes: string[]; | |
item_slot: string; | |
release_date: number; | |
} | |
export interface Community { | |
metadata: Metadata; | |
value: number; | |
valueHigh: number; | |
currency: string; | |
raw: number; | |
short: string; | |
long: string; | |
updatedAt: number; | |
difference: number; | |
} | |
export interface Suggested { | |
raw: number; | |
short: string; | |
long: string; | |
} | |
export interface Price { | |
steam: Steam; | |
community: Community; | |
suggested: Suggested; | |
} | |
export interface Quality { | |
id: number; | |
name: string; | |
color: string; | |
} | |
export interface Summary { | |
value: string; | |
} | |
export interface Spell { | |
id: string; | |
spellId: string; | |
name: string; | |
type: string; | |
defindex?: number; | |
color?: string; | |
} | |
interface Particle { | |
"id": number; | |
"name": string; | |
"shortName": string; | |
"imageUrl": string; | |
"type": string; | |
} | |
interface MpListing { | |
"value": number, | |
"raw": number, | |
"short": string, | |
"currency": string | |
} | |
export interface Item { | |
appid: number; | |
australium: boolean; | |
baseName: string; | |
class: string[]; | |
craftable: boolean; | |
defindex: number; | |
festivized: boolean; | |
id: string; | |
imageUrl: string; | |
killEaters?: KillEater[]; | |
level: number; | |
marketName: string; | |
name: string; | |
origin: Origin; | |
originalId: string; | |
particle?: Particle; | |
priceindex: string; | |
price: Price; | |
quality: Quality; | |
quantity: number; | |
slot: string; | |
tradable: boolean; | |
summary: Summary; | |
spells?: Spell[]; | |
marketplaceTfListing?: MpListing; | |
} | |
export interface Spell { | |
id: string; | |
spellId: string; | |
name: string; | |
type: string; | |
defindex?: number; | |
color?: string; | |
} | |
interface Particle { | |
"id": number; | |
"name": string; | |
"shortName": string; | |
"imageUrl": string; | |
"type": string; | |
} | |
interface MpListing { | |
"value": number, | |
"raw": number, | |
"short": string, | |
"currency": string | |
} | |
export interface Item { | |
appid: number; | |
australium: boolean; | |
baseName: string; | |
class: string[]; | |
craftable: boolean; | |
defindex: number; | |
festivized: boolean; | |
id: string; | |
imageUrl: string; | |
killEaters?: KillEater[]; | |
level: number; | |
marketName: string; | |
name: string; | |
origin: Origin; | |
originalId: string; | |
particle?: Particle; | |
priceindex: string; | |
price: Price; | |
quality: Quality; | |
quantity: number; | |
slot: string; | |
tradable: boolean; | |
summary: Summary; | |
spells?: Spell[]; | |
marketplaceTfListing?: MpListing; | |
} | |
export interface Value { | |
raw: number; | |
short: string; | |
long: string; | |
} | |
export interface Listing { | |
id: string; | |
steamid: string; | |
appid: number; | |
currencies: Currencies; | |
value: Value; | |
tradeOffersPreferred: boolean; | |
buyoutOnly: boolean; | |
details?: string | null | undefined; | |
listedAt: number; | |
bumpedAt: number; | |
intent: string; | |
item: Item; | |
count: number; | |
status: string; | |
userAgent?: UserAgent; | |
user: User; | |
} | |
let notifications: string[] = []; | |
const backpackSocket = new BackpackSocketManager(); | |
backpackSocket.on('message', (m) => { | |
if(typeof m.data === 'string') { | |
notifications.push(m.data); | |
} else { | |
console.error(`cannot add ${m}`); | |
} | |
}); | |
backpackSocket.connect(); | |
getListings = (): { event: string, payload: Listing }[] => { | |
const lastIndex = notifications.length; | |
const copy = notifications.slice(0,lastIndex); | |
notifications = notifications.slice(lastIndex); | |
return copy.map(e => JSON.parse(e)); | |
}; | |
while(true) { | |
const listings = getListings(); | |
console.log(JSON.stringify(listings, null, 2)); | |
} |