Works
This commit is contained in:
		
							parent
							
								
									4c5d5160d2
								
							
						
					
					
						commit
						02c36c06ca
					
				| @ -1,3 +1,3 @@ | ||||
| # BackpackDecalSpotter | ||||
| 
 | ||||
| Finds decaled items on Backpack.tf | ||||
| Finds decaled items on Backpack.tf. Relies on legacy soon-to-be-deprecated endpoints. Should be hosted to avoid "Access to Image from origin 'null' has been blocked by CORS policy" errors when fetching accounts with decaled item listings. | ||||
							
								
								
									
										
											BIN
										
									
								
								favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 15 KiB | 
							
								
								
									
										20
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <html> | ||||
| 
 | ||||
| <head> | ||||
|     <title>Backpack Decal Spotter</title> | ||||
| 
 | ||||
|     <link rel="stylesheet" type="text/css" href="style.css" /> | ||||
|     <link rel="shortcut icon" href="favicon.ico"> | ||||
|     <meta name="title" content="Backpack Decal Spotter"> | ||||
|     <meta name="description" content="Finds decaled items on Backpack.tf"> | ||||
|     <meta name="author" content="Abhorrent_Anger"> | ||||
|     <script src="https://code.jquery.com/jquery-3.7.1.min.js" | ||||
|         integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> | ||||
|     <script src="script.js"></script> | ||||
| </head> | ||||
| 
 | ||||
| <body> | ||||
|     <h4 id="empty-accounts" style='display:none'>No decaled items from </h4> | ||||
| </body> | ||||
| 
 | ||||
| </html> | ||||
							
								
								
									
										117
									
								
								script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								script.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | ||||
| var checkable_accounts = { '76561198311319887': 'Weapon Crusher' }; | ||||
| decaled_objects = { 'Conscientious Objector': '3.66', 'Clan Pride': '2.11', 'Flair!': '4.22', 'Photo Badge': '2.44' } | ||||
| backpack_page_limit = 3; | ||||
| 
 | ||||
| function fetchAccounts() { | ||||
|     var deferred = new $.Deferred(); | ||||
|     for (const [item, price] of Object.entries(decaled_objects)) { | ||||
|         handleItem(item, price); | ||||
|     } | ||||
|     deferred.resolve(checkable_accounts); | ||||
|     return deferred.promise() | ||||
| } | ||||
| 
 | ||||
