Skip to content

Commit c2ec403

Browse files
committed
fix: locally parse new inspect link format
1 parent 8b0a508 commit c2ec403

10 files changed

Lines changed: 147 additions & 21 deletions

File tree

package-lock.json

Lines changed: 41 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"webpack-cli": "^6.0.1"
6969
},
7070
"dependencies": {
71+
"@csfloat/cs2-inspect-serializer": "file:../cs-inspect-serializer",
7172
"buffer": "^6.0.3",
7273
"comlink": "^4.4.2",
7374
"@csfloat/tlsn-wasm": "0.1.0-alpha.14"

src/lib/bridge/handlers/fetch_inspect_info.ts

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {decodeLink, CEconItemPreviewDataBlock} from '@csfloat/cs2-inspect-serializer';
12
import {SimpleHandler} from './main';
23
import {RequestType} from './types';
34

@@ -47,6 +48,7 @@ export interface ItemInfo {
4748
export interface FetchInspectInfoRequest {
4849
link: string;
4950
listPrice?: number;
51+
marketHashName?: string;
5052
}
5153

5254
export interface FetchInspectInfoResponse {
@@ -56,16 +58,73 @@ export interface FetchInspectInfoResponse {
5658

5759
export const FetchInspectInfo = new SimpleHandler<FetchInspectInfoRequest, FetchInspectInfoResponse>(
5860
RequestType.FETCH_INSPECT_INFO,
59-
(req) => {
60-
const apiUrl = `https://api.csfloat.com/?url=${req.link}&minimal=true${req.listPrice ? '&listPrice=' + req.listPrice : ''}`;
61-
return fetch(apiUrl).then((resp) => {
62-
return resp.json().then((json: FetchInspectInfoResponse) => {
63-
if (resp.ok) {
64-
return json;
65-
} else {
66-
throw Error(json.error);
67-
}
68-
}) as Promise<FetchInspectInfoResponse>;
69-
});
61+
async (req) => {
62+
const itemMetadata = parseMarketHashName(req.marketHashName);
63+
let decoded: CEconItemPreviewDataBlock;
64+
try {
65+
decoded = decodeLink(req.link);
66+
} catch (error) {
67+
throw new Error('Failed to decode inspect link');
68+
}
69+
70+
return {
71+
iteminfo: {
72+
stickers: decoded.stickers.map((sticker) => ({
73+
slot: sticker.slot ?? 0,
74+
stickerId: sticker.stickerId ?? 0,
75+
wear: sticker.wear,
76+
})),
77+
keychains: decoded.keychains.map((keychain) => ({
78+
slot: keychain.slot ?? 0,
79+
stickerId: keychain.stickerId ?? 0,
80+
wear: keychain.wear,
81+
pattern: keychain.pattern ?? 0,
82+
})),
83+
itemid: decoded.itemid?.toString() ?? '',
84+
defindex: decoded.defindex ?? 0,
85+
paintindex: decoded.paintindex ?? 0,
86+
rarity: decoded.rarity ?? 0,
87+
quality: decoded.quality ?? 0,
88+
paintseed: decoded.paintseed ?? 0,
89+
inventory: decoded.inventory ?? 0,
90+
origin: decoded.origin ?? 0,
91+
s: '',
92+
a: '',
93+
d: '',
94+
m: '',
95+
floatvalue: decoded.paintwear ?? 0,
96+
imageurl: '',
97+
min: 0,
98+
max: 1,
99+
weapon_type: itemMetadata?.weaponType,
100+
item_name: itemMetadata?.itemName,
101+
wear_name: itemMetadata?.wearName,
102+
full_item_name: req.marketHashName,
103+
},
104+
};
70105
}
71106
);
107+
108+
interface ParsedMarketHashName {
109+
weaponType?: string;
110+
itemName?: string;
111+
wearName?: string;
112+
}
113+
114+
function parseMarketHashName(marketHashName?: string): ParsedMarketHashName | undefined {
115+
if (!marketHashName) {
116+
return;
117+
}
118+
119+
const match = /^(.*?) \| (.*?)(?: \(([^)]+)\))?$/.exec(marketHashName);
120+
if (!match) {
121+
return;
122+
}
123+
124+
const [, weaponType, itemName, wearName] = match;
125+
return {
126+
weaponType,
127+
itemName,
128+
wearName,
129+
};
130+
}

src/lib/components/common/item_holder_metadata.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,13 @@ export abstract class ItemHolderMetadata extends FloatElement {
9595
return;
9696
}
9797

98-
return this.asset
99-
?.actions![0].link.replace('%owner_steamid%', this.ownerSteamId)
100-
.replace('%assetid%', this.assetId!);
98+
const link = this.asset?.actions![0].link;
99+
if (link.includes('%propid:6%')) {
100+
const propId = this.asset.asset_properties?.find((p) => p.propertyid === 6)?.string_value;
101+
if (!propId || !link) return;
102+
return link.replace('%propid:6%', propId);
103+
}
104+
return link;
101105
}
102106

103107
protected render(): HTMLTemplateResult {
@@ -174,6 +178,7 @@ export abstract class ItemHolderMetadata extends FloatElement {
174178
try {
175179
this.itemInfo = await gFloatFetcher.fetch({
176180
link: this.inspectLink,
181+
marketHashName: this.asset.market_hash_name,
177182
});
178183
} catch (e: any) {
179184
console.error(`Failed to fetch float for ${this.assetId}: ${e.toString()}`);

src/lib/components/inventory/inventory_item_holder_metadata.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ export class InventoryItemHolderMetadata extends ItemHolderMetadata {
1818
if (isCAppwideInventory(g_ActiveInventory)) {
1919
const contextId = this.isTradeProtected ? ContextId.PROTECTED : ContextId.PRIMARY;
2020

21-
return g_ActiveInventory.m_rgChildInventories[contextId]?.m_rgAssets[this.assetId]?.description;
21+
const invAsset = g_ActiveInventory.m_rgChildInventories[contextId]?.m_rgAssets[this.assetId];
22+
if (invAsset && !invAsset.description.asset_properties) {
23+
// due to inconsistencies in Steam's data structure, we sometimes need to manually populate this field here
24+
invAsset.description.asset_properties = invAsset.asset_properties;
25+
}
26+
return invAsset?.description;
2227
} else {
2328
return g_ActiveInventory.m_rgAssets[this.assetId]?.description;
2429
}

src/lib/components/inventory/selected_item_info.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,13 @@ export class SelectedItemInfo extends FloatElement {
9494
return;
9595
}
9696

97-
return this.asset.description
98-
?.actions![0].link.replace('%owner_steamid%', g_ActiveInventory.m_owner.strSteamId!)
99-
.replace('%assetid%', this.asset.assetid!);
97+
const link = this.asset.description?.actions![0].link;
98+
if (link.includes('%propid:6%')) {
99+
const propId = this.asset.asset_properties?.find((p) => p.propertyid === 6)?.string_value;
100+
if (!propId || !link) return;
101+
return link.replace('%propid:6%', propId);
102+
}
103+
return link;
100104
}
101105

102106
get stallListing(): Contract | undefined {
@@ -259,6 +263,7 @@ export class SelectedItemInfo extends FloatElement {
259263
try {
260264
this.itemInfo = await gFloatFetcher.fetch({
261265
link: this.inspectLink,
266+
marketHashName: this.asset.description.market_hash_name,
262267
});
263268
} catch (e: any) {
264269
console.error(`Failed to fetch float for ${this.asset.assetid}: ${e.toString()}`);

src/lib/components/market/helpers.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ export function getMarketInspectLink(listingId: string): string | undefined {
1212
const asset = g_rgAssets[AppId.CSGO][ContextId.PRIMARY][listingInfo.asset.id!];
1313
if (!asset || !asset.market_actions?.length) return;
1414

15-
return asset.market_actions[0].link.replace('%listingid%', listingId).replace('%assetid%', asset.id);
15+
const link = asset.market_actions[0].link;
16+
if (link.includes('%propid:6%')) {
17+
const propId = asset.asset_properties?.find((p) => p.propertyid === 6)?.string_value;
18+
if (!propId || !link) return;
19+
return link.replace('%propid:6%', propId);
20+
}
21+
return link;
1622
}
1723

1824
/**

src/lib/components/market/item_row_wrapper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export class ItemRowWrapper extends FloatElement {
8686
return gFloatFetcher.fetch({
8787
link: this.inspectLink!,
8888
listPrice: this.usdPrice,
89+
marketHashName: this.asset?.market_hash_name,
8990
});
9091
}
9192

src/lib/components/market/sort_listings.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,12 @@ export class SortListings extends FloatElement {
122122
// Catch error to prevent one failure from stopping the Promise.all() later
123123
try {
124124
const link = getMarketInspectLink(listingId);
125-
const info = await gFloatFetcher.fetch({link: link!});
126125
const listingInfo = g_rgListingInfo[listingId];
127126
const asset = g_rgAssets[AppId.CSGO][ContextId.PRIMARY][listingInfo.asset.id];
127+
const info = await gFloatFetcher.fetch({
128+
link: link!,
129+
marketHashName: asset?.market_hash_name,
130+
});
128131
return {
129132
failed: false,
130133
info,

src/lib/types/steam.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export interface rgInventoryAsset {
117117
export interface InventoryAsset {
118118
amount: string;
119119
appid: AppId;
120+
asset_properties?: rgAssetProperty[];
120121
assetid: string;
121122
classid: string;
122123
contextid: string;

0 commit comments

Comments
 (0)