tf2-sku-to-name 1.0.7__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sku/parser.py CHANGED
@@ -1,236 +1,649 @@
1
- from sku.models import itemClass as itemClass
2
- from typing import List
3
- from collections import deque
4
- import requests
5
- import sqlite3
6
- import pkg_resources
7
-
8
- DB_FILE = pkg_resources.resource_filename(__name__, 'data/data.db')
9
-
10
-
11
- class Sku:
12
- @staticmethod
13
- def object_to_sku(item: itemClass) -> str:
14
- sku_parts: List[str] = [str(item.Defindex), str(int(item.Quality))]
15
-
16
- if item.Effect is not None:
17
- sku_parts.append(f"u{item.Effect}")
18
-
19
- if item.Australium:
20
- sku_parts.append("australium")
21
-
22
- if not item.Craftable:
23
- sku_parts.append("uncraftable")
24
-
25
- if item.Wear is not None:
26
- sku_parts.append(f"w{item.Wear}")
27
-
28
- if item.PaintKit is not None:
29
- sku_parts.append(f"pk{item.PaintKit}")
30
-
31
- if item.ElevatedQuality == 11:
32
- sku_parts.append("strange")
33
-
34
- if item.Killstreak != 0:
35
- sku_parts.append(f"kt-{item.Killstreak}")
36
-
37
- if item.Target is not None:
38
- sku_parts.append(f"td-{item.Target}")
39
-
40
- if item.Festive:
41
- sku_parts.append("festive")
42
-
43
- if item.CraftNum is not None:
44
- sku_parts.append(f"n{item.CraftNum}")
45
-
46
- if item.CrateSn is not None:
47
- sku_parts.append(f"c{item.CrateSn}")
48
-
49
- if item.Output is not None:
50
- sku_parts.append(f"od-{item.Output}")
51
-
52
- if item.OutputQuality is not None:
53
- sku_parts.append(f"oq-{item.OutputQuality}")
54
-
55
- return ";".join(sku_parts)
56
-
57
- @staticmethod
58
- def sku_to_object(sku: str) -> itemClass:
59
- item = itemClass()
60
- sku_parts = deque(sku.split(';'))
61
-
62
- if sku_parts and sku_parts[0].isdigit():
63
- item.Defindex = int(sku_parts.popleft())
64
-
65
- if sku_parts and sku_parts[0].isdigit():
66
- item.Quality = int(sku_parts.popleft())
67
-
68
- while sku_parts:
69
- Sku.change_attribute(sku_parts.popleft(), item)
70
-
71
- return item
72
-
73
- @staticmethod
74
- def change_attribute(attribute: str, item: itemClass) -> None:
75
- attr = attribute.replace("-", "")
76
-
77
- if attr == "uncraftable":
78
- item.Craftable = False
79
-
80
- elif attr == "australium":
81
- item.Australium = True
82
-
83
- elif attr == "festive":
84
- item.Festive = True
85
-
86
- elif attr == "strange":
87
- item.ElevatedQuality = 11
88
-
89
- elif attr.startswith("kt") and attr[2:].isdigit():
90
- item.Killstreak = int(attr[2:])
91
-
92
- elif attr.startswith("u") and attr[1:].isdigit():
93
- item.Effect = int(attr[1:])
94
-
95
- elif attr.startswith("pk") and attr[2:].isdigit():
96
- item.PaintKit = int(attr[2:])
97
-
98
- elif attr.startswith("w") and attr[1:].isdigit():
99
- item.Wear = int(attr[1:])
100
-
101
- elif attr.startswith("td") and attr[2:].isdigit():
102
- item.Target = int(attr[2:])
103
-
104
- elif attr.startswith("n") and attr[1:].isdigit():
105
- item.CraftNum = int(attr[1:])
106
-
107
- elif attr.startswith("c") and attr[1:].isdigit():
108
- item.CrateSn = int(attr[1:])
109
-
110
- elif attr.startswith("od") and attr[2:].isdigit():
111
- item.Output = int(attr[2:])
112
-
113
- elif attr.startswith("oq") and attr[2:].isdigit():
114
- item.OutputQuality = int(attr[2:])
115
-
116
- @staticmethod
117
- def sku_to_name(sku: str, proper_name: bool = True, force_use_autobot: bool = False) -> str:
118
- if not force_use_autobot:
119
- json_data = Sku.get_json_data(sku=sku)
120
- if json_data:
121
- return json_data
122
-
123
- url = requests.utils.quote(f"schema.autobot.tf/getName/fromSku/{sku}")
124
- req = requests.get(f"https://{url}", params={"proper": "true" if proper_name else "false"})
125
- if not req or req.status_code != 200:
126
- raise ValueError(f"Failed to get name from SKU: {sku} from autobot.tf")
127
-
128
- name = req.json().get("name")
129
-
130
- if not name:
131
- raise ValueError(f"Failed to get name from SKU: {sku} from autobot.tf")
132
-
133
- Sku.update_json_data(sku, name)
134
- return name
135
-
136
- @staticmethod
137
- def name_to_sku(name: str, force_use_autobot: bool = False) -> str:
138
- if not force_use_autobot:
139
- json_data = Sku.get_json_data(name=name)
140
- if json_data:
141
- return json_data
142
- url = requests.utils.quote(f"schema.autobot.tf/getSku/fromName/{name}")
143
- req = requests.get(f"https://{url}")
144
- if not req or req.status_code != 200:
145
- raise ValueError(f"Failed to get SKU from name: {name} from autobot.tf")
146
-
147
- sku = req.json().get("sku")
148
-
149
- if not sku:
150
- raise ValueError(f"Failed to get SKU from name: {name} from autobot.tf")
151
-
152
- Sku.update_json_data(sku, name)
153
- return sku
154
-
155
- @staticmethod
156
- def _create_tables_if_not_exist(conn):
157
- cursor = conn.cursor()
158
- # Create the "sku" and "name" tables if they don't exist
159
- cursor.execute("""
160
- CREATE TABLE IF NOT EXISTS sku (
161
- sku TEXT PRIMARY KEY,
162
- name TEXT NOT NULL
163
- )
164
- """)
165
- cursor.execute("""
166
- CREATE TABLE IF NOT EXISTS name (
167
- name TEXT PRIMARY KEY,
168
- sku TEXT NOT NULL
169
- )
170
- """)
171
- conn.commit()
172
-
173
- @staticmethod
174
- def get_json_data(sku: str = str(), name: str = str()) -> str:
175
- conn = sqlite3.connect(DB_FILE)
176
- Sku._create_tables_if_not_exist(conn) # Ensure tables exist
177
- cursor = conn.cursor()
178
-
179
- if sku:
180
- cursor.execute("SELECT name FROM sku WHERE sku=?", (sku,))
181
- result = cursor.fetchone()
182
- return result[0] if result else ""
183
-
184
- if name:
185
- cursor.execute("SELECT sku FROM name WHERE name=?", (name,))
186
- result = cursor.fetchone()
187
- return result[0] if result else ""
188
-
189
- conn.close()
190
- return ""
191
-
192
- @staticmethod
193
- def update_json_data(sku: str, name: str) -> None:
194
- conn = sqlite3.connect(DB_FILE)
195
- Sku._create_tables_if_not_exist(conn) # Ensure tables exist
196
- cursor = conn.cursor()
197
-
198
- try:
199
- cursor.execute("INSERT INTO sku (sku, name) VALUES (?, ?)", (sku, name))
200
- cursor.execute("INSERT INTO name (name, sku) VALUES (?, ?)", (name, sku))
201
- except sqlite3.IntegrityError:
202
- # If the name already exists, update the corresponding sku instead of inserting
203
- cursor.execute("UPDATE name SET sku=? WHERE name=?", (sku, name))
204
-
205
- conn.commit()
206
- conn.close()
207
-
208
- @staticmethod
209
- def update_autobot_pricelist() -> None:
210
- req = requests.get("https://autobot.tf/json/pricelist-array").json()
211
-
212
- conn = sqlite3.connect(DB_FILE)
213
- Sku._create_tables_if_not_exist(conn) # Ensure tables exist
214
- cursor = conn.cursor()
215
-
216
- for item in req.get("items"):
217
- name = item.get("name")
218
- sku = item.get("sku")
219
-
220
- # Check if the name already exists in the database
221
- cursor.execute("SELECT sku FROM name WHERE name=?", (name,))
222
- existing_sku = cursor.fetchone()
223
-
224
- # If the name exists, update the existing entry
225
- if existing_sku:
226
- existing_sku = existing_sku[0]
227
- if existing_sku != sku:
228
- # Update the SKU for the existing name
229
- cursor.execute("UPDATE name SET sku=? WHERE name=?", (sku, name))
230
- else:
231
- # If the name doesn't exist, insert a new entry
232
- cursor.execute("INSERT OR IGNORE INTO name (name, sku) VALUES (?, ?)", (name, sku))
233
- cursor.execute("INSERT OR IGNORE INTO sku (sku, name) VALUES (?, ?)", (sku, name))
234
-
235
- conn.commit()
236
- conn.close()
1
+ from sku.models import itemClass
2
+ from sku.schema import Schema
3
+ from typing import List
4
+ from collections import deque
5
+ import re
6
+
7
+ # Initialize schema (will load from cache or fetch from autobot.tf by default)
8
+ _schema = None
9
+
10
+ def get_schema(api_key=None, use_autobot=True):
11
+ """Get or initialize the schema instance"""
12
+ global _schema
13
+ if _schema is None:
14
+ _schema = Schema(api_key=api_key, use_autobot=use_autobot)
15
+ return _schema
16
+
17
+
18
+ class Sku:
19
+ @staticmethod
20
+ def object_to_sku(item: itemClass) -> str:
21
+ sku_parts: List[str] = [str(item.Defindex), str(int(item.Quality))]
22
+
23
+ if item.Effect is not None:
24
+ sku_parts.append(f"u{item.Effect}")
25
+
26
+ if item.Australium:
27
+ sku_parts.append("australium")
28
+
29
+ if not item.Craftable:
30
+ sku_parts.append("uncraftable")
31
+
32
+ if item.Wear is not None:
33
+ sku_parts.append(f"w{item.Wear}")
34
+
35
+ if item.PaintKit is not None:
36
+ sku_parts.append(f"pk{item.PaintKit}")
37
+
38
+ if item.ElevatedQuality == 11:
39
+ sku_parts.append("strange")
40
+
41
+ if item.Killstreak != 0:
42
+ sku_parts.append(f"kt-{item.Killstreak}")
43
+
44
+ if item.Target is not None:
45
+ sku_parts.append(f"td-{item.Target}")
46
+
47
+ if item.Festive:
48
+ sku_parts.append("festive")
49
+
50
+ if item.CraftNum is not None:
51
+ sku_parts.append(f"n{item.CraftNum}")
52
+
53
+ if item.CrateSn is not None:
54
+ sku_parts.append(f"c{item.CrateSn}")
55
+
56
+ if item.Output is not None:
57
+ sku_parts.append(f"od-{item.Output}")
58
+
59
+ if item.OutputQuality is not None:
60
+ sku_parts.append(f"oq-{item.OutputQuality}")
61
+
62
+ return ";".join(sku_parts)
63
+
64
+ @staticmethod
65
+ def sku_to_object(sku: str) -> itemClass:
66
+ item = itemClass()
67
+ sku_parts = deque(sku.split(';'))
68
+
69
+ if sku_parts and sku_parts[0].isdigit():
70
+ item.Defindex = int(sku_parts.popleft())
71
+
72
+ if sku_parts and sku_parts[0].isdigit():
73
+ item.Quality = int(sku_parts.popleft())
74
+
75
+ while sku_parts:
76
+ Sku.change_attribute(sku_parts.popleft(), item)
77
+
78
+ return item
79
+
80
+ @staticmethod
81
+ def change_attribute(attribute: str, item: itemClass) -> None:
82
+ attr = attribute.replace("-", "")
83
+
84
+ if attr == "uncraftable":
85
+ item.Craftable = False
86
+
87
+ elif attr == "australium":
88
+ item.Australium = True
89
+
90
+ elif attr == "festive":
91
+ item.Festive = True
92
+
93
+ elif attr == "strange":
94
+ item.ElevatedQuality = 11
95
+
96
+ elif attr.startswith("kt") and attr[2:].isdigit():
97
+ item.Killstreak = int(attr[2:])
98
+
99
+ elif attr.startswith("u") and attr[1:].isdigit():
100
+ item.Effect = int(attr[1:])
101
+
102
+ elif attr.startswith("pk") and attr[2:].isdigit():
103
+ item.PaintKit = int(attr[2:])
104
+
105
+ elif attr.startswith("w") and attr[1:].isdigit():
106
+ item.Wear = int(attr[1:])
107
+
108
+ elif attr.startswith("td") and attr[2:].isdigit():
109
+ item.Target = int(attr[2:])
110
+
111
+ elif attr.startswith("n") and attr[1:].isdigit():
112
+ item.CraftNum = int(attr[1:])
113
+
114
+ elif attr.startswith("c") and attr[1:].isdigit():
115
+ item.CrateSn = int(attr[1:])
116
+
117
+ elif attr.startswith("od") and attr[2:].isdigit():
118
+ item.Output = int(attr[2:])
119
+
120
+ elif attr.startswith("oq") and attr[2:].isdigit():
121
+ item.OutputQuality = int(attr[2:])
122
+
123
+ @staticmethod
124
+ def sku_to_name(sku: str, proper_name: bool = True) -> str:
125
+ """Convert SKU to item name using the schema"""
126
+ item = Sku.sku_to_object(sku)
127
+ schema = get_schema()
128
+
129
+ item_dict = {
130
+ 'defindex': item.Defindex,
131
+ 'quality': item.Quality,
132
+ 'craftable': item.Craftable,
133
+ 'australium': item.Australium,
134
+ 'festive': item.Festive,
135
+ 'killstreak': item.Killstreak,
136
+ 'effect': item.Effect,
137
+ 'paintkit': item.PaintKit,
138
+ 'wear': item.Wear,
139
+ 'quality2': item.ElevatedQuality,
140
+ 'target': item.Target,
141
+ 'craftnumber': item.CraftNum,
142
+ 'crateseries': item.CrateSn,
143
+ 'output': item.Output,
144
+ 'outputQuality': item.OutputQuality,
145
+ 'tradable': True, # SKUs don't track tradability
146
+ 'paint': None # SKUs don't track paint
147
+ }
148
+
149
+ name = schema.get_name(item_dict, proper_name)
150
+ if not name:
151
+ raise ValueError(f"Failed to get name from SKU: {sku}")
152
+
153
+ return name
154
+
155
+ @staticmethod
156
+ def name_to_sku(name: str) -> str:
157
+ schema = get_schema()
158
+
159
+ # Convert name to lowercase for processing
160
+ name = name.strip()
161
+ name_lower = name.lower()
162
+
163
+ # Initialize item dict
164
+ item = {
165
+ 'defindex': None,
166
+ 'quality': None,
167
+ 'craftable': True,
168
+ 'australium': False,
169
+ 'festive': False,
170
+ 'killstreak': 0,
171
+ 'effect': None,
172
+ 'paintkit': None,
173
+ 'wear': None,
174
+ 'quality2': None,
175
+ 'target': None,
176
+ 'craftnumber': None,
177
+ 'crateseries': None,
178
+ 'output': None,
179
+ 'outputQuality': None,
180
+ 'tradable': True,
181
+ 'paint': None
182
+ }
183
+
184
+ if any(x in name_lower for x in ['strange part:', 'strange cosmetic part:', 'strange filter:',
185
+ 'strange count transfer tool', 'strange bacon grease']):
186
+ schema_item = schema.get_item_by_item_name(name)
187
+ if schema_item:
188
+ item['defindex'] = schema_item['defindex']
189
+ item['quality'] = schema_item.get('item_quality', 6)
190
+ return Sku._dict_to_sku(item)
191
+
192
+ # Process wear
193
+ wears = {
194
+ '(factory new)': 1,
195
+ '(minimal wear)': 2,
196
+ '(field-tested)': 3,
197
+ '(well-worn)': 4,
198
+ '(battle scarred)': 5
199
+ }
200
+
201
+ for wear_text, wear_value in wears.items():
202
+ if wear_text in name_lower:
203
+ name_lower = name_lower.replace(wear_text, '').strip()
204
+ item['wear'] = wear_value
205
+ break
206
+
207
+ if 'strange(e)' in name_lower:
208
+ item['quality2'] = 11
209
+ name_lower = name_lower.replace('strange(e)', '').strip()
210
+
211
+ if 'strange' in name_lower:
212
+ item['quality'] = 11
213
+ name_lower = name_lower.replace('strange', '').strip()
214
+
215
+ name_lower = name_lower.replace('uncraftable', 'non-craftable')
216
+ if 'non-craftable' in name_lower:
217
+ name_lower = name_lower.replace('non-craftable', '').strip()
218
+ item['craftable'] = False
219
+
220
+ name_lower = name_lower.replace('untradeable', 'non-tradable').replace('untradable', 'non-tradable')
221
+ if 'non-tradable' in name_lower:
222
+ name_lower = name_lower.replace('non-tradable', '').strip()
223
+ item['tradable'] = False
224
+
225
+ if 'unusualifier' in name_lower:
226
+ name_lower = name_lower.replace('unusual ', '').replace(' unusualifier', '').strip()
227
+ item['defindex'] = 9258
228
+ item['quality'] = 5
229
+
230
+ schema_item = schema.get_item_by_item_name(name_lower)
231
+ if schema_item:
232
+ item['target'] = schema_item['defindex']
233
+
234
+ return Sku._dict_to_sku(item)
235
+
236
+ killstreaks = {
237
+ 'professional killstreak': 3,
238
+ 'specialized killstreak': 2,
239
+ 'killstreak': 1
240
+ }
241
+
242
+ for ks_text, ks_value in killstreaks.items():
243
+ if ks_text in name_lower:
244
+ name_lower = name_lower.replace(ks_text + ' ', '').strip()
245
+ item['killstreak'] = ks_value
246
+ break
247
+
248
+ if 'australium' in name_lower and 'australium gold' not in name_lower:
249
+ name_lower = name_lower.replace('australium', '').strip()
250
+ item['australium'] = True
251
+
252
+ if 'festivized' in name_lower and 'festivized formation' not in name_lower:
253
+ name_lower = name_lower.replace('festivized', '').strip()
254
+ item['festive'] = True
255
+
256
+ exception = [
257
+ 'haunted ghosts', 'haunted phantasm jr', 'haunted phantasm', 'haunted metal scrap',
258
+ 'haunted hat', 'unusual cap', 'vintage tyrolean', 'vintage merryweather',
259
+ 'haunted kraken', 'haunted forever!', 'haunted cremation', 'haunted wick'
260
+ ]
261
+
262
+ quality_search = name_lower
263
+ for ex in exception:
264
+ if ex in name_lower:
265
+ quality_search = name_lower.replace(ex, '').strip()
266
+ break
267
+
268
+ if quality_search not in exception:
269
+ for quality_name, quality_id in schema.qualities.items():
270
+ quality_lower = quality_name.lower()
271
+
272
+ if quality_lower == "collector's" and "collector's" in quality_search and 'chemistry set' in quality_search:
273
+ continue
274
+
275
+ if quality_lower == 'community' and quality_search.startswith('community sparkle'):
276
+ continue
277
+
278
+ if quality_search.startswith(quality_lower):
279
+ name_lower = name_lower.replace(quality_lower, '').strip()
280
+ item['quality2'] = item['quality']
281
+ item['quality'] = quality_id
282
+ break
283
+
284
+
285
+ effect_short_forms = {
286
+ 'burning': 'Burning Flames',
287
+ 'scorching': 'Scorching Flames',
288
+ 'green energy': 'Green Energy',
289
+ 'purple energy': 'Purple Energy',
290
+ 'circling tf': 'Circling TF Logo',
291
+ 'massed': 'Massed Flies',
292
+ 'nuts': 'Nuts n\' Bolts',
293
+ 'p fetti': 'Purple Confetti',
294
+ 'g fetti': 'Green Confetti',
295
+ 'haunted': 'Haunted Ghosts',
296
+ 'green black hole': 'Green Black Hole',
297
+ 'roboactive': 'Roboactive',
298
+ 'sulph': 'Sulphurous',
299
+ 'phos': 'Phosphorous',
300
+ 'c&d': 'Circling Peace Sign',
301
+ 'peace': 'Circling Peace Sign',
302
+ 'logo': 'Circling TF Logo',
303
+ 'hearts': 'Circling Heart',
304
+ 'tf logo': 'Circling TF Logo',
305
+ 'heart': 'Circling Heart',
306
+ 'frostbite': 'Frostbite',
307
+ 'scorching': 'Scorching Flames',
308
+ 'plasma': 'Vivid Plasma',
309
+ 'searing': 'Searing Plasma',
310
+ 'miami': 'Miami Nights',
311
+ 'disco': 'Disco Beat Down',
312
+ 'phosph': 'Phosphorous',
313
+ 'sulph': 'Sulphurous',
314
+ 'memory': 'Memory Leak',
315
+ 'overclocked': 'Overclocked',
316
+ 'electrostatic': 'Electrostatic',
317
+ 'harvest': 'Harvest Moon',
318
+ 'bonzo': 'Bonzo The All-Gnawing',
319
+ 'antifreeze': 'Anti-Freeze',
320
+ 'arcana': 'Arcana',
321
+ 'spellbound': 'Spellbound',
322
+ }
323
+
324
+ for short_form, full_effect in effect_short_forms.items():
325
+ if short_form in name_lower:
326
+ for effect_name, effect_id in schema.effects.items():
327
+ if effect_name == full_effect:
328
+ name_lower = name_lower.replace(short_form, '').strip()
329
+ item['effect'] = effect_id
330
+ if item['quality'] != 5:
331
+ item['quality2'] = item['quality'] or item['quality2']
332
+ item['quality'] = 5
333
+ break
334
+ if item['effect']:
335
+ break
336
+
337
+ if not item['effect']:
338
+ for effect_name, effect_id in schema.effects.items():
339
+ effect_lower = effect_name.lower()
340
+
341
+ if effect_lower == 'stardust' and 'starduster' in name_lower:
342
+ if 'starduster' in name_lower.replace('stardust', ''):
343
+ continue
344
+
345
+ if effect_lower == 'showstopper' and 'taunt: ' not in name_lower and 'shred alert' not in name_lower:
346
+ continue
347
+
348
+ if effect_lower == 'smoking' and name_lower in ['smoking jacket', 'the smoking skid lid'] or 'smoking skid lid' in name_lower:
349
+ if not name_lower.startswith('smoking smoking'):
350
+ continue
351
+
352
+ if effect_lower in ['haunted ghosts', 'pumpkin patch', 'stardust'] and item['wear']:
353
+ continue
354
+
355
+ if effect_lower == 'atomic' and ('subatomic' in name_lower or any(x in name_lower for x in ['bonk! atomic punch', 'atomic accolade'])):
356
+ continue
357
+
358
+ if effect_lower == 'spellbound' and ('taunt:' in name_lower or 'shred alert' in name_lower):
359
+ continue
360
+
361
+ if effect_lower == 'accursed' and 'accursed apparition' in name_lower:
362
+ continue
363
+
364
+ if effect_lower == 'haunted' and 'haunted kraken' in name_lower:
365
+ continue
366
+
367
+ if effect_lower == 'frostbite' and 'frostbite bonnet' in name_lower:
368
+ continue
369
+
370
+ if effect_lower == 'hot' and not item['wear']:
371
+ continue
372
+
373
+ if effect_lower == 'cool' and not item['wear']:
374
+ continue
375
+
376
+ if effect_lower in name_lower:
377
+ name_lower = name_lower.replace(effect_lower, '').strip()
378
+ item['effect'] = effect_id
379
+
380
+ if effect_id == 4: # Community Sparkle
381
+ if not item['quality']:
382
+ item['quality'] = 5
383
+ elif item['quality'] != 5:
384
+ item['quality2'] = item['quality'] or item['quality2']
385
+ item['quality'] = 5
386
+
387
+ break
388
+
389
+ if item['wear']:
390
+ for paintkit_name, paintkit_id in schema.paintkits.items():
391
+ paintkit_lower = paintkit_name.lower()
392
+
393
+ if 'mk.ii' in name_lower and 'mk.ii' not in paintkit_lower:
394
+ continue
395
+
396
+ if '(green)' in name_lower and '(green)' not in paintkit_lower:
397
+ continue
398
+
399
+ if 'chilly' in name_lower and 'chilly' not in paintkit_lower:
400
+ continue
401
+
402
+ if paintkit_lower in name_lower:
403
+ name_lower = name_lower.replace(paintkit_lower, '').replace(' | ', '').strip()
404
+ item['paintkit'] = paintkit_id
405
+
406
+ if item['effect'] is not None:
407
+ if item['quality'] == 5 and item['quality2'] == 11:
408
+ if 'strange(e)' not in name.lower():
409
+ item['quality'] = 11
410
+ item['quality2'] = None
411
+ else:
412
+ item['quality'] = 15
413
+ elif item['quality'] == 5 and not item['quality2']:
414
+ item['quality'] = 15
415
+
416
+ if not item['quality']:
417
+ item['quality'] = 15
418
+
419
+ break
420
+
421
+ if 'war paint' not in name_lower and item['paintkit']:
422
+ Sku._handle_weapon_skins(name_lower, item, schema)
423
+
424
+ if '(paint: ' in name_lower:
425
+ name_lower = name_lower.replace('(paint: ', '').replace(')', '').strip()
426
+
427
+ paint_key = f"(paint: {name_lower})"
428
+ if paint_key in schema.PAINT_MAPPINGS:
429
+ item['paint'] = schema.PAINT_MAPPINGS[paint_key]
430
+ # Remove paint name from name_lower
431
+ for paint_name, paint_value in schema.paints.items():
432
+ if paint_value == item['paint'] and paint_name.lower() in name_lower:
433
+ name_lower = name_lower.replace(paint_name.lower(), '').strip()
434
+ break
435
+
436
+ name_lower = Sku._process_special_items(name_lower, item, schema)
437
+
438
+ name_lower = name_lower.replace(' series ', ' ').replace(' series#', ' #')
439
+
440
+ if 'salvaged mann co. supply crate #' in name_lower:
441
+ item['crateseries'] = int(name_lower[32:])
442
+ item['defindex'] = 5068
443
+ item['quality'] = 6
444
+ return Sku._dict_to_sku(item)
445
+
446
+ elif 'select reserve mann co. supply crate #' in name_lower:
447
+ item['defindex'] = 5660
448
+ item['crateseries'] = 60
449
+ item['quality'] = 6
450
+ return Sku._dict_to_sku(item)
451
+
452
+ elif 'mann co. supply crate #' in name_lower:
453
+ crateseries = int(name_lower[23:])
454
+
455
+ if crateseries in [1, 3, 7, 12, 13, 18, 19, 23, 26, 31, 34, 39, 43, 47, 54, 57, 75]:
456
+ item['defindex'] = 5022
457
+ elif crateseries in [2, 4, 8, 11, 14, 17, 20, 24, 27, 32, 37, 42, 44, 49, 56, 71, 76]:
458
+ item['defindex'] = 5041
459
+ elif crateseries in [5, 9, 10, 15, 16, 21, 25, 28, 29, 33, 38, 41, 45, 55, 59, 77]:
460
+ item['defindex'] = 5045
461
+
462
+ item['crateseries'] = crateseries
463
+ item['quality'] = 6
464
+ return Sku._dict_to_sku(item)
465
+
466
+ elif 'mann co. supply munition #' in name_lower:
467
+ crateseries = int(name_lower[26:])
468
+ item['defindex'] = schema.MUNITION_CRATES.get(crateseries)
469
+ item['crateseries'] = crateseries
470
+ item['quality'] = 6
471
+ return Sku._dict_to_sku(item)
472
+
473
+ number = None
474
+ if '#' in name_lower:
475
+ match = re.search(r'#(\d+)', name_lower)
476
+ if match:
477
+ number = match.group(1)
478
+ name_lower = re.sub(r'#\d+', '', name_lower).strip()
479
+
480
+ retired_key_names = [key['name'].lower() for key in schema.RETIRED_KEYS.values()]
481
+ if name_lower in retired_key_names:
482
+ for key in schema.RETIRED_KEYS.values():
483
+ if key['name'].lower() == name_lower:
484
+ item['defindex'] = key['defindex']
485
+ item['quality'] = item['quality'] or 6
486
+ return Sku._dict_to_sku(item)
487
+
488
+ schema_item = schema.get_item_by_item_name_with_the(name_lower)
489
+ if not schema_item:
490
+ raise ValueError(f"Failed to get SKU from name: {name}")
491
+
492
+ item['defindex'] = schema_item['defindex']
493
+ item['quality'] = item['quality'] or schema_item.get('item_quality', 6)
494
+
495
+ if item['quality'] == 1 and item['defindex'] in schema.EXCLUSIVE_GENUINE:
496
+ item['defindex'] = schema.EXCLUSIVE_GENUINE[item['defindex']]
497
+
498
+ if schema_item.get('item_class') == 'supply_crate':
499
+ item['crateseries'] = schema.crate_series_list.get(item['defindex'])
500
+ elif number:
501
+ item['craftnumber'] = int(number)
502
+
503
+ return Sku._dict_to_sku(item)
504
+
505
+ @staticmethod
506
+ def _process_special_items(name_lower: str, item: dict, schema: Schema) -> str:
507
+
508
+ if 'kit fabricator' in name_lower and item['killstreak'] > 1:
509
+ name_lower = name_lower.replace('kit fabricator', '').strip()
510
+ item['defindex'] = 20003 if item['killstreak'] > 2 else 20002
511
+
512
+ if name_lower:
513
+ schema_item = schema.get_item_by_item_name(name_lower)
514
+ if schema_item:
515
+ item['target'] = schema_item['defindex']
516
+ item['quality'] = item['quality'] or schema_item.get('item_quality', 6)
517
+
518
+ if not item['quality']:
519
+ item['quality'] = 6
520
+
521
+ item['output'] = 6526 if item['killstreak'] > 2 else 6523
522
+ item['outputQuality'] = 6
523
+
524
+ elif (("collector's" not in name_lower or 'strangifier chemistry set' not in name_lower) and
525
+ 'chemistry set' in name_lower):
526
+ name_lower = name_lower.replace("collector's ", '').replace('chemistry set', '').strip()
527
+
528
+ if 'festive' in name_lower and 'a rather festive tree' not in name_lower:
529
+ item['defindex'] = 20007
530
+ else:
531
+ item['defindex'] = 20006
532
+
533
+ schema_item = schema.get_item_by_item_name(name_lower)
534
+ if schema_item:
535
+ item['output'] = schema_item['defindex']
536
+ item['outputQuality'] = 14
537
+ item['quality'] = item['quality'] or schema_item.get('item_quality', 6)
538
+
539
+ elif 'strangifier chemistry set' in name_lower:
540
+ name_lower = name_lower.replace('strangifier chemistry set', '').strip()
541
+
542
+ schema_item = schema.get_item_by_item_name(name_lower)
543
+ if schema_item:
544
+ item['defindex'] = 20000
545
+ item['target'] = schema_item['defindex']
546
+ item['quality'] = 6
547
+ item['output'] = 6522
548
+ item['outputQuality'] = 6
549
+
550
+ elif 'strangifier' in name_lower:
551
+ name_lower = name_lower.replace('strangifier', '').strip()
552
+ item['defindex'] = 6522
553
+
554
+ schema_item = schema.get_item_by_item_name(name_lower)
555
+ if schema_item:
556
+ item['target'] = schema_item['defindex']
557
+ item['quality'] = item['quality'] or schema_item.get('item_quality', 6)
558
+
559
+ elif 'kit' in name_lower and item['killstreak']:
560
+ name_lower = name_lower.replace('kit', '').strip()
561
+
562
+ if item['killstreak'] == 1:
563
+ item['defindex'] = 6527
564
+ elif item['killstreak'] == 2:
565
+ item['defindex'] = 6523
566
+ elif item['killstreak'] == 3:
567
+ item['defindex'] = 6526
568
+
569
+ if name_lower:
570
+ schema_item = schema.get_item_by_item_name(name_lower)
571
+ if schema_item:
572
+ item['target'] = schema_item['defindex']
573
+
574
+ if not item['quality']:
575
+ item['quality'] = 6
576
+
577
+ elif item['paintkit'] and 'war paint' in name_lower:
578
+ name_lower = f"Paintkit {item['paintkit']}"
579
+ if not item['quality']:
580
+ item['quality'] = 15
581
+
582
+ for schema_item in schema.raw['schema']['items']:
583
+ if schema_item.get('name') == name_lower:
584
+ item['defindex'] = schema_item['defindex']
585
+ break
586
+
587
+ return name_lower
588
+
589
+ @staticmethod
590
+ def _handle_weapon_skins(name_lower: str, item: dict, schema: Schema):
591
+ """Handle weapon skin defindex mapping"""
592
+ if 'pistol' in name_lower and item['paintkit'] in schema.PISTOL_SKINS:
593
+ item['defindex'] = schema.PISTOL_SKINS[item['paintkit']]
594
+ elif 'rocket launcher' in name_lower and item['paintkit'] in schema.ROCKET_LAUNCHER_SKINS:
595
+ item['defindex'] = schema.ROCKET_LAUNCHER_SKINS[item['paintkit']]
596
+ elif 'medi gun' in name_lower and item['paintkit'] in schema.MEDIGUN_SKINS:
597
+ item['defindex'] = schema.MEDIGUN_SKINS[item['paintkit']]
598
+ elif 'revolver' in name_lower and item['paintkit'] in schema.REVOLVER_SKINS:
599
+ item['defindex'] = schema.REVOLVER_SKINS[item['paintkit']]
600
+ elif 'stickybomb launcher' in name_lower and item['paintkit'] in schema.STICKYBOMB_SKINS:
601
+ item['defindex'] = schema.STICKYBOMB_SKINS[item['paintkit']]
602
+ elif 'sniper rifle' in name_lower and item['paintkit'] in schema.SNIPER_RIFLE_SKINS:
603
+ item['defindex'] = schema.SNIPER_RIFLE_SKINS[item['paintkit']]
604
+ elif 'flame thrower' in name_lower and item['paintkit'] in schema.FLAME_THROWER_SKINS:
605
+ item['defindex'] = schema.FLAME_THROWER_SKINS[item['paintkit']]
606
+ elif 'minigun' in name_lower and item['paintkit'] in schema.MINIGUN_SKINS:
607
+ item['defindex'] = schema.MINIGUN_SKINS[item['paintkit']]
608
+ elif 'scattergun' in name_lower and item['paintkit'] in schema.SCATTERGUN_SKINS:
609
+ item['defindex'] = schema.SCATTERGUN_SKINS[item['paintkit']]
610
+ elif 'shotgun' in name_lower and item['paintkit'] in schema.SHOTGUN_SKINS:
611
+ item['defindex'] = schema.SHOTGUN_SKINS[item['paintkit']]
612
+ elif 'smg' in name_lower and item['paintkit'] in schema.SMG_SKINS:
613
+ item['defindex'] = schema.SMG_SKINS[item['paintkit']]
614
+ elif 'grenade launcher' in name_lower and item['paintkit'] in schema.GRENADE_LAUNCHER_SKINS:
615
+ item['defindex'] = schema.GRENADE_LAUNCHER_SKINS[item['paintkit']]
616
+ elif 'wrench' in name_lower and item['paintkit'] in schema.WRENCH_SKINS:
617
+ item['defindex'] = schema.WRENCH_SKINS[item['paintkit']]
618
+ elif 'knife' in name_lower and item['paintkit'] in schema.KNIFE_SKINS:
619
+ item['defindex'] = schema.KNIFE_SKINS[item['paintkit']]
620
+
621
+ @staticmethod
622
+ def _dict_to_sku(item: dict) -> str:
623
+ """Convert item dict to SKU string"""
624
+ item_obj = itemClass()
625
+ item_obj.Defindex = item['defindex']
626
+ item_obj.Quality = item['quality']
627
+ item_obj.Craftable = item['craftable']
628
+ item_obj.Australium = item['australium']
629
+ item_obj.Festive = item['festive']
630
+ item_obj.Killstreak = item['killstreak']
631
+ item_obj.Effect = item['effect']
632
+ item_obj.PaintKit = item['paintkit']
633
+ item_obj.Wear = item['wear']
634
+ item_obj.ElevatedQuality = item['quality2']
635
+ item_obj.Target = item['target']
636
+ item_obj.CraftNum = item['craftnumber']
637
+ item_obj.CrateSn = item['crateseries']
638
+ item_obj.Output = item['output']
639
+ item_obj.OutputQuality = item['outputQuality']
640
+
641
+ return Sku.object_to_sku(item_obj)
642
+
643
+ @staticmethod
644
+ def update_schema(api_key: str = None, use_autobot: bool = True):
645
+ global _schema
646
+ cache_file = Schema.SCHEMA_CACHE_FILE
647
+ if cache_file.exists():
648
+ cache_file.unlink()
649
+ _schema = Schema(api_key=api_key, use_autobot=use_autobot)