| function handleItem(item, price) { | ||||
|     for (let i = 1; i <= backpack_page_limit; i++) { | ||||
|         $.ajax({ | ||||
|             dataType: 'html', | ||||
|             url: 'https://backpack.tf/classifieds', | ||||
|             data: 'page=' + i + '&item=' + encodeURIComponent(item) + '&quality=6&tradable=1&craftable=1&australium=-1&killstreak_tier=0&numeric=price&comparison=lt&value=' + price + '&low=' + price, | ||||
|             async: false, | ||||
|             tryCount: 0, | ||||
|             retryLimit: 3, | ||||
|             success: function (msg) { | ||||
|                 if ($('.col-md-6:first .alert', msg).length > 0) { | ||||
|                     return false; | ||||
|                 } | ||||
|                 $('.col-md-6:first .user-link', msg).each(function () { | ||||
|                     checkable_accounts[$(this).attr('data-id')] = $(this).attr('data-name'); | ||||
|                 }); | ||||
|             }, | ||||
|             error: function (response, status, error) { | ||||
|                 if (response.status == 429) { | ||||
|                     this.tryCount++; | ||||
|                     if (this.tryCount <= this.retryLimit) { | ||||
|                         setTimeout(() => { | ||||
|                             $.ajax(this); | ||||
|                         }, 3000); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function handleAccounts() { | ||||
|     for (const [steamid64, name] of Object.entries(checkable_accounts)) { | ||||
|         handleAccount(steamid64, name); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function handleAccount(steamid64, name) { | ||||
|     var url = "https://backpack.tf/_inventory/" + steamid64; | ||||
|     $.ajax({ | ||||
|         dataType: 'json', | ||||
|         url: url, | ||||
|         async: false, | ||||
|         tryCount: 0, | ||||
|         retryLimit: 3, | ||||
|         success: function (msg) { handleHTML(steamid64, name, msg['html']); }, | ||||
|         error: function (response, status, error) { | ||||
|             if (response.status == 429) { | ||||
|                 this.tryCount++; | ||||
|                 if (this.tryCount <= this.retryLimit) { | ||||
|                     setTimeout(() => { | ||||
|                         $.ajax(this); | ||||
|                     }, 3000); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function handleHTML(steamid64, name, html_string) { | ||||
|     html = $.parseHTML(html_string); | ||||
|     var decaled_items = $('div.decal', html); | ||||
|     if (decaled_items.length == 0) { | ||||
|         var empty_accounts = $('#empty-accounts'); | ||||
|         empty_accounts.append('<a href="https://next.backpack.tf/profiles/' + steamid64 + '">' + name + '</a>; '); | ||||
|         empty_accounts.fadeIn(); | ||||
|         return false; | ||||
|     } | ||||
|     var inventory = $('<div class="inventory"></div>'); | ||||
|     inventory.append('<a href="https://next.backpack.tf/profiles/' + steamid64 + '"><h3>' + name + '</h3></a>'); | ||||
|     decaled_items.each(function () { | ||||
|         var url = "https://next.backpack.tf/item/" + $(this).parent().attr('data-id'); | ||||
|         var a = $('<a href="' + url + '"></a>'); | ||||
|         a.append($(this).parent()); | ||||
|         inventory.append(a); | ||||
|     }); | ||||
|     var inventories = $('.inventory'); | ||||
|     if (inventories.length > 0) { | ||||
|         var child_count = inventory.children().length; | ||||
|         inventory.attr('data-items', child_count); | ||||
|         var last_div = null; | ||||
|         inventories.each(function () { | ||||
|             if (child_count > $(this).children().length) { | ||||
|                 return false; | ||||
|             } | ||||
|             last_div = $(this); | ||||
|         }); | ||||
|         if (last_div) { | ||||
|             last_div.after(inventory); | ||||
|         } else { | ||||
|             $('body').prepend(inventory); | ||||
|         } | ||||
|     } else { | ||||
|         $('#empty-accounts').before(inventory); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
|     $.when(fetchAccounts()).done(function () { | ||||
|         handleAccounts(); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										119
									
								
								style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								style.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| body { | ||||
|     background-color: #111; | ||||
|     color: #eee; | ||||
|     font-family: Verdana, Geneva, sans-serif; | ||||
|     font-size: 0.85em; | ||||
|     margin: 0px; | ||||
|     text-align: justify; | ||||
|     text-justify: inter-word; | ||||
|     word-wrap: break-word; | ||||
|     word-break: break-all; | ||||
|     white-space: normal; | ||||
|     text-align: center; | ||||
| } | ||||
| 
 | ||||
| div { | ||||
|     display: inline-block; | ||||
| } | ||||
| 
 | ||||
| h3 { | ||||
|     text-align: center; | ||||
|     padding: 0.5em; | ||||
| } | ||||
| 
 | ||||
| h4 { | ||||
|     color: #555; | ||||
|     text-align: center; | ||||
|     padding: 5em; | ||||
| } | ||||
| 
 | ||||
| li { | ||||
|     display: inline-block; | ||||
|     width: 140px; | ||||
|     height: 140px; | ||||
|     position: relative; | ||||
|     border-radius: 3px; | ||||
|     margin: 10px; | ||||
|     border: 3px solid; | ||||
|     margin-bottom: 38px; | ||||
| } | ||||
| 
 | ||||
| .decal { | ||||
|     width: 128px; | ||||
|     height: 128px; | ||||
|     margin: auto; | ||||
|     z-index: 2; | ||||
|     position: absolute; | ||||
|     top: 6px; | ||||
|     left: 6px; | ||||
| } | ||||
| 
 | ||||
| .item-icon { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
|     bottom: -38px; | ||||
|     left: -3px; | ||||
|     background-size: 24px; | ||||
|     z-index: 1; | ||||
|     position: absolute; | ||||
|     border-radius: 3px; | ||||
|     border: 3px solid; | ||||
| } | ||||
| 
 | ||||
| .q-440-6, | ||||
| .q-440-6 .item-icon, | ||||
| .q-440-6 .bottom-right { | ||||
|     background-color: rgb(119, 101, 3); | ||||
|     border-color: rgb(181, 154, 5); | ||||
| } | ||||
| 
 | ||||
| .q-440-11, | ||||
| .q-440-11 .item-icon , | ||||
| .q-440-11 .bottom-right { | ||||
|     background-color: rgb(110, 56, 26); | ||||
|     border-color: rgb(144, 73, 34); | ||||
| } | ||||
| 
 | ||||
| .nocraft { | ||||
|     border-style: dashed; | ||||
| } | ||||
| 
 | ||||
| .top-left { | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| .bottom-right { | ||||
|     position: absolute; | ||||
|     width: 105px; | ||||
|     height: 24px; | ||||
|     bottom: -38px; | ||||
|     left: 32px; | ||||
|     border-radius: 3px; | ||||
|     border: 3px solid; | ||||
|     margin: auto; | ||||
| } | ||||
| 
 | ||||
| .bottom-right span { | ||||
|     text-align: center; | ||||
|     display: block; | ||||
|     margin-top: 3px; | ||||
| } | ||||
| 
 | ||||
| a, | ||||
| a:link, | ||||
| a:visited, | ||||
| a:hover, | ||||
| a:active { | ||||
|     text-decoration: none; | ||||
|     color: #eee; | ||||
| } | ||||
| 
 | ||||
| h4 a, | ||||
| h4 a:link, | ||||
| h4 a:visited, | ||||
| h4 a:hover, | ||||
| h4 a:active { | ||||
|     text-decoration: none; | ||||
|     color: #555; | ||||
|     font-style: italic; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user