GetDYSKUID

show sku id for douyin

  1. // ==UserScript==
  2. // @name GetDYSKUID
  3. // @namespace supermeatboy@getdyskuid
  4. // @version 0.4
  5. // @description show sku id for douyin
  6. // @author supermeatboy
  7. // @match https://haohuo.jinritemai.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=haohuo.jinritemai.com
  9. // @grant none
  10. // @run-at document-start
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. let oldfetch = fetch;
  18. let skuMetaMapping = {}
  19. let skuSpecNameToID = {}
  20. let maxRetry = 20
  21. let retryCount = 1
  22. var selectSkuList = {}
  23.  
  24. let interceptor = {
  25. urls: ['/aweme/v2/shop/promotion/pack/h5'],
  26. originalXHR: window.XMLHttpRequest,
  27. myXHR: function () {
  28.  
  29. let isScriptDispatched = false
  30. const modifyResponse = () => {
  31. if(isScriptDispatched) {
  32. return
  33. }
  34. // console.info("trigger modifyResponse", xhr.responseType)
  35. let matchUrls = interceptor.urls.filter(url => xhr.responseURL.indexOf(url) > -1)
  36. let match = matchUrls.length > 0
  37. if (match) {
  38. let data;
  39. if (!xhr.responseType || xhr.responseType === "text") {
  40. data = xhr.responseText;
  41. } else if (xhr.responseType === "document") {
  42. data = xhr.responseXML;
  43. } else {
  44. data = xhr.response;
  45. }
  46. // console.info("match", typeof data, data)
  47. let result = JSON.parse(data)
  48. if(result.promotion_h5 && result.promotion_h5.page_meta) {
  49. let pageMeta = result.promotion_h5.page_meta
  50. if(pageMeta.sku_meta && pageMeta.sku_meta.sku_mappings) {
  51. skuMetaMapping = pageMeta.sku_meta.sku_mappings
  52. console.info("hook skuMetaMapping", skuMetaMapping)
  53. }
  54. if(pageMeta.common_meta && pageMeta.common_meta.sku_spec_info) {
  55. let skuSpecList = pageMeta.common_meta.sku_spec_info
  56. for(let i=0; i<skuSpecList.length; i++) {
  57. let specInfo = skuSpecList[i]
  58. for(let j=0; j<specInfo.spec_ids.length;j++) {
  59. skuSpecNameToID[specInfo.spec_names[j]] = specInfo.spec_ids[j]
  60. }
  61. }
  62. console.info("hook skuSpecToName", skuSpecNameToID)
  63. }
  64.  
  65. // 延迟触发显示id
  66. setTimeout(hookBottomButtonClick, 1000)
  67. }
  68. this.responseText = this.response = data
  69. }
  70. isScriptDispatched = true
  71. }
  72. const xhr = new interceptor.originalXHR
  73. for (let attr in xhr) {
  74. if (attr === 'onreadystatechange') {
  75. xhr.onreadystatechange = (...args) => {
  76. if (this.readyState === 4) {
  77. modifyResponse()
  78. }
  79. this.onreadystatechange && this.onreadystatechange.apply(this, args)
  80. }
  81. continue
  82. } else if (attr === 'onload') {
  83. xhr.onload = (...args) => {
  84. modifyResponse()
  85. this.onload && this.onload.apply(this, args)
  86. }
  87. continue
  88. }
  89.  
  90. if (typeof xhr[attr] === 'function') {
  91. this[attr] = xhr[attr].bind(xhr);
  92. } else {
  93. // responseText和response不是writeable的,但拦截时需要修改它,所以修改就存储在this[`_${attr}`]上
  94. if (attr === 'responseText' || attr === 'response') {
  95. Object.defineProperty(this, attr, {
  96. get: () => this[`_${attr}`] == undefined ? xhr[attr] : this[`_${attr}`],
  97. set: (val) => this[`_${attr}`] = val,
  98. enumerable: true
  99. });
  100. } else {
  101. Object.defineProperty(this, attr, {
  102. get: () => xhr[attr],
  103. set: (val) => xhr[attr] = val,
  104. enumerable: true
  105. });
  106. }
  107. }
  108. }
  109. }
  110. }
  111.  
  112.  
  113. window.XMLHttpRequest = interceptor.myXHR
  114.  
  115. // Your code here...
  116. function buildShowNode() {
  117. let newDiv = document.createElement("div");
  118. newDiv.style.width = "100%"
  119. newDiv.style.fontSize = "12px"
  120. let newPre = document.createElement("pre");
  121. newPre.id = "supermeatboy_sku_map"
  122. newPre.innerText = "SKU ID: 待选择全部属性"
  123. newDiv.appendChild(newPre);
  124. return newDiv
  125. }
  126. function hookBottomButtonClick () {
  127. if(retryCount > maxRetry) {
  128. return
  129. }
  130. let doms = document.querySelectorAll(".footer__right-buttons__item")
  131. console.info("hook, bottom", doms)
  132. // 伺机重试
  133. if(!doms || doms.length == 0) {
  134. setTimeout(hookBottomButtonClick, 1000)
  135. retryCount ++
  136. return
  137. }
  138. for(let d of doms) {
  139. d.addEventListener("click", function() {
  140. setTimeout(updateSkuId, 500)
  141. })
  142. }
  143. }
  144. function updateSkuId() {
  145. if(retryCount > maxRetry) {
  146. return
  147. }
  148. let doms = document.querySelectorAll(".cart-sku>div>div:nth-child(2)>div")
  149. console.info("hook doms", doms)
  150. // 伺机重试
  151. if(!doms || doms.length == 0) {
  152. setTimeout(updateSkuId, 1000)
  153. retryCount ++
  154. return
  155. }
  156. let lastSku = doms[doms.length - 1]
  157. lastSku.parentNode.appendChild(buildShowNode());
  158. console.info("hook lastSku", lastSku)
  159. let skuLevelCount = 0
  160. let skuParentNode = null;
  161. for(let d of doms) {
  162. if(skuParentNode == null || d.parentNode != skuParentNode) {
  163. skuParentNode = d.parentNode
  164. skuLevelCount += 1
  165. }
  166. d.setAttribute("sku_level", skuLevelCount)
  167. d.addEventListener("click", (e) => {
  168. let skuDom = e.target
  169. // 找到所有带有item-highlight的文本
  170. setTimeout(() => {
  171. let allSubDoms = skuParentNode.querySelectorAll("div")
  172. let specKeyList = []
  173. for(let i=0;i<allSubDoms.length;i++) {
  174. let classStr = allSubDoms[i].getAttribute("class")
  175. if(!classStr) {
  176. continue
  177. }
  178. if(classStr.indexOf("item-highlight") > 0) {
  179. let innerText = allSubDoms[i].innerText
  180. let specId = skuSpecNameToID[innerText]
  181. specKeyList.push(specId)
  182. console.info("hook, highlight", innerText, specId)
  183. }
  184. }
  185. console.info("hook, highlight list", specKeyList)
  186. let skuID = skuMetaMapping[specKeyList.join("_")]
  187. var skuMapNode = document.getElementById("supermeatboy_sku_map")
  188. if(!skuID || skuID == undefined) {
  189. skuMapNode.innerText = "SKU ID: 待选择全部属性"
  190. } else {
  191. skuMapNode.innerText = "SKU ID: " + skuID
  192. }
  193. }, 100)
  194.  
  195. });
  196. }
  197. }
  198. //
  199. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址