| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- const {
- describe,
- test,
- expect,
- } = require('@jest/globals')
- const { WebDriver } = require('../common/web_driver')
- const {
- inflate,
- deflate,
- } = require('pako')
- const fs = require('fs')
- const path = require('node:path')
- const root = require('./hotconi/proto/market.v2.trade')
- // Static code + Reflection + .proto parser
- const timeout = 9999999
- async function sleep (ms) {
- return new Promise(resolve => setTimeout(resolve, ms))
- }
- describe('hotcoin站点测试', () => {
- let targetInfo = {
- 'targetId': '',
- 'type': '',
- 'title': '',
- 'url': '',
- 'attached': true,
- 'canAccessOpener': false,
- 'browserContextId': '',
- }
- const driver = new WebDriver({
- // port: 23035,
- })
- const init = async () => {
- // await driver.setProxy('socks://localhost:8880')
- await driver.setProxy('http://172.16.1.132:3128')
- await driver.builder()
- let target = await driver.cdp.Target
- targetInfo = await target.getTargetInfo()
- console.info('info>>>>', targetInfo)
- }
- const baseUrl = 'https://www.hotcoin.com/'
- const prefix = 'hotcoin'
- let cookiesPath = path.join(__dirname, 'tmp', prefix + '_cookies')
- let storagePath = path.join(__dirname, 'tmp', prefix + '_storage')
- test('测试打开', async (done) => {
- await init()
- const page = driver.cdp.Page
- page.navigate({ url: baseUrl })
- done()
- }, timeout)
- const login = async (Storage, Runtime) => {
- let cookie = '', localStorage = ''
- if (fs.existsSync(cookiesPath)) {
- cookie = fs.readFileSync(cookiesPath, 'utf8')
- }
- // 借助localStorage中的jwt信息登录
- if (fs.existsSync(storagePath)) {
- localStorage = fs.readFileSync(storagePath, 'utf8')
- }
- if (cookie) {
- await Storage.setCookies(JSON.parse(cookie))
- }
- if (localStorage) {
- let storage = {}
- try {
- storage = JSON.parse(`${localStorage}`) ||{}
- } catch (e) {
- console.error(e)
- }
- // let script = `
- // for (const k in storage) {
- // localStorage.setItem(k,storage[k]);
- // }
- // `
- // script=`
- // localStorage.setItem('aaa','bbb')
- // `
- // await Runtime.evaluate({
- // expression: `localStorage.setItem('aaa','>>>>>')`,
- // // awaitPromise: true,
- // });
- for (const k in storage) {
- await Runtime.evaluate({
- expression: `localStorage.setItem(\`${k}\`, \`${storage[k]}\`)`,
- // awaitPromise: true,
- })
- }
- }
- }
- test('自动登录', async (done) => {
- await init()
- const {
- Storage,
- Page,
- Runtime,
- } = driver.cdp
- await Runtime.enable()
- try {
- Page.navigate({ url: baseUrl })
- await login(Storage, Runtime)
- let t = Date.now()
- let s = setInterval(async () => {
- let cookies = await Storage.getCookies()
- fs.writeFileSync(cookiesPath, JSON.stringify(cookies), 'utf8')
- let localStorage = await Runtime.evaluate({
- expression: 'JSON.stringify(localStorage)',
- })
- fs.writeFileSync(storagePath, localStorage?.result?.value, 'utf8')
- if (Date.now() - t > 5 * 60 * 1000) {
- clearInterval(s)
- }
- }, 1000)
- } catch (e) {
- console.error(e)
- }
- await sleep(timeout)
- done()
- }, timeout)
- test('监听wss', async (done) => {
- await init()
- const {
- Storage,
- Page,
- Network,
- Runtime,
- } = driver.cdp
- Network.enable()
- Page.navigate({ url: baseUrl })
- await login(Storage, Runtime)
- //这个网站连接了3个wss,不同的wss的数据结构不一样。
- // "wss://wsw.spentr.com/trade/multiple",
- //"wss://wcws.spentr.com/",
- const requestInfo = {}
- const decodeWsw = (data) => {
- let res = inflate(data/* , { to: 'string' } */)
- console.info('解压缩结果:', res)
- switch (res) {
- case 'pong':
- return res
- default: {
- let root = require('./hotconi/proto/market.v2.trade')
- let response = root.market.v2.trade.Response.decode(res)
- let object = response.toJSON()
- console.info('=decodeWsw==>', object)
- }
- }
- }
- const decodeWsws = (data) => {
- let res = inflate(data/* , { to: 'string' } */)
- //字符串中有2个隐藏字符 DCC EM
- let regex = new RegExp('(\\n|' + String.fromCharCode(18) + '|' + String.fromCharCode(30)+ '|' + String.fromCharCode(31) + ')', 'g')
- let keys = inflate(data, { to: 'string' }).split(regex).filter(s => (s || '').includes('type.googleapis.com')).flatMap(s => (s || '').split('/'))
- // CommonPbMsg
- console.info('解压缩结果:', res)
- switch (res) {
- case 'pong':
- return res
- default: {
- let root = require('./hotconi/proto/' + (keys.join('.') || '').replaceAll('"', ''))
- let response = root.type.googleapis.com[keys[1]].Response.decode(res)
- let object = response.toJSON()
- console.info('=decodeWsws==>', object)
- }
- }
- }
- // 一个二进制数据流还原
- // opcode number WebSocket message opcode.
- // mask boolean WebSocket message mask.
- // payloadData string WebSocket message payload data. If the opcode is 1, this is a text message and payloadData is a UTF-8 string.
- // If the opcode isn't 1, then payloadData is a base64 encoded string representing binary data.
- const formatResponse = (params = {
- requestId: '',
- timestamp: '',
- response: {
- opcode: 1,
- mask: false,
- payloadData: '',
- },
- }) => {
- try {
- if (!params.response?.opcode) {
- return params.response
- }
- if (params.response?.opcode === 1) {
- return params.response.payloadData
- }
- const binaryData = Buffer.from(params.response.payloadData, 'base64')
- let res = {}
- if ((requestInfo[params.requestId].url || '').includes('wsw.spentr.com')) {
- res = decodeWsw(binaryData)
- } else if ((requestInfo[params.requestId].url || '').includes('wcws.spentr.com')) {
- res = decodeWsws(binaryData)
- }
- console.info('结果解析:', res)
- } catch (e) {
- console.error(e)
- }
- }
- Network.requestWillBeSent((params) => {
- console.log('Request Headers:', params.request.headers);
- });
- Network.webSocketCreated(params => {
- console.log('WebSocket created:', params.url)
- requestInfo[params.requestId] = {
- url: params.url,
- }
- })
- // 订阅 Network.webSocketFrameSent 和 Network.webSocketFrameReceived 事件,监听 WebSocket 帧的发送和接收:
- // 订阅 Network.webSocketClosed 事件,监听 WebSocket 连接的关闭:
- Network.webSocketClosed(params => {
- console.log('WebSocket closed:', params.closeCode, params.closeReason)
- // formatResponse(params)
- })
- // 订阅Network.webSocketWillSendHandshakeRequest事件,拦截WebSocket连接的握手请求:
- Network.webSocketWillSendHandshakeRequest(params => {
- console.log('WebSocket handshake request:', params.request)
- // formatResponse(params)
- })
- // 订阅Network.webSocketHandshakeResponseReceived事件,拦截WebSocket连接的握手响应:
- Network.webSocketHandshakeResponseReceived(params => {
- console.log('WebSocket handshake response:', params.response)
- let data = formatResponse(params)
- console.info('webSocketHandshakeResponseReceived解析结果:', data)
- })
- // 订阅Network.webSocketFrameSent和Network.webSocketFrameReceived事件,拦截WebSocket数据帧的发送和接收:
- Network.webSocketFrameSent(params => {
- console.log('WebSocket frame sent:', params.response)
- // formatResponse(params)
- })
- Network.webSocketFrameReceived(params => {
- // console.log('WebSocket frame received:', params.response)
- console.info('webSocketFrameReceived 回复', params.response)
- let data = formatResponse(params)
- console.info('webSocketFrameReceived解析结果:', data)
- })
- Network.webSocketFrameError(params => {
- console.log('WebSocket frame error:', params.response)
- // let data = formatResponse(params)
- // console.info('webSocketFrameError解析结果:', data)
- })
- await sleep(timeout)
- done()
- }, timeout)
- test('拆包', done => {
- let str = `0{"sid":"b6535f35-3047-4f12-9cd3-c526b39cd019","upgrades":["websocket"],"pingInterval":30000,"pingTimeout":60000}`
- while (/^\d/.test(str)) {
- str = str.substring(1)
- }
- try {
- JSON.parse(str)
- } catch (e) {
- console.error(e)
- }
- console.info(str)
- done()
- })
- })
|