Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b224c75ad0 | |||
| 945388bdb5 | |||
| ae7c6c13fb | |||
| 4e174a02aa | |||
| 0719dbdf89 | |||
| c487defeed | |||
| 717896d92e | |||
| 6bc925a06b | |||
| d7e96b0b08 | |||
| 2073dd2377 | |||
| 6438e4dbd3 | |||
| c7a619503b | |||
| f591ff14ac | |||
| 0a7657f716 | |||
| 9085a3c1c4 | |||
| 539042881e | |||
| e0b1b2a4f4 | |||
| 727cee69bb | |||
| fcc9ef1b98 | |||
| 38d50c77dc | |||
| e954055042 | |||
| 0cf94d44fc | |||
| 605bc8b252 | |||
| a689e66635 | |||
| 026e06a6b3 | |||
| c98ded5250 | |||
| 02562f1c50 | |||
| 4824f17881 | |||
| 9c06034579 | |||
| e204c4a6da | |||
| 4a33094140 | |||
| 354dbe3f15 | |||
| 93f8367b37 | |||
| 244af8a290 | |||
| 0f75bc03e1 | |||
| 8786280209 | |||
| 04fbf87490 | |||
| cd0f0ebebc | |||
| 6c704d69e3 | |||
| 468fcea934 | |||
| ec18b9bf68 | |||
| 2d54c90d43 | |||
| d8cba15006 | |||
| 5b87938acf | |||
| a789a81fbd | |||
| 02d7b85190 | |||
| 8936129558 | |||
| e6282083ba | |||
| d21f64bfc2 | |||
| 474c9bf339 | |||
| 7eab86c910 | |||
| 57ae14049e | |||
| ca49028e98 | |||
| 32eb83c5d6 | |||
| 9b191be6d6 | |||
| 8a6444cb14 |
@@ -0,0 +1,445 @@
|
|||||||
|
// JSPL的计算过程总结:
|
||||||
|
//
|
||||||
|
// 输入: 传入的会话ID或相关数据
|
||||||
|
// 哈希处理: 使用DJB2算法变种对输入进行哈希
|
||||||
|
// 种子生成: 结合时间戳和常量生成加密种子
|
||||||
|
// 数据收集: 收集各种浏览器指纹和环境信息
|
||||||
|
// 加密处理: 使用自定义的流加密算法对数据进行加密
|
||||||
|
// Base64编码: 最终使用自定义字符集进行Base64编码
|
||||||
|
// 这个函数生成的第三个返回值就是用于JSPL参数的加密字符串
|
||||||
|
var zn = (function () {
|
||||||
|
// 检查是否已经初始化
|
||||||
|
// if (Pn) {
|
||||||
|
// return Nn;
|
||||||
|
// }
|
||||||
|
|
||||||
|
Pn = true;
|
||||||
|
var n = "unknown"; // 默认返回值
|
||||||
|
var constantSeed = 11027890091; // 常量种子
|
||||||
|
var o = true; // 状态标志
|
||||||
|
|
||||||
|
// 字符串哈希函数 - DJB2算法的变种
|
||||||
|
function djb2HashString(str) {
|
||||||
|
if (!str) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
var hash = 0;
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
hash = (hash << 8) - hash + str.charCodeAt(i) | 0;
|
||||||
|
}
|
||||||
|
return hash === 0 ? n : hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 映射函数 - 用于Base64编码的自定义字符集
|
||||||
|
function mapChar(n) {
|
||||||
|
if (n > 37) {
|
||||||
|
return 59 + n;
|
||||||
|
} else if (n > 11) {
|
||||||
|
return 53 + n;
|
||||||
|
} else if (n > 1) {
|
||||||
|
return 46 + n;
|
||||||
|
} else {
|
||||||
|
return n * 50 + 45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 线性同余生成器 - 用于生成伪随机数
|
||||||
|
function lcg(n) {
|
||||||
|
return (n = (n ^= n << 13) ^ n >> 17) ^ n << 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密随机数生成器
|
||||||
|
function createRandomGenerator(seed, initialValue) {
|
||||||
|
var state = seed;
|
||||||
|
var counter = -1;
|
||||||
|
var value = initialValue;
|
||||||
|
var firstCall = o;
|
||||||
|
o = false;
|
||||||
|
var buffer = null;
|
||||||
|
|
||||||
|
return function (peek) {
|
||||||
|
var result;
|
||||||
|
if (buffer !== null) {
|
||||||
|
result = buffer;
|
||||||
|
buffer = null;
|
||||||
|
} else {
|
||||||
|
if (++counter > 2) {
|
||||||
|
state = lcg(state);
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
result = ((result = state >> 16 - counter * 8) ^ (firstCall ? --value : 0)) & 255;
|
||||||
|
if (peek) {
|
||||||
|
buffer = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主加密函数
|
||||||
|
return Nn = function (inputString, additionalData) {
|
||||||
|
// console.log("inputString:" + inputString)
|
||||||
|
// console.log("additionalData:" + additionalData)
|
||||||
|
// 混合输入数据生成种子
|
||||||
|
var seed = constantSeed ^ djb2HashString(inputString) ^ additionalData;
|
||||||
|
|
||||||
|
// 生成基于时间的随机数
|
||||||
|
var timeBasedRandom = lcg(lcg(Date.now() >> 3 ^ constantSeed) * constantSeed);
|
||||||
|
|
||||||
|
// 创建随机数生成器
|
||||||
|
var randomGenerator = createRandomGenerator(seed, timeBasedRandom);
|
||||||
|
|
||||||
|
// 存储加密数据的数组
|
||||||
|
var encryptedData = [];
|
||||||
|
var isFirstCall = true;
|
||||||
|
var callCounter = 0;
|
||||||
|
|
||||||
|
// UTF-8编码和加密函数
|
||||||
|
function utf8EncodeAndEncrypt(str) {
|
||||||
|
var bytes = [];
|
||||||
|
var byteIndex = 0;
|
||||||
|
|
||||||
|
// UTF-8编码
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
var charCode = str.charCodeAt(i);
|
||||||
|
if (charCode < 128) {
|
||||||
|
bytes[byteIndex++] = charCode;
|
||||||
|
} else {
|
||||||
|
if (charCode < 2048) {
|
||||||
|
bytes[byteIndex++] = charCode >> 6 | 192;
|
||||||
|
} else {
|
||||||
|
if ((charCode & 64512) == 55296 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) == 56320) {
|
||||||
|
charCode = 65536 + ((charCode & 1023) << 10) + (str.charCodeAt(++i) & 1023);
|
||||||
|
bytes[byteIndex++] = charCode >> 18 | 240;
|
||||||
|
bytes[byteIndex++] = charCode >> 12 & 63 | 128;
|
||||||
|
} else {
|
||||||
|
bytes[byteIndex++] = charCode >> 12 | 224;
|
||||||
|
}
|
||||||
|
bytes[byteIndex++] = charCode >> 6 & 63 | 128;
|
||||||
|
}
|
||||||
|
bytes[byteIndex++] = charCode & 63 | 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XOR加密
|
||||||
|
for (var j = 0; j < bytes.length; j++) {
|
||||||
|
bytes[j] ^= randomGenerator();
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON序列化函数
|
||||||
|
function safeJsonStringify(obj) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(obj);
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据收集和加密函数
|
||||||
|
function collectAndEncrypt(key, value) {
|
||||||
|
// console.log("key:" + key)
|
||||||
|
// console.log("value:" + value)
|
||||||
|
if (!(typeof key != "string" || key.length == 0 || value && ["number", "string", "boolean"].indexOf(typeof value) == -1)) {
|
||||||
|
let serializedKey = safeJsonStringify(key);
|
||||||
|
// console.log("serializedKey:" + serializedKey)
|
||||||
|
value = safeJsonStringify(value);
|
||||||
|
// console.log("serializedValue:" + value)
|
||||||
|
|
||||||
|
if (key && value !== undefined && key !== "xt1") {
|
||||||
|
// 添加分隔符和加密数据
|
||||||
|
encryptedData.push(randomGenerator() ^ (encryptedData.length ? 44 : 123));
|
||||||
|
Array.prototype.push.apply(encryptedData, utf8EncodeAndEncrypt(serializedKey));
|
||||||
|
encryptedData.push(randomGenerator() ^ 58);
|
||||||
|
Array.prototype.push.apply(encryptedData, utf8EncodeAndEncrypt(value));
|
||||||
|
|
||||||
|
// 第一次调用时添加额外数据
|
||||||
|
if (isFirstCall) {
|
||||||
|
isFirstCall = false;
|
||||||
|
// var hsv = typeof window._hsv == "string" && window._hsv.length > 0 ||
|
||||||
|
// typeof window._hsv == "number" && !isNaN(window._hsv) ? window._hsv : 33;
|
||||||
|
//todo hsv 怎么拿到
|
||||||
|
var hsv = 33;
|
||||||
|
collectAndEncrypt("r3n", hsv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var processedKeys = new Set();
|
||||||
|
|
||||||
|
// 返回三个函数的数组
|
||||||
|
return [
|
||||||
|
// 1. 主要的数据收集函数
|
||||||
|
collectAndEncrypt,
|
||||||
|
|
||||||
|
// 2. 带去重保护的数据收集函数
|
||||||
|
function (key, value) {
|
||||||
|
if (!processedKeys.has(key)) {
|
||||||
|
processedKeys.add(key);
|
||||||
|
collectAndEncrypt(key, value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 3. 最终生成加密字符串的函数
|
||||||
|
function (finalKey) {
|
||||||
|
var finalRandomGen = createRandomGenerator(djb2HashString(finalKey) ^ 1809053797, timeBasedRandom);
|
||||||
|
collectAndEncrypt("bpc", ++callCounter);
|
||||||
|
|
||||||
|
// 对收集的数据进行最终加密
|
||||||
|
var finalEncrypted = [];
|
||||||
|
for (var i = 0; i < encryptedData.length; i++) {
|
||||||
|
finalEncrypted.push(encryptedData[i] ^ finalRandomGen());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加结束标记
|
||||||
|
finalEncrypted.push(randomGenerator(true) ^ 125 ^ finalRandomGen());
|
||||||
|
|
||||||
|
// Base64编码
|
||||||
|
var resultBytes = finalEncrypted;
|
||||||
|
var resultChars = [];
|
||||||
|
var baseValue = timeBasedRandom;
|
||||||
|
|
||||||
|
for (var pos = 0; pos < resultBytes.length;) {
|
||||||
|
var triplet = (--baseValue & 255 ^ resultBytes[pos++]) << 16 |
|
||||||
|
(--baseValue & 255 ^ resultBytes[pos++]) << 8 |
|
||||||
|
--baseValue & 255 ^ resultBytes[pos++];
|
||||||
|
|
||||||
|
resultChars.push(String.fromCharCode(mapChar(triplet >> 18 & 63)));
|
||||||
|
resultChars.push(String.fromCharCode(mapChar(triplet >> 12 & 63)));
|
||||||
|
resultChars.push(String.fromCharCode(mapChar(triplet >> 6 & 63)));
|
||||||
|
resultChars.push(String.fromCharCode(mapChar(triplet & 63)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理剩余字节
|
||||||
|
if (resultBytes.length % 3) {
|
||||||
|
resultChars.length -= 3 - (resultBytes.length % 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultChars.join("");
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// 创建一个工具函数来生成JSPL
|
||||||
|
function createJSPLGenerator(dateTimeStamp) {
|
||||||
|
return {
|
||||||
|
generate: function (sessionData, fingerprintData) {
|
||||||
|
// let dateTimeStamp = Math.floor(Date.now() / 1000)
|
||||||
|
// console.log("dateTimeStamp : " + dateTimeStamp)
|
||||||
|
// 使用会话数据作为输入
|
||||||
|
var functions = zn(sessionData, dateTimeStamp);
|
||||||
|
var collect = functions[1]; // 收集函数
|
||||||
|
var generate = functions[2]; //加密函数
|
||||||
|
|
||||||
|
// 收集指纹数据
|
||||||
|
for (var key in fingerprintData) {
|
||||||
|
if (fingerprintData.hasOwnProperty(key)) {
|
||||||
|
collect(key, fingerprintData[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成并返回JSPL
|
||||||
|
return generate("jspl");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// print process.argv
|
||||||
|
// process.argv.forEach(function (val, index, array) {
|
||||||
|
// console.log(index + ': ' + val);
|
||||||
|
// });
|
||||||
|
var fingerprint = undefined
|
||||||
|
var dateTimeStamp = undefined
|
||||||
|
if (process.argv[2] != undefined) {
|
||||||
|
fingerprint = JSON.parse(process.argv[2])
|
||||||
|
}
|
||||||
|
dateTimeStamp = JSON.parse(process.argv[3])
|
||||||
|
|
||||||
|
// main
|
||||||
|
// if (dateTimeStamp == undefined) {
|
||||||
|
// dateTimeStamp = Math.floor(Date.now() / 1000)
|
||||||
|
// }
|
||||||
|
// let dateTimeStamp = Math.floor(Date.now() / 1000)
|
||||||
|
// let dateTimeStamp = 1754908260
|
||||||
|
|
||||||
|
// console.log(dateTimeStamp)
|
||||||
|
// 使用示例
|
||||||
|
let jsplGenerator = createJSPLGenerator(dateTimeStamp);
|
||||||
|
|
||||||
|
// fingerprint = {
|
||||||
|
// "nddc": 1,
|
||||||
|
// "r3n": 33,
|
||||||
|
// "exp8": 0,
|
||||||
|
// "uid": null,
|
||||||
|
// "bci": true,
|
||||||
|
// "bcl": 0.8,
|
||||||
|
// "bct": "Infinity",
|
||||||
|
// "bdt": "Infinity",
|
||||||
|
// "dp0": false,
|
||||||
|
// "ucdv": false,
|
||||||
|
// "wdifrm": false,
|
||||||
|
// "iwgl": "undefined",
|
||||||
|
// "npmtm": false,
|
||||||
|
// "wdif": false,
|
||||||
|
// "wdifpnh": 2800984568,
|
||||||
|
// "lg": "fr-FR",
|
||||||
|
// "isb": false,
|
||||||
|
// "idp": true,
|
||||||
|
// "crt": 0,
|
||||||
|
// "vnd": "Google Inc.",
|
||||||
|
// "bid": "NA",
|
||||||
|
// "med": "defined",
|
||||||
|
// "pltod": false,
|
||||||
|
// "csssp": "",
|
||||||
|
// "awe": false,
|
||||||
|
// "phe": false,
|
||||||
|
// "dat": false,
|
||||||
|
// "nm": false,
|
||||||
|
// "geb": false,
|
||||||
|
// "sqt": false,
|
||||||
|
// "pf": "Linux armv81",
|
||||||
|
// "hc": 8,
|
||||||
|
// "br_oh": 745,
|
||||||
|
// "br_ow": 393,
|
||||||
|
// "ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36",
|
||||||
|
// "wbd": false,
|
||||||
|
// "ts_mtp": 5,
|
||||||
|
// "mob": true,
|
||||||
|
// "lgs": ["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"],
|
||||||
|
// "dvm": 4,
|
||||||
|
// "hcovdr": false,
|
||||||
|
// "plovdr": false,
|
||||||
|
// "ftsovdr": false,
|
||||||
|
// "orf": "debug",
|
||||||
|
// "ttst": 0.8517814137469564,
|
||||||
|
// "br_w": 393,
|
||||||
|
// "br_h": 745,
|
||||||
|
// "br_iw": 513,
|
||||||
|
// "br_ih": 847,
|
||||||
|
// "ars_w": 393,
|
||||||
|
// "ars_h": 876,
|
||||||
|
// "rs_w": 393,
|
||||||
|
// "rs_h": 876,
|
||||||
|
// "rs_cd": 24,
|
||||||
|
// "pr": 2.75,
|
||||||
|
// "so": "portrait-primary",
|
||||||
|
// "vco": "",
|
||||||
|
// "vcots": false,
|
||||||
|
// "vch": "probably",
|
||||||
|
// "vchts": true,
|
||||||
|
// "vcw": "probably",
|
||||||
|
// "vcwts": true,
|
||||||
|
// "vc3": "maybe",
|
||||||
|
// "vc3ts": false,
|
||||||
|
// "vcmp": "",
|
||||||
|
// "vcmpts": false,
|
||||||
|
// "vcq": "",
|
||||||
|
// "vcqts": false,
|
||||||
|
// "vc1": "probably",
|
||||||
|
// "vc1ts": true,
|
||||||
|
// "cssS": "3.93,0.39,12.24,9.75,5.64,10.98,13.46,2.19,6.51",
|
||||||
|
// "css0": "7,75,0",
|
||||||
|
// "css1": "9.74354,0.354646,-0.00922698,0.000685511,0.203723,-5.61673,-0.755238,0.0561098,-0.0279023,0.481607,-10.9534,0.813777,-0.375565,6.48243,-147.433,11.9534",
|
||||||
|
// "cssH": "15px",
|
||||||
|
// "plu": "",
|
||||||
|
// "plgod": false,
|
||||||
|
// "plg": 0,
|
||||||
|
// "plgne": "NA",
|
||||||
|
// "plgre": "NA",
|
||||||
|
// "plgof": "NA",
|
||||||
|
// "plggt": "NA",
|
||||||
|
// "mmt": "empty",
|
||||||
|
// "bchk": "3223aeb6721e0d0917e792818d193ac88dcd62fad5cad7bf7a2b2b473ecf58ee60f018dbdb1a5832e8dc6528387b0745971dbcd82387261e9a4e3f",
|
||||||
|
// "nt_tcp": 0,
|
||||||
|
// "nt_dns": 0,
|
||||||
|
// "nt_rd": 0,
|
||||||
|
// "nt_irt": -29.600000008940697,
|
||||||
|
// "nt_rt": 1129,
|
||||||
|
// "nt_tls": 6.700000002980232,
|
||||||
|
// "nt_ttf": 1166.7000000029802,
|
||||||
|
// "nt_swt": 22.900000005960464,
|
||||||
|
// "nt_csd": 411060,
|
||||||
|
// "nt_nhp": "h2",
|
||||||
|
// "nt_rdc": 0,
|
||||||
|
// "nt_it": "navigation",
|
||||||
|
// "nt_prs": 6.700000002980232,
|
||||||
|
// "nt_esc": 0,
|
||||||
|
// "nt_ttrd": null,
|
||||||
|
// "nt_le": 3.0999999940395355,
|
||||||
|
// "nt_dcle": 141.79999999701977,
|
||||||
|
// "nt_di": 1415.2000000029802,
|
||||||
|
// "nt_dc": 2862.6000000089407,
|
||||||
|
// "ccsT": "Error\nat S (https://d.digital.hermes/tags.js:173:22)\nat Un.C (https://d.digital.hermes/tags.js:1252:41\nat nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%20pour%20Femme%20_%20Herme%CC%80s%20France.html:7:13468)",
|
||||||
|
// "ccsB": "tags.js:1252:41 at nrWrapper (sac-p-tit-arcon-H085871CKAO.html:7:13468)",
|
||||||
|
// "ccsH": "1050544242",
|
||||||
|
// "ccsV": ",993b46baf0942a343b7e6b02fa3f8eef64727f077d3b0055af56e6994dcaf046",
|
||||||
|
// "muev": false,
|
||||||
|
// "pro_t": true,
|
||||||
|
// "wglo": true,
|
||||||
|
// "prso": true,
|
||||||
|
// "wbst": true,
|
||||||
|
// "psn": true,
|
||||||
|
// "edp": true,
|
||||||
|
// "addt": true,
|
||||||
|
// "wsdc": true,
|
||||||
|
// "ccsr": true,
|
||||||
|
// "nuad": true,
|
||||||
|
// "bcda": true,
|
||||||
|
// "idn": true,
|
||||||
|
// "capi": true,
|
||||||
|
// "svde": true,
|
||||||
|
// "vpbq": true,
|
||||||
|
// "mq": "aptr:coarse,ahvr:none",
|
||||||
|
// "aco": "probably",
|
||||||
|
// "acots": false,
|
||||||
|
// "acmp": "probably",
|
||||||
|
// "acmpts": true,
|
||||||
|
// "acw": "probably",
|
||||||
|
// "acwts": false,
|
||||||
|
// "acma": "maybe",
|
||||||
|
// "acmats": false,
|
||||||
|
// "acaa": "probably",
|
||||||
|
// "acaats": true,
|
||||||
|
// "ac3": "",
|
||||||
|
// "ac3ts": false,
|
||||||
|
// "acf": "probably",
|
||||||
|
// "acfts": false,
|
||||||
|
// "acmp4": "maybe",
|
||||||
|
// "acmp4ts": false,
|
||||||
|
// "acmp3": "probably",
|
||||||
|
// "acmp3ts": false,
|
||||||
|
// "acwm": "maybe",
|
||||||
|
// "acwmts": false,
|
||||||
|
// "ocpt": false,
|
||||||
|
// "ckwa": false,
|
||||||
|
// "spwn": false,
|
||||||
|
// "emt": false,
|
||||||
|
// "bfr": false,
|
||||||
|
// "tz": -120,
|
||||||
|
// "hdn": false,
|
||||||
|
// "xt1": false,
|
||||||
|
// "cdhf": false,
|
||||||
|
// "eva": 33,
|
||||||
|
// "cokys": ",loadTimes,csi,app",
|
||||||
|
// "ecpc": false,
|
||||||
|
// "nhi": ",64,true,Nexus 5,Android,6.0,138.0.7204.184,false",
|
||||||
|
// "k_lyts": 48,
|
||||||
|
// "k_lytk": "kg20va`l\u00a7'w8mh.71pdfoqcn[zy365x/\\,-4bt9siu=j;r]e",
|
||||||
|
// "emd": "k:ai,vi,ao",
|
||||||
|
// "wwl": false,
|
||||||
|
// "glvd": "Google Inc. (ARM)",
|
||||||
|
// "glrd": "ANGLE (ARM,Mali-G57 MC2,OpenGL ES 3.2)",
|
||||||
|
// "tzp": "Europe/Paris",
|
||||||
|
// "isf": true,
|
||||||
|
// "isf2": false,
|
||||||
|
// "dt": false,
|
||||||
|
// "fph": 416468867,
|
||||||
|
// "jset": 1754750959
|
||||||
|
// }
|
||||||
|
|
||||||
|
// console.log("received fringerprint is :"+fingerprint)
|
||||||
|
// console.log(fingerprint)
|
||||||
|
let jspl = jsplGenerator.generate("user_session_12345", fingerprint);
|
||||||
|
console.log(jspl);
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def encrpte_to_jspl(fingerprint_json):
|
||||||
|
dir = os.path.dirname(__file__)
|
||||||
|
# print(fingerprint_json)
|
||||||
|
_timestamp = int(time.time())
|
||||||
|
p = subprocess.Popen(['node', dir + '/jspl_encoder.js', fingerprint_json, str(_timestamp)], stdout=subprocess.PIPE)
|
||||||
|
encrypted_fingerprint = p.stdout.read()
|
||||||
|
_result = encrypted_fingerprint.decode('utf-8')
|
||||||
|
return _result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fingerprint = {
|
||||||
|
"nddc": 1,
|
||||||
|
"r3n": 33,
|
||||||
|
"exp8": 0,
|
||||||
|
"uid": None,
|
||||||
|
"bci": True,
|
||||||
|
"bcl": 0.8,
|
||||||
|
"bct": "Infinity",
|
||||||
|
"bdt": "Infinity",
|
||||||
|
"dp0": False,
|
||||||
|
"ucdv": False,
|
||||||
|
"wdifrm": False,
|
||||||
|
"iwgl": "undefined",
|
||||||
|
"npmtm": False,
|
||||||
|
"wdif": False,
|
||||||
|
"wdifpnh": 2800984568,
|
||||||
|
"lg": "fr-FR",
|
||||||
|
"isb": False,
|
||||||
|
"idp": True,
|
||||||
|
"crt": 0,
|
||||||
|
"vnd": "Google Inc.",
|
||||||
|
"bid": "NA",
|
||||||
|
"med": "defined",
|
||||||
|
"pltod": False,
|
||||||
|
"csssp": "",
|
||||||
|
"awe": False,
|
||||||
|
"phe": False,
|
||||||
|
"dat": False,
|
||||||
|
"nm": False,
|
||||||
|
"geb": False,
|
||||||
|
"sqt": False,
|
||||||
|
"pf": "Linux armv81",
|
||||||
|
"hc": 8,
|
||||||
|
"br_oh": 745,
|
||||||
|
"br_ow": 393,
|
||||||
|
"ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36",
|
||||||
|
"wbd": False,
|
||||||
|
"ts_mtp": 5,
|
||||||
|
"mob": True,
|
||||||
|
"lgs": ["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"],
|
||||||
|
"dvm": 4,
|
||||||
|
"hcovdr": False,
|
||||||
|
"plovdr": False,
|
||||||
|
"ftsovdr": False,
|
||||||
|
"orf": "debug",
|
||||||
|
"ttst": 0.8517814137469564,
|
||||||
|
"br_w": 393,
|
||||||
|
"br_h": 745,
|
||||||
|
"br_iw": 513,
|
||||||
|
"br_ih": 847,
|
||||||
|
"ars_w": 393,
|
||||||
|
"ars_h": 876,
|
||||||
|
"rs_w": 393,
|
||||||
|
"rs_h": 876,
|
||||||
|
"rs_cd": 24,
|
||||||
|
"pr": 2.75,
|
||||||
|
"so": "portrait-primary",
|
||||||
|
"vco": "",
|
||||||
|
"vcots": False,
|
||||||
|
"vch": "probably",
|
||||||
|
"vchts": True,
|
||||||
|
"vcw": "probably",
|
||||||
|
"vcwts": True,
|
||||||
|
"vc3": "maybe",
|
||||||
|
"vc3ts": False,
|
||||||
|
"vcmp": "",
|
||||||
|
"vcmpts": False,
|
||||||
|
"vcq": "",
|
||||||
|
"vcqts": False,
|
||||||
|
"vc1": "probably",
|
||||||
|
"vc1ts": True,
|
||||||
|
"cssS": "3.93,0.39,12.24,9.75,5.64,10.98,13.46,2.19,6.51",
|
||||||
|
"css0": "7,75,0",
|
||||||
|
"css1": "9.74354,0.354646,-0.00922698,0.000685511,0.203723,-5.61673,-0.755238,0.0561098,-0.0279023,0.481607,-10.9534,0.813777,-0.375565,6.48243,-147.433,11.9534",
|
||||||
|
"cssH": "15px",
|
||||||
|
"plu": "",
|
||||||
|
"plgod": False,
|
||||||
|
"plg": 0,
|
||||||
|
"plgne": "NA",
|
||||||
|
"plgre": "NA",
|
||||||
|
"plgof": "NA",
|
||||||
|
"plggt": "NA",
|
||||||
|
"mmt": "empty",
|
||||||
|
"bchk": "3223aeb6721e0d0917e792818d193ac88dcd62fad5cad7bf7a2b2b473ecf58ee60f018dbdb1a5832e8dc6528387b0745971dbcd82387261e9a4e3f",
|
||||||
|
"nt_tcp": 0,
|
||||||
|
"nt_dns": 0,
|
||||||
|
"nt_rd": 0,
|
||||||
|
"nt_irt": -29.600000008940697,
|
||||||
|
"nt_rt": 1129,
|
||||||
|
"nt_tls": 6.700000002980232,
|
||||||
|
"nt_ttf": 1166.7000000029802,
|
||||||
|
"nt_swt": 22.900000005960464,
|
||||||
|
"nt_csd": 411060,
|
||||||
|
"nt_nhp": "h2",
|
||||||
|
"nt_rdc": 0,
|
||||||
|
"nt_it": "navigation",
|
||||||
|
"nt_prs": 6.700000002980232,
|
||||||
|
"nt_esc": 0,
|
||||||
|
"nt_ttrd": None,
|
||||||
|
"nt_le": 3.0999999940395355,
|
||||||
|
"nt_dcle": 141.79999999701977,
|
||||||
|
"nt_di": 1415.2000000029802,
|
||||||
|
"nt_dc": 2862.6000000089407,
|
||||||
|
"ccsT": "Error\nat S (https://d.digital.hermes/tags.js:173:22)\nat Un.C (https://d.digital.hermes/tags.js:1252:41\nat nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%20pour%20Femme%20_%20Herme%CC%80s%20France.html:7:13468)",
|
||||||
|
"ccsB": "tags.js:1252:41 at nrWrapper (sac-p-tit-arcon-H085871CKAO.html:7:13468)",
|
||||||
|
"ccsH": "1050544242",
|
||||||
|
"ccsV": ",993b46baf0942a343b7e6b02fa3f8eef64727f077d3b0055af56e6994dcaf046",
|
||||||
|
"muev": False,
|
||||||
|
"pro_t": True,
|
||||||
|
"wglo": True,
|
||||||
|
"prso": True,
|
||||||
|
"wbst": True,
|
||||||
|
"psn": True,
|
||||||
|
"edp": True,
|
||||||
|
"addt": True,
|
||||||
|
"wsdc": True,
|
||||||
|
"ccsr": True,
|
||||||
|
"nuad": True,
|
||||||
|
"bcda": True,
|
||||||
|
"idn": True,
|
||||||
|
"capi": True,
|
||||||
|
"svde": True,
|
||||||
|
"vpbq": True,
|
||||||
|
"mq": "aptr:coarse,ahvr:none",
|
||||||
|
"aco": "probably",
|
||||||
|
"acots": False,
|
||||||
|
"acmp": "probably",
|
||||||
|
"acmpts": True,
|
||||||
|
"acw": "probably",
|
||||||
|
"acwts": False,
|
||||||
|
"acma": "maybe",
|
||||||
|
"acmats": False,
|
||||||
|
"acaa": "probably",
|
||||||
|
"acaats": True,
|
||||||
|
"ac3": "",
|
||||||
|
"ac3ts": False,
|
||||||
|
"acf": "probably",
|
||||||
|
"acfts": False,
|
||||||
|
"acmp4": "maybe",
|
||||||
|
"acmp4ts": False,
|
||||||
|
"acmp3": "probably",
|
||||||
|
"acmp3ts": False,
|
||||||
|
"acwm": "maybe",
|
||||||
|
"acwmts": False,
|
||||||
|
"ocpt": False,
|
||||||
|
"ckwa": False,
|
||||||
|
"spwn": False,
|
||||||
|
"emt": False,
|
||||||
|
"bfr": False,
|
||||||
|
"tz": -120,
|
||||||
|
"hdn": False,
|
||||||
|
"xt1": False,
|
||||||
|
"cdhf": False,
|
||||||
|
"eva": 33,
|
||||||
|
"cokys": ",loadTimes,csi,app",
|
||||||
|
"ecpc": False,
|
||||||
|
"nhi": ",64,true,Nexus 5,Android,6.0,138.0.7204.184,false",
|
||||||
|
"k_lyts": 48,
|
||||||
|
"k_lytk": "kg20va`l\u00a7'w8mh.71pdfoqcn[zy365x/\\,-4bt9siu=j;r]e",
|
||||||
|
"emd": "k:ai,vi,ao",
|
||||||
|
"wwl": False,
|
||||||
|
"glvd": "Google Inc. (ARM)",
|
||||||
|
"glrd": "ANGLE (ARM,Mali-G57 MC2,OpenGL ES 3.2)",
|
||||||
|
"tzp": "Europe/Paris",
|
||||||
|
"isf": True,
|
||||||
|
"isf2": False,
|
||||||
|
"dt": False,
|
||||||
|
"fph": 416468867,
|
||||||
|
"jset": 1754750959
|
||||||
|
}
|
||||||
|
fingerprint_json = json.dumps(fingerprint)
|
||||||
|
print(encrpte_to_jspl(fingerprint_json))
|
||||||
+103
-36
@@ -1,6 +1,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
|
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ from models.contact_pojo import ContactPojo
|
|||||||
from models.mail_pojo import MailAddress
|
from models.mail_pojo import MailAddress
|
||||||
from models.regisered_user_pojo import RegisteredUserPojo
|
from models.regisered_user_pojo import RegisteredUserPojo
|
||||||
|
|
||||||
MONGO_DB_URL = "mongodb://mongo.lpaconsulting.fr/?timeoutMS=100000"
|
MONGO_DB_URL = "mongodb://mongo2.lpaconsulting.fr/?timeoutMS=100000"
|
||||||
CAPTCHA_ERROR_COLLECTION_PREFIX = "CAPTCHA_ERROR_"
|
CAPTCHA_ERROR_COLLECTION_PREFIX = "CAPTCHA_ERROR_"
|
||||||
BLACK_LIST = "BLACK_LIST"
|
BLACK_LIST = "BLACK_LIST"
|
||||||
ACCEPTED_APPOINTMENT_LIST = "ACCEPTED_APPOINTMENT_LIST"
|
ACCEPTED_APPOINTMENT_LIST = "ACCEPTED_APPOINTMENT_LIST"
|
||||||
@@ -25,7 +26,22 @@ CONTACT_LIST_SERIAL_MAP = "CONTACT_LIST_SERIAL_MAP"
|
|||||||
|
|
||||||
class MongoDbManager:
|
class MongoDbManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
client = MongoClient(MONGO_DB_URL, username='appointment', password='Rdv@2022', authSource='appointment')
|
# Get username and password from environment variables
|
||||||
|
mongo_username = os.getenv("MONGO_USERNAME")
|
||||||
|
mongo_password = os.getenv("MONGO_PASSWORD")
|
||||||
|
|
||||||
|
# Validate that environment variables exist
|
||||||
|
if not mongo_username or not mongo_password:
|
||||||
|
raise ValueError(
|
||||||
|
"MONGO_USERNAME and MONGO_PASSWORD environment variables must be set"
|
||||||
|
)
|
||||||
|
|
||||||
|
client = MongoClient(
|
||||||
|
MONGO_DB_URL,
|
||||||
|
username=mongo_username,
|
||||||
|
password=mongo_password,
|
||||||
|
authSource="appointment",
|
||||||
|
)
|
||||||
self.db = client.appointment
|
self.db = client.appointment
|
||||||
self.logger = logging.getLogger("mongoDb")
|
self.logger = logging.getLogger("mongoDb")
|
||||||
|
|
||||||
@@ -36,8 +52,13 @@ class MongoDbManager:
|
|||||||
def insert_reserve_result(self, collection_name, reserve: ReserveResultPojo):
|
def insert_reserve_result(self, collection_name, reserve: ReserveResultPojo):
|
||||||
try:
|
try:
|
||||||
collection_to_use = self.db[collection_name]
|
collection_to_use = self.db[collection_name]
|
||||||
collection_to_use.replace_one(filter={'_id': reserve.id, }, replacement=reserve.to_firestore_dict(),
|
collection_to_use.replace_one(
|
||||||
upsert=True)
|
filter={
|
||||||
|
"_id": reserve.id,
|
||||||
|
},
|
||||||
|
replacement=reserve.to_firestore_dict(),
|
||||||
|
upsert=True,
|
||||||
|
)
|
||||||
except Exception as Error:
|
except Exception as Error:
|
||||||
self.logger.info(Error)
|
self.logger.info(Error)
|
||||||
|
|
||||||
@@ -83,7 +104,14 @@ class MongoDbManager:
|
|||||||
result_list.append(ContactPojo.from_firestore_dict(document))
|
result_list.append(ContactPojo.from_firestore_dict(document))
|
||||||
return result_list
|
return result_list
|
||||||
|
|
||||||
def save_links_to_validate(self, link: str, mail_address: str, model: str, _all_contact_list: list):
|
def save_links_to_validate(
|
||||||
|
self,
|
||||||
|
link: str,
|
||||||
|
mail_address: str,
|
||||||
|
model: str,
|
||||||
|
_all_contact_list: list,
|
||||||
|
_used_ip: str = "",
|
||||||
|
):
|
||||||
collection_to_use = self.db[LINKS_TO_VALIDATE]
|
collection_to_use = self.db[LINKS_TO_VALIDATE]
|
||||||
updated_at = time.strftime("%H:%M:%S", time.localtime())
|
updated_at = time.strftime("%H:%M:%S", time.localtime())
|
||||||
_ip_country = "FR"
|
_ip_country = "FR"
|
||||||
@@ -94,30 +122,42 @@ class MongoDbManager:
|
|||||||
_ip_country = _contact.ip_country
|
_ip_country = _contact.ip_country
|
||||||
|
|
||||||
if len(mail_address) > 0:
|
if len(mail_address) > 0:
|
||||||
collection_to_use.replace_one(filter={'_id': mail_address, }, replacement={
|
collection_to_use.replace_one(
|
||||||
u'url': link,
|
filter={
|
||||||
u'email': mail_address,
|
"_id": mail_address,
|
||||||
u'serial': serial,
|
},
|
||||||
u'model': model,
|
replacement={
|
||||||
u'ip_country': _ip_country,
|
"url": link,
|
||||||
"updated_at": updated_at
|
"email": mail_address,
|
||||||
},
|
"serial": serial,
|
||||||
upsert=True)
|
"model": model,
|
||||||
|
"ip_country": _ip_country,
|
||||||
|
"_used_ip": _used_ip,
|
||||||
|
"updated_at": updated_at,
|
||||||
|
},
|
||||||
|
upsert=True,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
collection_to_use.replace_one(filter={'_id': link, }, replacement={
|
collection_to_use.replace_one(
|
||||||
u'url': link,
|
filter={
|
||||||
u'serial': serial,
|
"_id": link,
|
||||||
u'model': model,
|
},
|
||||||
u'ip_country': _ip_country,
|
replacement={
|
||||||
"updated_at": updated_at
|
"url": link,
|
||||||
},
|
"serial": serial,
|
||||||
upsert=True)
|
"model": model,
|
||||||
|
"ip_country": _ip_country,
|
||||||
|
"_used_ip": _used_ip,
|
||||||
|
"updated_at": updated_at,
|
||||||
|
},
|
||||||
|
upsert=True,
|
||||||
|
)
|
||||||
|
|
||||||
def get_code_for_email(self, email: str):
|
def get_code_for_email(self, email: str):
|
||||||
collection_name = DESTINATION_EMAIL_LIST
|
collection_name = DESTINATION_EMAIL_LIST
|
||||||
try:
|
try:
|
||||||
collection_to_use = self.db[collection_name]
|
collection_to_use = self.db[collection_name]
|
||||||
mailDocument = collection_to_use.find_one(filter={'_id': email})
|
mailDocument = collection_to_use.find_one(filter={"_id": email})
|
||||||
if mailDocument is not None:
|
if mailDocument is not None:
|
||||||
return MailAddress.from_firestore_dict(mailDocument).password
|
return MailAddress.from_firestore_dict(mailDocument).password
|
||||||
else:
|
else:
|
||||||
@@ -131,7 +171,9 @@ class MongoDbManager:
|
|||||||
_cursor = self.db[_collection_name]
|
_cursor = self.db[_collection_name]
|
||||||
registered_user_list = []
|
registered_user_list = []
|
||||||
for document in _cursor.find():
|
for document in _cursor.find():
|
||||||
registered_user_list.append(RegisteredUserPojo.from_firestore_dict(document))
|
registered_user_list.append(
|
||||||
|
RegisteredUserPojo.from_firestore_dict(document)
|
||||||
|
)
|
||||||
return registered_user_list
|
return registered_user_list
|
||||||
|
|
||||||
def get_destination_emails(self) -> list:
|
def get_destination_emails(self) -> list:
|
||||||
@@ -164,8 +206,20 @@ class MongoDbManager:
|
|||||||
self.logger.info(error)
|
self.logger.info(error)
|
||||||
return link_list
|
return link_list
|
||||||
|
|
||||||
def link_validated_for_result(self, link: str, linkPojo: LinkPojo, state=True, is_duplicated=False,
|
def link_validated_for_result(
|
||||||
is_invalid=False, segement_position=1, ua=""):
|
self,
|
||||||
|
link: str,
|
||||||
|
linkPojo: LinkPojo,
|
||||||
|
state=True,
|
||||||
|
is_duplicated=False,
|
||||||
|
is_invalid=False,
|
||||||
|
segement_position=1,
|
||||||
|
ua="",
|
||||||
|
model="",
|
||||||
|
timestamp_in_s: list = None,
|
||||||
|
):
|
||||||
|
if timestamp_in_s is None:
|
||||||
|
timestamp_in_s = []
|
||||||
print("link_validated_for_result() called with url = " + link)
|
print("link_validated_for_result() called with url = " + link)
|
||||||
if is_duplicated:
|
if is_duplicated:
|
||||||
_id = link.split("/")[-2]
|
_id = link.split("/")[-2]
|
||||||
@@ -176,7 +230,10 @@ class MongoDbManager:
|
|||||||
print("link_validated_for_result() called with id = " + _id)
|
print("link_validated_for_result() called with id = " + _id)
|
||||||
|
|
||||||
collection_name = str(datetime.date.today())
|
collection_name = str(datetime.date.today())
|
||||||
print("link_validated_for_result() called with collection_name = " + collection_name)
|
print(
|
||||||
|
"link_validated_for_result() called with collection_name = "
|
||||||
|
+ collection_name
|
||||||
|
)
|
||||||
|
|
||||||
collection = self.db[collection_name]
|
collection = self.db[collection_name]
|
||||||
validated_at = time.strftime("%H:%M:%S", time.localtime())
|
validated_at = time.strftime("%H:%M:%S", time.localtime())
|
||||||
@@ -185,17 +242,27 @@ class MongoDbManager:
|
|||||||
validated_by = "Invalid"
|
validated_by = "Invalid"
|
||||||
if is_duplicated:
|
if is_duplicated:
|
||||||
validated_by = "Double"
|
validated_by = "Double"
|
||||||
collection.find_one_and_update({'_id': _id}, {
|
collection.find_one_and_update(
|
||||||
"$set": {"url_validated": state, "validated_at": validated_at, "id": _id, "email": linkPojo.email,
|
{"_id": _id},
|
||||||
"url": link,
|
{
|
||||||
"source_from": linkPojo.model,
|
"$set": {
|
||||||
"serial": linkPojo.serial,
|
"url_validated": state,
|
||||||
"validated_by_ua": ua,
|
"validated_at": validated_at,
|
||||||
"validated_by": validated_by}},
|
"id": _id,
|
||||||
upsert=True)
|
"email": linkPojo.email,
|
||||||
|
"url": link,
|
||||||
|
"validated_by_model": model,
|
||||||
|
"serial": linkPojo.serial,
|
||||||
|
"validated_by_ua": ua,
|
||||||
|
"timestamp_in_s": "-".join(str(x) for x in timestamp_in_s),
|
||||||
|
"validated_by": validated_by,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upsert=True,
|
||||||
|
)
|
||||||
# remove the link from db
|
# remove the link from db
|
||||||
collection_to_use = self.db[LINKS_TO_VALIDATE]
|
collection_to_use = self.db[LINKS_TO_VALIDATE]
|
||||||
collection_to_use.delete_one({'_id': linkPojo.email})
|
collection_to_use.delete_one({"_id": linkPojo.email})
|
||||||
|
|
||||||
|
|
||||||
MONGO_STORE_MANAGER = MongoDbManager()
|
MONGO_STORE_MANAGER = MongoDbManager()
|
||||||
|
|||||||
@@ -0,0 +1,423 @@
|
|||||||
|
nddc:1 --> OK, 1, 需要从网页中获得
|
||||||
|
数值应该就是1
|
||||||
|
var nddc;
|
||||||
|
try {
|
||||||
|
if ((nddc = (document.cookie.match(/datadome=/g) || []).length) > 1) {
|
||||||
|
t.deleteAllDDCookies();
|
||||||
|
}
|
||||||
|
} catch (n) {
|
||||||
|
nddc = "err";
|
||||||
|
}
|
||||||
|
|
||||||
|
r3n:33
|
||||||
|
r3n 数值是window._hsv 的值,如果没有window._hsv的值,那么返回33
|
||||||
|
// var hsv = typeof window._hsv == "string" && window._hsv.length > 0 ||
|
||||||
|
// typeof window._hsv == "number" && !isNaN(window._hsv) ? window._hsv : 33;
|
||||||
|
exp8:0
|
||||||
|
固定是0
|
||||||
|
uid:null
|
||||||
|
默认为null
|
||||||
|
n.i("uid", t.getCookie("correlation_id"));
|
||||||
|
bci:true
|
||||||
|
bcl:0.8
|
||||||
|
bct:Infinity
|
||||||
|
bdt:Infinity
|
||||||
|
window.navigator.getBattery().then(function (batteryManager) {
|
||||||
|
n("bci", batteryManager.charging);
|
||||||
|
n("bcl", batteryManager.level);
|
||||||
|
n("bct", batteryManager.chargingTime);
|
||||||
|
n("bdt", batteryManager.dischargingTime);
|
||||||
|
});
|
||||||
|
|
||||||
|
dp0:false
|
||||||
|
默认为false ?
|
||||||
|
ucdv:false
|
||||||
|
默认为false
|
||||||
|
ucdv = typeof objectToInspect != "undefined" && objectToInspect === "null" && typeof result != "undefined" && !!result)
|
||||||
|
wdifrm:false
|
||||||
|
默认为false
|
||||||
|
iwgl:undefined ??
|
||||||
|
|
||||||
|
|
||||||
|
npmtm:false
|
||||||
|
默认为false
|
||||||
|
wdif:false
|
||||||
|
|
||||||
|
wdifpnh:2800984568
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lg:fr-FR
|
||||||
|
n("lg", window.navigator.language || window.navigator.userLanguage || window.navigator.browserLanguage || window.navigator.systemLanguage || "");
|
||||||
|
isb:false
|
||||||
|
n("isb", !!window.navigator.brave);
|
||||||
|
idp:true
|
||||||
|
crt:0
|
||||||
|
crt = window.navigator.connection && window.navigator.connection['rtt']
|
||||||
|
vnd:Google Inc.
|
||||||
|
OK
|
||||||
|
|
||||||
|
bid:NA
|
||||||
|
OK
|
||||||
|
med:defined
|
||||||
|
OK
|
||||||
|
pltod:false
|
||||||
|
默认为false
|
||||||
|
csssp:
|
||||||
|
为空
|
||||||
|
awe:false
|
||||||
|
默认为false
|
||||||
|
phe:false
|
||||||
|
默认为false
|
||||||
|
dat:false
|
||||||
|
默认为false
|
||||||
|
nm:false
|
||||||
|
默认为false
|
||||||
|
geb:false
|
||||||
|
默认为false
|
||||||
|
sqt:false
|
||||||
|
默认为false
|
||||||
|
pf:MacIntel
|
||||||
|
pf = window.navigator.platform
|
||||||
|
hc:12
|
||||||
|
ok
|
||||||
|
br_oh:847
|
||||||
|
ok
|
||||||
|
br_ow:513
|
||||||
|
ok
|
||||||
|
ua:Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Mobile Safari/537.36
|
||||||
|
ok
|
||||||
|
wbd:false
|
||||||
|
默认为false
|
||||||
|
ts_mtp:0
|
||||||
|
ok
|
||||||
|
mob:true
|
||||||
|
mob = navigator.userAgentData?navigator.userAgentData.mobile:"NA"
|
||||||
|
lgs:["fr-FR","en-US","zh-CN","zh","fr","en"]
|
||||||
|
lgs=JSON.stringify(navigator.languages)
|
||||||
|
dvm:8
|
||||||
|
ok
|
||||||
|
hcovdr:false
|
||||||
|
默认为false
|
||||||
|
plovdr:false
|
||||||
|
默认为false
|
||||||
|
ftsovdr:false
|
||||||
|
默认为false
|
||||||
|
|
||||||
|
orf:debug
|
||||||
|
|
||||||
|
trrd:0.5678095129748595
|
||||||
|
0到1之间的,小数后面有15位的随机数
|
||||||
|
|
||||||
|
br_w:513
|
||||||
|
ok
|
||||||
|
br_h:847
|
||||||
|
ok
|
||||||
|
br_iw:513
|
||||||
|
window.innerWidth || 0
|
||||||
|
br_ih:847
|
||||||
|
window.innerHeight || 0
|
||||||
|
ars_w:513
|
||||||
|
ok
|
||||||
|
ars_h:847
|
||||||
|
ok
|
||||||
|
rs_w:513
|
||||||
|
ok
|
||||||
|
rs_h:847
|
||||||
|
ok
|
||||||
|
rs_cd:24
|
||||||
|
ok
|
||||||
|
pr:2
|
||||||
|
ok
|
||||||
|
so:portrait-primary
|
||||||
|
ok
|
||||||
|
vco:
|
||||||
|
ok
|
||||||
|
vcots:false
|
||||||
|
ok
|
||||||
|
vch:probably
|
||||||
|
ok
|
||||||
|
vchts:true
|
||||||
|
ok
|
||||||
|
vcw:probably
|
||||||
|
ok
|
||||||
|
vcwts:true
|
||||||
|
ok
|
||||||
|
vc3:maybe
|
||||||
|
ok
|
||||||
|
vc3ts:false
|
||||||
|
ok
|
||||||
|
vcmp:
|
||||||
|
ok
|
||||||
|
vcmpts:false
|
||||||
|
ok
|
||||||
|
vcq:
|
||||||
|
ok
|
||||||
|
vcqts:false
|
||||||
|
ok
|
||||||
|
vc1:probably
|
||||||
|
ok
|
||||||
|
vc1ts:true
|
||||||
|
ok
|
||||||
|
|
||||||
|
cssS:3.93,0.39,12.24,9.75,5.64,10.98,13.46,2.19,6.51
|
||||||
|
|
||||||
|
css0:7, 75, 0
|
||||||
|
|
||||||
|
css1:9.74354, 0.354646, -0.00922698, 0.000685511, 0.203723, -5.61673, -0.755238, 0.0561098, -0.0279023, 0.481607, -10.9534, 0.813777, -0.375565, 6.48243, -147.433, 11.9534
|
||||||
|
|
||||||
|
cssH:15px
|
||||||
|
|
||||||
|
plu:empty
|
||||||
|
plgod:false
|
||||||
|
plg:0
|
||||||
|
plgne:NA
|
||||||
|
plgre:NA
|
||||||
|
plgof:NA
|
||||||
|
plggt:NA
|
||||||
|
|
||||||
|
mmt:empty
|
||||||
|
bchk:3223aeb6721e0d0917e7928181193ac88dcd62fad5cadfbe7a2b2b473ecf58ee70f098dbdb1a1832e8dc6528387b0745971dbcd82384261e9a4e3f
|
||||||
|
for (var n = ["AppBannerPromptResult", "webkitRTCPeerConnection", "webkitAudioContext", "webkitRequestAnimationFrame", "chrome.runtime",
|
||||||
|
"chrome.webstore", "console.context", "InputMethodContext", "SVGAnimationElement", "SVGPathSegList", "PasswordCredential", "ViewTransition",
|
||||||
|
"VisualViewport.prototype.segments", "DeprecationReportBody", "MathMLElement", "opr", "CSS2Properties.prototype.colorScheme", "WebKitCSSMatrix",
|
||||||
|
"SVGTextPositioningElement", "XMLHttpRequestEventTarget", "TextDecoderStream", "onloadend", "WritableStream", "TransformStream", "TextTrackCue",
|
||||||
|
"-283", "VisualViewport", "StyleSheet", "RTCDtlsTransport", "Atomics", "StaticRange", "UIEvent", "VideoStreamTrack", "OfflineResourceList",
|
||||||
|
"SVGGeometryElement", "RTCDataChannel", "VTTRegion", "AbortController", "Controllers", "onanimationcancel",
|
||||||
|
"SVGDocument", "IIRFilterNode", "RTCStatsReport", "MediaStreamTrack", "CSS2Properties.prototype.MozOsxFontSmoothing", "CropTarget", "BatteryManager",
|
||||||
|
"LaunchQueue", "CSSFontPaletteValuesRule", "PushSubscriptionOptions", "DOMSettableTokenList", "RTCTrackEvent",
|
||||||
|
"MozSmsMessage", "ServiceWorkerContainer", "CanvasCaptureMediaStream", "DeviceStorage", "XPathNSResolver", "SmartCardEvent", "WeakSet",
|
||||||
|
"MozMobileMessageManager", "External.prototype.getHostEnvironmentValue", "WindowUtils", "XPathNamespace", "SVGFEDropShadowElement",
|
||||||
|
"SharedWorker", "WorkerMessageEvent", "CSS2Properties.prototype.MozOSXFontSmoothing", "AudioSinkInfo",
|
||||||
|
"Notification.prototype.image", "ContentVisibilityAutoStateChangeEvent", "PerformanceResourceTiming.prototype.renderBlockingStatus", "console.createTask",
|
||||||
|
"PerformanceServerTiming", "CanvasFilter", "structuredClone", "onslotchange", "EyeDropper", "URLPattern", "VideoFrame", "WritableStreamDefaultController", "SharedArrayBuffer",
|
||||||
|
"CSSCounterStyleRule", "CustomStateSet", "ReadableStreamDefaultController", "XMLDocument.prototype.hasStorageAccess",
|
||||||
|
"CryptoKey", "SubmitEvent", "MediaMetadata", "VideoPlaybackQuality", "ReadableStreamDefaultReader", "UserActivation", "FragmentDirective",
|
||||||
|
"WebKitMediaKeyError", "RTCRtpTransceiver.prototype.stop", "Scheduling", "EventCounts", "VideoTrackList", "SourceBuffer", "RTCError", "FontFaceSet", "CSSCharsetRule", "MediaDeviceInfo",
|
||||||
|
"RTCPeerConnectionIceErrorEvent", "RTCSctpTransport", "MediaSessionCoordinator", "XULPopupElement", "MediaSourceHandle",
|
||||||
|
"366", "__REACT_DEVTOOLS_GLOBAL_HOOK__", "ShadowRealm", "HTMLSlotElement", "DetachedViewControlEvent", "GeolocationPosition", "SiteBoundCredential", "MediaSource",
|
||||||
|
"WebTransport", "GPUSupportedLimits", "ToggleEvent"], bchk = "", e = 0; e < n.length; e++) {
|
||||||
|
for (var r = n[e].split("."), i = window, o = true, c = 0; c < r.length; c++) {
|
||||||
|
var s = r[c];
|
||||||
|
if (!(s in i)) {
|
||||||
|
o = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c < r.length - 1) {
|
||||||
|
i = i[s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o) {
|
||||||
|
bchk += "52738db37a1ea50137e79e8181193ac872cd325ba5cacfbe7aab5b36b9c9879e7c0018dbd31a1832a8dc6528387b67451719dcd8b784a518904e3f07c69b9d30"[e];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
bchk += "3829ae9642df0d791e41d2159da28bd18d056afadf1bd70fc9222a473eaf58e860ff950e7bf35b66e4aa90b156c80c96913dbd9c23c7262e4adbc3ddd77ff263"[e];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nt_tcp:0
|
||||||
|
var performanceNavigationTiming = window.performance.getEntriesByType && window.performance.getEntriesByType("navigation")[0];
|
||||||
|
nt_tcp = performanceNavigationTiming.connectEnd - performanceNavigationTiming.connectStart
|
||||||
|
nt_dns:0
|
||||||
|
|
||||||
|
nt_dns =performanceNavigationTiming.domainLookupEnd - performanceNavigationTiming.domainLookupStart
|
||||||
|
nt_rd:0
|
||||||
|
nt_rd = performanceNavigationTiming.redirectEnd - performanceNavigationTiming.redirectStart
|
||||||
|
nt_irt:-3.400000002235174
|
||||||
|
nt_irt = performanceNavigationTiming.firstInterimResponseStart - performanceNavigationTiming.requestStart
|
||||||
|
nt_rt:0
|
||||||
|
nt_rt = performanceNavigationTiming.responseStart - performanceNavigationTiming.requestStart
|
||||||
|
nt_tls:3.400000002235174
|
||||||
|
let nt_tls = performanceNavigationTiming.requestStart - performanceNavigationTiming.secureConnectionStart
|
||||||
|
nt_ttf:3.099999997764826
|
||||||
|
let nt_ttf = performanceNavigationTiming.responseEnd - performanceNavigationTiming.fetchStart
|
||||||
|
nt_swt:3.400000002235174
|
||||||
|
let nt_swt = performanceNavigationTiming.fetchStart - performanceNavigationTiming.workerStart
|
||||||
|
nt_csd:0
|
||||||
|
let nt_csd = performanceNavigationTiming.decodedBodySize - performanceNavigationTiming.encodedBodySize
|
||||||
|
nt_nhp:
|
||||||
|
let nt_nhp = performanceNavigationTiming.nextHopProtocol
|
||||||
|
nt_rdc:0
|
||||||
|
let nt_rdc = performanceNavigationTiming.redirectCount
|
||||||
|
nt_it:navigation
|
||||||
|
let nt_it = performanceNavigationTiming.initiatorType
|
||||||
|
nt_prs:0
|
||||||
|
let nt_prs = performanceNavigationTiming.requestStart - performanceNavigationTiming.connectEnd
|
||||||
|
nt_esc:-3.400000002235174
|
||||||
|
let nt_esc = performanceNavigationTiming.secureConnectionStart - performanceNavigationTiming.connectStart
|
||||||
|
nt_ttrd:-2
|
||||||
|
e = performanceNavigationTiming.secureConnectionStart - performanceNavigationTiming.connectStart
|
||||||
|
nt_ttrd = (e - (e = performanceNavigationTiming.connectEnd - performanceNavigationTiming.connectStart)) / e)
|
||||||
|
nt_le:0
|
||||||
|
nt_le = performanceNavigationTiming.loadEventEnd - performanceNavigationTiming.loadEventStart
|
||||||
|
nt_dcle:0.10000000149011612
|
||||||
|
nt_dcle = performanceNavigationTiming.domContentLoadedEventEnd - performanceNavigationTiming.domContentLoadedEventStart
|
||||||
|
nt_di:74.80000000074506
|
||||||
|
nt_di = performanceNavigationTiming.domInteractive
|
||||||
|
nt_dc:0
|
||||||
|
nt_dc = performanceNavigationTiming.domComplete
|
||||||
|
ccsT:Error
|
||||||
|
at S (https://d.digital.hermes/tags.js:173:22)
|
||||||
|
at Un.C (https://d.digital.hermes/tags.js:1252:41
|
||||||
|
ccsB:/tags.js:1252:41
|
||||||
|
at nrWrapper (file:///Users/lpan/Downloads/Sacs%20et%20pochettes%20pour%20Femme%20_%20Herme%CC%80s%20France.html:7:13468)
|
||||||
|
|
||||||
|
ccsH:1050544242
|
||||||
|
|
||||||
|
ccsV:,993b46baf0942a343b7e6b02fa3f8eef64727f077d3b0055af56e6994dcaf046
|
||||||
|
muev:false
|
||||||
|
let muev = !!window.MutationEvent
|
||||||
|
pro_t:true
|
||||||
|
let pro_t = typeof window.Promise != "undefined" && !!window.Promise.try
|
||||||
|
wglo:true
|
||||||
|
!!window.WebGLObject
|
||||||
|
prso:true
|
||||||
|
!!window.PressureObserver
|
||||||
|
wbst:true
|
||||||
|
!!window.WebSocketStream
|
||||||
|
psn:true
|
||||||
|
!!window.PermissionStatus && window.PermissionStatus.prototype.hasOwnProperty('name')
|
||||||
|
edp:true
|
||||||
|
!!window.EyeDropper
|
||||||
|
addt:true
|
||||||
|
!window.AudioData
|
||||||
|
wsdc:true
|
||||||
|
!!window.WritableStreamDefaultController
|
||||||
|
ccsr:true
|
||||||
|
!!window.CSSCounterStyleRule
|
||||||
|
nuad:true
|
||||||
|
!!window.NavigatorUAData
|
||||||
|
bcda:true
|
||||||
|
!!window.BarcodeDetector
|
||||||
|
idn:true
|
||||||
|
!(!window.Intl || !window.Intl.DisplayNames)
|
||||||
|
capi:false
|
||||||
|
capi = !!(window.navigator && window.navigator.contacts && window.navigator[2])
|
||||||
|
svde:false
|
||||||
|
!!window.SVGDiscardElement
|
||||||
|
vpbq:true
|
||||||
|
!!(window.HTMLVideoElement && window.HTMLVideoElement.prototype && window.HTMLVideoElement.prototype.getVideoPlaybackQuality)
|
||||||
|
mq:aptr:coarse, ahvr:none
|
||||||
|
aco:probably
|
||||||
|
var audioElement = document.createElement("audio");
|
||||||
|
aco = audioElement.canPlayType("audio/ogg; codecs=\"vorbis\"")
|
||||||
|
acots:false
|
||||||
|
window.MediaSource.isTypeSupported("audio/ogg; codecs=\"vorbis\"")
|
||||||
|
acmp:probably
|
||||||
|
ok audioElement.canPlayType("audio/mpeg;")
|
||||||
|
acmpts:true
|
||||||
|
ok, default to true
|
||||||
|
acw:probably
|
||||||
|
ok, default to probably
|
||||||
|
acwts:false
|
||||||
|
ok, default to false
|
||||||
|
acma:maybe
|
||||||
|
ok, default to maybe
|
||||||
|
acmats:false
|
||||||
|
ok, default to false
|
||||||
|
|
||||||
|
acaa:probably
|
||||||
|
ok, default to probably
|
||||||
|
|
||||||
|
acaats:true
|
||||||
|
ok, default to true
|
||||||
|
|
||||||
|
ac3:
|
||||||
|
default to empty: ""
|
||||||
|
ac3ts:false
|
||||||
|
ok, default to false
|
||||||
|
|
||||||
|
acf:probably
|
||||||
|
ok, default to probably
|
||||||
|
|
||||||
|
acfts:false
|
||||||
|
ok, default to false
|
||||||
|
|
||||||
|
acmp4:maybe
|
||||||
|
ok, default to maybe
|
||||||
|
|
||||||
|
acmp4ts:false
|
||||||
|
ok, default to false
|
||||||
|
|
||||||
|
acmp3:probably
|
||||||
|
ok, default to probably
|
||||||
|
|
||||||
|
acmp3ts:false
|
||||||
|
ok, default to false
|
||||||
|
|
||||||
|
acwm:maybe
|
||||||
|
ok, default to maybe
|
||||||
|
|
||||||
|
acwmts:false
|
||||||
|
ok, default to false
|
||||||
|
|
||||||
|
ocpt:false
|
||||||
|
ok ocpt = audioElement.canPlayType.toString().indexOf('canPlayType') === -1
|
||||||
|
ckwa:false
|
||||||
|
ok, default to false
|
||||||
|
spwn:false
|
||||||
|
spwn = !!window.spawn
|
||||||
|
emt:false
|
||||||
|
emt = !!window.emit
|
||||||
|
bfr:false
|
||||||
|
bfr = !!window.Buffer
|
||||||
|
tz:-120
|
||||||
|
ok
|
||||||
|
hdn:false
|
||||||
|
hdn = !!window.hidden
|
||||||
|
ok, default to false
|
||||||
|
xt1:false
|
||||||
|
xt1 = !!window.navigator.pdfViewerEnabled
|
||||||
|
cdhf:false
|
||||||
|
cdhf = window.hasFocus()
|
||||||
|
eva:40
|
||||||
|
eva = window.XMLDocument.toString().length
|
||||||
|
cokys:,loadTimes,csi,app
|
||||||
|
default to ",loadTimes,csi,app"
|
||||||
|
var cokys = ""
|
||||||
|
for (var v in window.chrome) {
|
||||||
|
cokys += "," + v;
|
||||||
|
}
|
||||||
|
ecpc:false
|
||||||
|
default to false
|
||||||
|
ecpc = !!window.process
|
||||||
|
|
||||||
|
nhi:,64,true,Nexus 5,Android,6.0,138.0.7204.184,false
|
||||||
|
let results = await window.navigator.userAgentData.getHighEntropyValues(["architecture", "bitness", "model", "platformVersion", "uaFullVersion", "wow64"])
|
||||||
|
for (var e = ["architecture", "bitness", "mobile", "model", "platform", "platformVersion", "uaFullVersion", "wow64"], r = [], i = 0; i < e.length; i++) {
|
||||||
|
r.push(results[e[i]]);
|
||||||
|
}
|
||||||
|
nhi = r.join(",");
|
||||||
|
k_lyts:48
|
||||||
|
k_lytk:kg20va`l§'w8mh.71pdfoqcn[zy365x/\,-4bt9siu=j;r]e
|
||||||
|
let keyboardLayoutMap = await window.navigator.keyboard.getLayoutMap()
|
||||||
|
let k_lyts = keyboardLayoutMap.size
|
||||||
|
for (var e = "", r = window.Array.from(keyboardLayoutMap.values()), i = 0; i < r.length; i++) {
|
||||||
|
e += r[i];
|
||||||
|
}
|
||||||
|
let k_lytk = e
|
||||||
|
|
||||||
|
//}
|
||||||
|
//).catch(function (t) {
|
||||||
|
// n("k_lyts", "Err: " + Q(t.message));
|
||||||
|
//});
|
||||||
|
|
||||||
|
emd:k:ai,vi,ao
|
||||||
|
ok
|
||||||
|
wwl:false
|
||||||
|
glvd:Google Inc. (Apple)
|
||||||
|
ok
|
||||||
|
glrd:ANGLE (Apple, ANGLE Metal Renderer: Apple M2 Pro, Unspecified Version)
|
||||||
|
ok
|
||||||
|
tzp:Europe/Paris
|
||||||
|
ok: Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
|
isf:true
|
||||||
|
isf = window.outerHeight - window.innerHeight <= 1
|
||||||
|
isf2:false
|
||||||
|
isf2 = window.matchMedia && window.matchMedia("(display-mode: fullscreen)").matches
|
||||||
|
dt:false
|
||||||
|
dt = (window.outerHeight - window.innerHeight > 170)
|
||||||
|
fph:416468867
|
||||||
|
|
||||||
|
jset:1754233764
|
||||||
|
jset = Math.floor(Date.now() / 1000)
|
||||||
@@ -1 +0,0 @@
|
|||||||
jsData={"ttst":26.700000002980232,"ifov":false,"hc":8,"br_oh":803,"br_ow":407,"ua":"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36","wbd":false,"tagpu":8.178524146392085,"wdif":false,"wdifrm":false,"npmtm":false,"br_h":803,"br_w":407,"isf":true,"nddc":1,"rs_h":904,"rs_w":407,"rs_cd":24,"phe":false,"nm":false,"jsf":false,"lg":"en-US","pr":3,"ars_h":904,"ars_w":407,"tz":-120,"str_ss":true,"str_ls":true,"str_idb":true,"str_odb":false,"plgod":false,"plg":0,"plgne":"NA","plgre":"NA","plgof":"NA","plggt":"NA","pltod":false,"hcovdr":false,"hcovdr2":false,"plovdr":false,"plovdr2":false,"ftsovdr":false,"ftsovdr2":false,"lb":false,"eva":33,"lo":false,"ts_mtp":5,"ts_tec":true,"ts_tsa":true,"vnd":"Google Inc.","bid":"NA","mmt":"empty","plu":"empty","hdn":false,"awe":false,"geb":false,"dat":false,"med":"defined","aco":"probably","acots":false,"acmp":"probably","acmpts":true,"acw":"probably","acwts":false,"acma":"maybe","acmats":false,"acaa":"probably","acaats":true,"ac3":"","ac3ts":false,"acf":"probably","acfts":false,"acmp4":"maybe","acmp4ts":false,"acmp3":"probably","acmp3ts":false,"acwm":"maybe","acwmts":false,"ocpt":false,"vco":"","vcots":false,"vch":"probably","vchts":true,"vcw":"probably","vcwts":true,"vc3":"maybe","vc3ts":false,"vcmp":"","vcmpts":false,"vcq":"","vcqts":false,"vc1":"probably","vc1ts":true,"dvm":8,"sqt":false,"so":"portrait-primary","wdw":true,"cokys":"bG9hZFRpbWVzY3NpL=","ecpc":false,"lgs":true,"lgsod":false,"psn":true,"edp":false,"addt":true,"wsdc":true,"ccsr":true,"nuad":true,"bcda":true,"idn":true,"capi":false,"svde":false,"vpbq":true,"ucdv":false,"spwn":false,"emt":false,"bfr":false,"dbov":false,"cfpfe":"ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudFsnXHg3MVx4NzVceDY1XHg3Mlx4NzlceDUzXHg2NVx4NmNceDY1XHg2M1x4NzRceDZmXHg3MiddKCdceDYyXHg3Mlx4NmZceDc3XHg3M1x4NjVceDcyXHg2Nlx4NmNceDZmXHg3N1x4MmRceDYzXHg2Zlx4NmVceDc0XHg2","stcfp":"Z2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4MjA4NykKICAgIGF0IDxjb21wdXRlZD4gW2FzIGRkX2FjXSAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDE4MjgpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjU2OTA5","ckwa":true,"glvd":"ARM","glrd":"Mali-G610 MC6","wwl":false,"jset":1727368033}&eventCounters=[]&jsType=ch&cid=_HVXtG_qYKC_7qVGzucgKRERQZKdu0OX2QWSHlhBY2mKRFTznVsiPH1avKpVyWC2xPjcEU6HpZUeVmohtzPmY8uyqnYVsxHP_HORmhr0xm3Z73h6A2j95cLo67lwH0Pj&ddk=789361B674144528D0B7EE76B35826&Referer=https%3A%2F%2Frendezvousparis.hermes.com%2Fclient%2Fregister%2F6GJ97H&request=%2Fclient%2Fregister%2F6GJ97H&responsePage=origin&ddv=4.35.1
|
|
||||||
+1
-1
@@ -12,7 +12,7 @@ chinnese_number_prefix = ['13', '15', '18']
|
|||||||
|
|
||||||
def read_contacts(file_name) -> list:
|
def read_contacts(file_name) -> list:
|
||||||
print("read file " + file_name)
|
print("read file " + file_name)
|
||||||
contact_list_in_json = pandas.read_excel(file_name).to_json(orient='records')
|
contact_list_in_json = pandas.read_excel(file_name, dtype={'passport': str}).to_json(orient='records')
|
||||||
contact_dict_list = json.loads(contact_list_in_json)
|
contact_dict_list = json.loads(contact_list_in_json)
|
||||||
contact_list = []
|
contact_list = []
|
||||||
for contact_dict in contact_dict_list:
|
for contact_dict in contact_dict_list:
|
||||||
|
|||||||
@@ -3,10 +3,14 @@ import time
|
|||||||
from workers.link_validator_with_provided_list import validate_all_links
|
from workers.link_validator_with_provided_list import validate_all_links
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def start_link_validation():
|
||||||
# generate test data
|
# generate test data
|
||||||
while True:
|
while True:
|
||||||
print("call validate_all_links()")
|
print("call validate_all_links()")
|
||||||
validate_all_links([])
|
validate_all_links([])
|
||||||
print("wait for 30 seconds")
|
print("wait for 30 seconds")
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
start_link_validation()
|
||||||
|
|||||||
+18
-13
@@ -9,6 +9,7 @@ from mail.mail_reader_all_contacts import find_links_to_validate_from_mail_list
|
|||||||
from models.mail_pojo import MailAddress
|
from models.mail_pojo import MailAddress
|
||||||
|
|
||||||
host = "https://authhk.bhdata.com:30015/bhmailer?uid=482391396&sign=32d7748da00047b9a1054c81a5750365"
|
host = "https://authhk.bhdata.com:30015/bhmailer?uid=482391396&sign=32d7748da00047b9a1054c81a5750365"
|
||||||
|
is_checking = False
|
||||||
|
|
||||||
HERMES_EMAIL = "no-reply@hermes.com"
|
HERMES_EMAIL = "no-reply@hermes.com"
|
||||||
|
|
||||||
@@ -92,16 +93,20 @@ def check_confirmed_mails():
|
|||||||
|
|
||||||
|
|
||||||
def check_all_need_to_check_emails():
|
def check_all_need_to_check_emails():
|
||||||
logger = logging.getLogger()
|
global is_checking
|
||||||
_mail_list_before_filter = get_mail_list_to_check()
|
if not is_checking:
|
||||||
_mails = filter_mail_with_links(_mail_list_before_filter)
|
is_checking = True
|
||||||
for _mail in _mails:
|
logger = logging.getLogger()
|
||||||
if "outlook.com" in _mail or "hotmail.com" in _mail:
|
_mail_list_before_filter = get_mail_list_to_check()
|
||||||
check_mail(_mail)
|
_mails = filter_mail_with_links(_mail_list_before_filter)
|
||||||
time.sleep(2)
|
for _mail in _mails:
|
||||||
|
if "outlook.com" in _mail or "hotmail.com" in _mail:
|
||||||
|
check_mail(_mail)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
_mail_list = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
|
# _mail_list = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
|
||||||
find_links_to_validate_from_mail_list(_mail_list, logger)
|
# find_links_to_validate_from_mail_list(_mail_list, logger)
|
||||||
|
is_checking = False
|
||||||
|
|
||||||
|
|
||||||
def try_to_check_all_mails():
|
def try_to_check_all_mails():
|
||||||
@@ -112,12 +117,12 @@ def try_to_check_all_mails():
|
|||||||
if "outlook.com" in _mail or "hotmail.com" in _mail:
|
if "outlook.com" in _mail or "hotmail.com" in _mail:
|
||||||
check_appointment_link_mail(_mail)
|
check_appointment_link_mail(_mail)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
_mail_list = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
|
# _mail_list = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
|
||||||
find_links_to_validate_from_mail_list(_mail_list, logger)
|
# find_links_to_validate_from_mail_list(_mail_list, logger)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# check_all_need_to_check_emails()
|
check_all_need_to_check_emails()
|
||||||
try_to_check_all_mails()
|
# try_to_check_all_mails()
|
||||||
# check_confirmed_mails()
|
# check_confirmed_mails()
|
||||||
# check_appointment_link_mail("hcunlvi533@outlook.com")
|
# check_appointment_link_mail("hcunlvi533@outlook.com")
|
||||||
|
|||||||
+33
-51
@@ -2,6 +2,7 @@ import imaplib
|
|||||||
|
|
||||||
from imapclient import IMAPClient
|
from imapclient import IMAPClient
|
||||||
|
|
||||||
|
# 邮件域名常量
|
||||||
DOMAIN_YAHOO = "yahoo.com"
|
DOMAIN_YAHOO = "yahoo.com"
|
||||||
DOMAIN_SINA = "sina.com"
|
DOMAIN_SINA = "sina.com"
|
||||||
DOMAIN_HOTMAIL = "hotmail.com"
|
DOMAIN_HOTMAIL = "hotmail.com"
|
||||||
@@ -10,9 +11,9 @@ DOMAIN_163 = "163.com"
|
|||||||
DOMAIN_RAMBLER_RU = "rambler.ru"
|
DOMAIN_RAMBLER_RU = "rambler.ru"
|
||||||
DOMAIN_ALICE_IT = "alice.it"
|
DOMAIN_ALICE_IT = "alice.it"
|
||||||
DOMAIN_MARS_DTI_NE_JP = "mars.dti.ne.jp"
|
DOMAIN_MARS_DTI_NE_JP = "mars.dti.ne.jp"
|
||||||
DOMAN_BTVM_NE_JP = "btvm.ne.jp"
|
DOMAIN_BTVM_NE_JP = "btvm.ne.jp"
|
||||||
DOMAN_AURORA_DTI_NE_JP = "aurora.dti.ne.jp"
|
DOMAIN_AURORA_DTI_NE_JP = "aurora.dti.ne.jp"
|
||||||
DOMAN_GMAIL = "gmail.com"
|
DOMAIN_GMAIL = "gmail.com"
|
||||||
DOMAIN_GMX = "gmx.com"
|
DOMAIN_GMX = "gmx.com"
|
||||||
DOMAIN_GMX_NET = "gmx.net"
|
DOMAIN_GMX_NET = "gmx.net"
|
||||||
DOMAIN_GMX_AT = "gmx.at"
|
DOMAIN_GMX_AT = "gmx.at"
|
||||||
@@ -27,6 +28,7 @@ DOMAIN_NAVER = "naver.com"
|
|||||||
DOMAIN_INBOX_LV = "inbox.lv"
|
DOMAIN_INBOX_LV = "inbox.lv"
|
||||||
DOMAIN_GMX_DE = "gmx.de"
|
DOMAIN_GMX_DE = "gmx.de"
|
||||||
|
|
||||||
|
# 垃圾邮件域名
|
||||||
DOMAIN_PISS_MAIL = "pissmail.com"
|
DOMAIN_PISS_MAIL = "pissmail.com"
|
||||||
DOMAIN_INCEL_EMAIL = "incel.email"
|
DOMAIN_INCEL_EMAIL = "incel.email"
|
||||||
DOMAIN_SHITPOSTING_EXPERT = "shitposting.expert"
|
DOMAIN_SHITPOSTING_EXPERT = "shitposting.expert"
|
||||||
@@ -38,6 +40,7 @@ DOMAIN_WEB_DE = "web.de"
|
|||||||
DOMAIN_OUTLOOK_COM = "outlook.com"
|
DOMAIN_OUTLOOK_COM = "outlook.com"
|
||||||
DOMAIN_FIREMAIL_DE = "firemail.de"
|
DOMAIN_FIREMAIL_DE = "firemail.de"
|
||||||
|
|
||||||
|
# IMAP服务器地址常量
|
||||||
AOL_IMAP_SERVER = "imap.aol.com"
|
AOL_IMAP_SERVER = "imap.aol.com"
|
||||||
IMAP_SERVER_163 = "imap.163.com"
|
IMAP_SERVER_163 = "imap.163.com"
|
||||||
IMAP_SERVER_SINA = "imap.sina.com"
|
IMAP_SERVER_SINA = "imap.sina.com"
|
||||||
@@ -49,18 +52,17 @@ ALICE_IMAP_SERVER = "in.alice.it"
|
|||||||
TIME_IT_SERVER = "imap.tim.it"
|
TIME_IT_SERVER = "imap.tim.it"
|
||||||
MARS_DTI_NE_JP_SERVER = "imap.cm.dream.jp"
|
MARS_DTI_NE_JP_SERVER = "imap.cm.dream.jp"
|
||||||
NAVER_SERVER = "imap.naver.com"
|
NAVER_SERVER = "imap.naver.com"
|
||||||
BTVM_NE_JP = "imap.btvm.ne.jp"
|
BTVM_NE_JP_SERVER = "imap.btvm.ne.jp"
|
||||||
SEREVER_GMAIL = "imap.gmail.com"
|
GMAIL_IMAP_SERVER = "imap.gmail.com"
|
||||||
SERVER_IMAGE_ONET = "imap.poczta.onet.pl"
|
ONET_IMAP_SERVER = "imap.poczta.onet.pl"
|
||||||
SERVER_GMX = "imap.gmx.com"
|
GMX_IMAP_SERVER = "imap.gmx.com"
|
||||||
SERVER_GMX_NET = "imap.gmx.net"
|
GMX_NET_IMAP_SERVER = "imap.gmx.net"
|
||||||
SERVER_GMX_AT = "imap.gmx.at"
|
GMX_AT_IMAP_SERVER = "imap.gmx.at"
|
||||||
SERVER_FIREMAIL_DE = "imap.firemail.de"
|
FIREMAIL_DE_IMAP_SERVER = "imap.firemail.de"
|
||||||
SERVER_PISS_MAIL = "mail.pissmail.com"
|
PISS_MAIL_IMAP_SERVER = "mail.pissmail.com"
|
||||||
INBOX_LV = "mail.inbox.lv"
|
INBOX_LV_IMAP_SERVER = "mail.inbox.lv"
|
||||||
SERVER_WEB_DE = "imap.web.de"
|
WEB_DE_IMAP_SERVER = "imap.web.de"
|
||||||
IMAP_SERVER_DOMAIN_GAZETA_PL = "imap.gazeta.pl"
|
GAZETA_PL_IMAP_SERVER = "imap.gazeta.pl"
|
||||||
|
|
||||||
|
|
||||||
def show_folders(imap) -> list:
|
def show_folders(imap) -> list:
|
||||||
folders = []
|
folders = []
|
||||||
@@ -82,69 +84,49 @@ def show_folders(imap) -> list:
|
|||||||
|
|
||||||
|
|
||||||
def create_imap(login: str):
|
def create_imap(login: str):
|
||||||
# create an IMAP4 class with SSL
|
# 创建一个IMAP4类实例
|
||||||
if DOMAIN_163 in login:
|
if DOMAIN_163 in login:
|
||||||
imap = IMAPClient(IMAP_SERVER_163, use_uid=True)
|
imap = IMAPClient(IMAP_SERVER_163, use_uid=True)
|
||||||
elif DOMAIN_YAHOO in login:
|
elif DOMAIN_YAHOO in login:
|
||||||
# imap = imaplib.IMAP4_SSL(YAHOO_IMAP_SERVER)
|
|
||||||
imap = IMAPClient(YAHOO_IMAP_SERVER, use_uid=True)
|
imap = IMAPClient(YAHOO_IMAP_SERVER, use_uid=True)
|
||||||
elif DOMAIN_FIREMAIL_DE in login:
|
elif DOMAIN_FIREMAIL_DE in login:
|
||||||
# imap = imaplib.IMAP4_SSL(SERVER_FIREMAIL_DE)
|
imap = IMAPClient(FIREMAIL_DE_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(SERVER_FIREMAIL_DE, use_uid=True)
|
|
||||||
elif DOMAIN_GMX in login or DOMAIN_GMX_FR in login or DOMAIN_GMX_US in login or DOMAIN_GMX_CH in login or DOMAIN_GMX_PT in login or DOMAIN_GMX_SG in login:
|
elif DOMAIN_GMX in login or DOMAIN_GMX_FR in login or DOMAIN_GMX_US in login or DOMAIN_GMX_CH in login or DOMAIN_GMX_PT in login or DOMAIN_GMX_SG in login:
|
||||||
# imap = imaplib.IMAP4_SSL(SERVER_GMX)
|
imap = IMAPClient(GMX_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(SERVER_GMX, use_uid=True)
|
|
||||||
elif DOMAIN_SINA in login:
|
elif DOMAIN_SINA in login:
|
||||||
# imap = imaplib.IMAP4_SSL(IMAP_SERVER_SINA)
|
|
||||||
imap = IMAPClient(IMAP_SERVER_SINA, use_uid=True)
|
imap = IMAPClient(IMAP_SERVER_SINA, use_uid=True)
|
||||||
elif DOMAIN_HOTMAIL in login or DOMAIN_OUTLOOK_COM in login:
|
elif DOMAIN_HOTMAIL in login or DOMAIN_OUTLOOK_COM in login:
|
||||||
# imap = imaplib.IMAP4_SSL(HOTMAIL_IMAP_SERVER)
|
|
||||||
imap = IMAPClient(HOTMAIL_IMAP_SERVER, use_uid=True)
|
imap = IMAPClient(HOTMAIL_IMAP_SERVER, use_uid=True)
|
||||||
elif DOMAIN_RAMBLER_RU in login:
|
elif DOMAIN_RAMBLER_RU in login:
|
||||||
# imap = imaplib.IMAP4_SSL(RAMBLER_IMAP_SERVER)
|
|
||||||
imap = IMAPClient(RAMBLER_IMAP_SERVER, use_uid=True)
|
imap = IMAPClient(RAMBLER_IMAP_SERVER, use_uid=True)
|
||||||
elif DOMAN_BTVM_NE_JP in login:
|
elif DOMAIN_BTVM_NE_JP in login:
|
||||||
# imap = imaplib.IMAP4_SSL(BTVM_NE_JP)
|
imap = IMAPClient(BTVM_NE_JP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(BTVM_NE_JP, use_uid=True)
|
elif DOMAIN_GMAIL in login:
|
||||||
elif DOMAN_GMAIL in login:
|
imap = IMAPClient(GMAIL_IMAP_SERVER, use_uid=True)
|
||||||
# imap = imaplib.IMAP4_SSL(SEREVER_GMAIL, port=993)
|
|
||||||
imap = IMAPClient(SEREVER_GMAIL, use_uid=True)
|
|
||||||
elif DOMAIN_ONET in login:
|
elif DOMAIN_ONET in login:
|
||||||
imap = IMAPClient(SERVER_IMAGE_ONET, use_uid=True)
|
imap = IMAPClient(ONET_IMAP_SERVER, use_uid=True)
|
||||||
elif DOMAIN_TIM_IT in login:
|
elif DOMAIN_TIM_IT in login:
|
||||||
# imap = imaplib.IMAP4(TIME_IT_SERVER)
|
|
||||||
imap = IMAPClient(TIME_IT_SERVER, use_uid=True)
|
imap = IMAPClient(TIME_IT_SERVER, use_uid=True)
|
||||||
elif DOMAIN_ALICE_IT in login:
|
elif DOMAIN_ALICE_IT in login:
|
||||||
# imap = imaplib.IMAP4(ALICE_IMAP_SERVER, port=143)
|
|
||||||
imap = IMAPClient(ALICE_IMAP_SERVER, use_uid=True)
|
imap = IMAPClient(ALICE_IMAP_SERVER, use_uid=True)
|
||||||
elif DOMAIN_MARS_DTI_NE_JP in login:
|
elif DOMAIN_MARS_DTI_NE_JP in login:
|
||||||
# imap = imaplib.IMAP4(MARS_DTI_NE_JP_SERVER, port=143)
|
|
||||||
imap = IMAPClient(MARS_DTI_NE_JP_SERVER, use_uid=True)
|
imap = IMAPClient(MARS_DTI_NE_JP_SERVER, use_uid=True)
|
||||||
elif DOMAN_AURORA_DTI_NE_JP in login:
|
elif DOMAIN_AURORA_DTI_NE_JP in login:
|
||||||
# imap = imaplib.IMAP4(MARS_DTI_NE_JP_SERVER, port=143)
|
|
||||||
imap = IMAPClient(MARS_DTI_NE_JP_SERVER, use_uid=True)
|
imap = IMAPClient(MARS_DTI_NE_JP_SERVER, use_uid=True)
|
||||||
elif DOMAIN_NAVER in login:
|
elif DOMAIN_NAVER in login:
|
||||||
# imap = imaplib.IMAP4_SSL(NAVER_SERVER, port=993)
|
|
||||||
imap = IMAPClient(NAVER_SERVER, use_uid=True)
|
imap = IMAPClient(NAVER_SERVER, use_uid=True)
|
||||||
elif DOMAIN_GMX_DE in login or DOMAIN_GMX_NET in login:
|
elif DOMAIN_GMX_DE in login or DOMAIN_GMX_NET in login:
|
||||||
# imap = imaplib.IMAP4_SSL(SERVER_GMX_NET, port=993)
|
imap = IMAPClient(GMX_NET_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(SERVER_GMX_NET, use_uid=True)
|
|
||||||
elif DOMAIN_GMX_AT in login:
|
elif DOMAIN_GMX_AT in login:
|
||||||
# imap = imaplib.IMAP4_SSL(SERVER_GMX_AT, port=993)
|
imap = IMAPClient(GMX_AT_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(SERVER_GMX_AT, use_uid=True)
|
|
||||||
elif DOMAIN_GAZETA_PL in login:
|
elif DOMAIN_GAZETA_PL in login:
|
||||||
# imap = imaplib.IMAP4_SSL(IMAP_SERVER_DOMAIN_GAZETA_PL, port=993)
|
imap = IMAPClient(GAZETA_PL_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(IMAP_SERVER_DOMAIN_GAZETA_PL, use_uid=True)
|
|
||||||
elif DOMAIN_INBOX_LV in login:
|
elif DOMAIN_INBOX_LV in login:
|
||||||
# imap = imaplib.IMAP4_SSL(INBOX_LV, port=993)
|
imap = IMAPClient(INBOX_LV_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(INBOX_LV, use_uid=True)
|
|
||||||
elif DOMAIN_WEB_DE in login:
|
elif DOMAIN_WEB_DE in login:
|
||||||
# imap = imaplib.IMAP4_SSL(SERVER_WEB_DE, port=993)
|
imap = IMAPClient(WEB_DE_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(SERVER_WEB_DE, use_uid=True)
|
|
||||||
elif DOMAIN_PISS_MAIL in login or DOMAIN_CHILD_PIZZA in login or DOMAIN_DMC_CHAT in login or DOMAIN_GENOCIDE_FUN in login or DOMAIN_HATESJE_WS in login or DOMAIN_INCEL_EMAIL in login or DOMAIN_SHITPOSTING_EXPERT in login:
|
elif DOMAIN_PISS_MAIL in login or DOMAIN_CHILD_PIZZA in login or DOMAIN_DMC_CHAT in login or DOMAIN_GENOCIDE_FUN in login or DOMAIN_HATESJE_WS in login or DOMAIN_INCEL_EMAIL in login or DOMAIN_SHITPOSTING_EXPERT in login:
|
||||||
# imap = imaplib.IMAP4_SSL(SERVER_PISS_MAIL, port=993)
|
imap = IMAPClient(PISS_MAIL_IMAP_SERVER, use_uid=True)
|
||||||
imap = IMAPClient(SERVER_PISS_MAIL, use_uid=True)
|
|
||||||
else:
|
else:
|
||||||
# imap = imaplib.IMAP4_SSL(AOL_IMAP_SERVER)
|
|
||||||
imap = IMAPClient(AOL_IMAP_SERVER, use_uid=True)
|
imap = IMAPClient(AOL_IMAP_SERVER, use_uid=True)
|
||||||
return imap
|
return imap
|
||||||
Executable → Regular
+284
-161
@@ -2,11 +2,10 @@ import datetime
|
|||||||
import email
|
import email
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from builtins import list
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from email.header import decode_header
|
from email.header import decode_header
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
from typing import Union
|
from typing import Union, List
|
||||||
|
|
||||||
from imapclient import IMAPClient
|
from imapclient import IMAPClient
|
||||||
from db.mongo_manager import MONGO_STORE_MANAGER
|
from db.mongo_manager import MONGO_STORE_MANAGER
|
||||||
@@ -15,74 +14,87 @@ from mail.mail_constants import DOMAIN_HOTMAIL, create_imap
|
|||||||
from models.ReserveResultPojo import ReserveResultPojo
|
from models.ReserveResultPojo import ReserveResultPojo
|
||||||
from models.mail_pojo import MailPojo, MailAddress
|
from models.mail_pojo import MailPojo, MailAddress
|
||||||
|
|
||||||
VALIDATION_URL_SUBJECT_fr = 'Validation de votre demande de rendez-vous'
|
# 定义常量
|
||||||
|
VALIDATION_URL_SUBJECT_FR = 'Validation de votre demande de rendez-vous'
|
||||||
VALIDATION_URL_SUBJECT_EN = 'Please confirm your appointment request'
|
VALIDATION_URL_SUBJECT_EN = 'Please confirm your appointment request'
|
||||||
VALIDATION_URL_REGEX = """https:\/\/rendezvousparis.hermes.com\/client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"""
|
VALIDATION_URL_REGEX = r"https:\/\/rendezvousparis.hermes.com\/client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"
|
||||||
PART_VALIDATION_URL_REGEX = """client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"""
|
PART_VALIDATION_URL_REGEX = r"client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"
|
||||||
HERMES_EMAIL = "no-reply@hermes.com"
|
HERMES_EMAIL = "no-reply@hermes.com"
|
||||||
EMAIL_ADDRESS_REGEX = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b'
|
EMAIL_ADDRESS_REGEX = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b'
|
||||||
|
|
||||||
date_format = "%d-%b-%Y" # DD-Mon-YYYY e.g., 3-Mar-2014
|
# 日期格式
|
||||||
|
DATE_FORMAT = "%d-%b-%Y"
|
||||||
|
|
||||||
|
# 邮箱列表(简化为常量)
|
||||||
REDIRECTION_MAILS = "appointment2022@aol.com, chenpeijun@aol.com,hongjiang176@aol.com,ciyuexie@aol.com,rutger.62@aol.com,ciccidaniel@aol.com,armasgoodman@aol.com,wknd.gemerine@aol.com,rafmail1981@aol.com,tonovichivanenaki@aol.com,hetland.ari@aol.com,mateusiversen@aol.com,lacerdaraffaello@aol.com,anasida76@aol.com,liamolinari@aol.com,sen70zib@aol.com,mezeiderrick@aol.com,stanisl49avchic@aol.com,damcvrobaneuron@aol.com,suyzanna_fleona@aol.com,dxealing.dissa@aol.com,hogg.karen@aol.com,obocharovamarina@aol.com,buchholzjohann@aol.com,orn.cecchini@aol.com,percivaltorgersen@aol.com,candalgudrun@aol.com,filimonis.76@aol.com,bengann_100@aol.com,axelhanne@aol.com,tiffanylarochelle@aol.com,nicoleta.r@aol.com,eichenbaum.1963@aol.com,kotensasharev@aol.com,samognat32@aol.com,edem_headshot@aol.com,kozmakuzmich1960@aol.com,damonsvensson@aol.com,anders.riva@aol.com,caiminwei123@gmail.com,yulingguo086@gmail.com,yingxiaolu086@gmail.com,lijiazhen0035@gmail.com,fangp370@gmail.com,huangyayu10086@gmail.com,fuziyuan110@gmail.com,xinyingdu886@gmail.com,yasiaforever.1971@aol.com,lukaszfidalgo@aol.com,zaichi29@aol.com,prostotakitak.1974@aol.com,mo90nroe@aol.com,blonde.87@aol.com,dimidrol.1969@aol.com"
|
REDIRECTION_MAILS = "appointment2022@aol.com, chenpeijun@aol.com,hongjiang176@aol.com,ciyuexie@aol.com,rutger.62@aol.com,ciccidaniel@aol.com,armasgoodman@aol.com,wknd.gemerine@aol.com,rafmail1981@aol.com,tonovichivanenaki@aol.com,hetland.ari@aol.com,mateusiversen@aol.com,lacerdaraffaello@aol.com,anasida76@aol.com,liamolinari@aol.com,sen70zib@aol.com,mezeiderrick@aol.com,stanisl49avchic@aol.com,damcvrobaneuron@aol.com,suyzanna_fleona@aol.com,dxealing.dissa@aol.com,hogg.karen@aol.com,obocharovamarina@aol.com,buchholzjohann@aol.com,orn.cecchini@aol.com,percivaltorgersen@aol.com,candalgudrun@aol.com,filimonis.76@aol.com,bengann_100@aol.com,axelhanne@aol.com,tiffanylarochelle@aol.com,nicoleta.r@aol.com,eichenbaum.1963@aol.com,kotensasharev@aol.com,samognat32@aol.com,edem_headshot@aol.com,kozmakuzmich1960@aol.com,damonsvensson@aol.com,anders.riva@aol.com,caiminwei123@gmail.com,yulingguo086@gmail.com,yingxiaolu086@gmail.com,lijiazhen0035@gmail.com,fangp370@gmail.com,huangyayu10086@gmail.com,fuziyuan110@gmail.com,xinyingdu886@gmail.com,yasiaforever.1971@aol.com,lukaszfidalgo@aol.com,zaichi29@aol.com,prostotakitak.1974@aol.com,mo90nroe@aol.com,blonde.87@aol.com,dimidrol.1969@aol.com"
|
||||||
|
|
||||||
|
|
||||||
def check_email_address(email):
|
# 邮件处理相关函数
|
||||||
# pass the regular expression
|
def is_valid_email(email: str) -> bool:
|
||||||
# and the string into the fullmatch() method
|
"""验证邮箱地址是否有效"""
|
||||||
if (re.fullmatch(EMAIL_ADDRESS_REGEX, email)):
|
return re.fullmatch(EMAIL_ADDRESS_REGEX, email) is not None
|
||||||
print("Valid Email")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print("Invalid Email:" + email)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def find_from_mail(param):
|
def extract_email_from_from_address(content: str) -> str:
|
||||||
|
"""从邮件地址中提取邮箱"""
|
||||||
|
match = re.search(r'[\w.+-]+@[\w-]+\.[\w.-]+', content)
|
||||||
|
return match.group(0) if match else ""
|
||||||
|
|
||||||
|
|
||||||
|
def find_from_mail(param) -> str:
|
||||||
|
"""解析邮件地址"""
|
||||||
from_address, encoded_algo = param[0]
|
from_address, encoded_algo = param[0]
|
||||||
|
|
||||||
|
# 处理字节编码
|
||||||
if isinstance(from_address, bytes):
|
if isinstance(from_address, bytes):
|
||||||
from_address = from_address.decode(encoded_algo)
|
from_address = from_address.decode(encoded_algo)
|
||||||
if not check_email_address(from_address) and len(param) == 2:
|
|
||||||
|
# 如果邮箱地址无效,尝试另一种编码
|
||||||
|
if not is_valid_email(from_address) and len(param) == 2:
|
||||||
from_address, new_encode = param[1]
|
from_address, new_encode = param[1]
|
||||||
if new_encode is None:
|
if new_encode is None:
|
||||||
new_encode = encoded_algo
|
new_encode = encoded_algo
|
||||||
if isinstance(from_address, bytes):
|
if isinstance(from_address, bytes):
|
||||||
from_address = from_address.decode(new_encode)
|
from_address = from_address.decode(new_encode)
|
||||||
return from_address.strip(" ").strip(">").strip("<")
|
|
||||||
|
# 清理邮箱地址
|
||||||
return from_address.strip(" ").strip(">").strip("<")
|
return from_address.strip(" ").strip(">").strip("<")
|
||||||
|
|
||||||
|
|
||||||
def extract_email_from_from_address(content: str):
|
class MailReader:
|
||||||
_match = re.search(r'[\w.+-]+@[\w-]+\.[\w.-]+', content)
|
"""邮件读取器类"""
|
||||||
return _match.group(0)
|
|
||||||
|
|
||||||
|
def __init__(self, login: str, password: str):
|
||||||
class MailReader():
|
|
||||||
def __init__(self, login, password):
|
|
||||||
self.login = login
|
self.login = login
|
||||||
self.password = password
|
self.password = password
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def show_folders(imap) -> list:
|
def show_folders(imap) -> List[str]:
|
||||||
|
"""获取邮箱文件夹列表"""
|
||||||
folders = []
|
folders = []
|
||||||
isImapClient = isinstance(imap, IMAPClient)
|
is_imap_client = isinstance(imap, IMAPClient)
|
||||||
if not isImapClient:
|
|
||||||
|
if not is_imap_client:
|
||||||
|
# 处理非IMAPClient对象
|
||||||
for i in imap.list()[1]:
|
for i in imap.list()[1]:
|
||||||
l = i.decode().split(' "/" ')
|
l = i.decode().split(' "/" ')
|
||||||
folders.append(l[1])
|
folders.append(l[1])
|
||||||
return folders
|
|
||||||
else:
|
else:
|
||||||
list = imap.list_folders()
|
# 处理IMAPClient对象
|
||||||
for i in list:
|
folder_list = imap.list_folders()
|
||||||
|
for i in folder_list:
|
||||||
name = i[-1]
|
name = i[-1]
|
||||||
folders.append(name)
|
folders.append(name)
|
||||||
return folders
|
|
||||||
|
|
||||||
def read_emails(self, mails_messages: list) -> list:
|
return folders
|
||||||
|
|
||||||
|
def read_emails(self, mails_messages: List[MailPojo]) -> List[MailPojo]:
|
||||||
|
"""读取邮件"""
|
||||||
imap = create_imap(self.login)
|
imap = create_imap(self.login)
|
||||||
isImapClient = isinstance(imap, IMAPClient)
|
is_imap_client = isinstance(imap, IMAPClient)
|
||||||
print("isImapClient is " + str(isImapClient))
|
|
||||||
if isImapClient:
|
# 登录邮箱
|
||||||
# authenticate
|
if is_imap_client:
|
||||||
dat = imap.login(self.login, str(self.password))
|
dat = imap.login(self.login, str(self.password))
|
||||||
print("type is {} for {}".format(dat, self.login))
|
print("type is {} for {}".format(dat, self.login))
|
||||||
else:
|
else:
|
||||||
@@ -91,224 +103,335 @@ class MailReader():
|
|||||||
|
|
||||||
mail_list = []
|
mail_list = []
|
||||||
print("read mails from {}".format(self.login))
|
print("read mails from {}".format(self.login))
|
||||||
if not isImapClient:
|
|
||||||
folder_list = self.show_folders(imap)
|
# 获取文件夹列表
|
||||||
for folder in folder_list:
|
folder_list = self.show_folders(imap)
|
||||||
print("folder is {}".format(folder))
|
|
||||||
mail_list.extend(self._get_messages_from_folder(imap, subject=VALIDATION_URL_SUBJECT_fr,
|
# 处理每个文件夹
|
||||||
folder=folder))
|
for folder in folder_list:
|
||||||
mail_list.extend(self._get_messages_from_folder(imap, subject=VALIDATION_URL_SUBJECT_EN,
|
print("folder is {}".format(folder))
|
||||||
folder=folder))
|
|
||||||
else:
|
# 跳过Sent和Drafts文件夹
|
||||||
folder_list = self.show_folders(imap)
|
if folder in ["Sent", "Drafts"]:
|
||||||
for folder in folder_list:
|
continue
|
||||||
print("folder is " + folder)
|
|
||||||
if folder == "Sent" or folder == "Drafts":
|
if is_imap_client:
|
||||||
pass
|
# 使用IMAPClient处理
|
||||||
else:
|
mail_list.extend(self._get_messages_from_folder_for_imapclient(imap, folder))
|
||||||
mail_list.extend(self._get_messages_from_folder_for_imapclient(imap, folder=folder))
|
else:
|
||||||
if not isImapClient:
|
# 使用传统IMAP处理
|
||||||
|
mail_list.extend(self._get_messages_from_folder(imap, subject=VALIDATION_URL_SUBJECT_FR, folder=folder))
|
||||||
|
mail_list.extend(self._get_messages_from_folder(imap, subject=VALIDATION_URL_SUBJECT_EN, folder=folder))
|
||||||
|
|
||||||
|
# 关闭连接
|
||||||
|
if not is_imap_client:
|
||||||
imap.close()
|
imap.close()
|
||||||
imap.logout()
|
imap.logout()
|
||||||
|
|
||||||
|
# 添加邮件到结果列表
|
||||||
mails_messages.extend(mail_list)
|
mails_messages.extend(mail_list)
|
||||||
return mail_list
|
return mail_list
|
||||||
|
|
||||||
def _get_messages_from_folder(self, imap, subject, folder="INBOX") -> list:
|
def _get_messages_from_folder(self, imap, subject: str, folder: str = "INBOX") -> List[MailPojo]:
|
||||||
|
"""从指定文件夹获取邮件(传统IMAP方式)"""
|
||||||
imap.select(folder)
|
imap.select(folder)
|
||||||
mail_messages = []
|
mail_messages = []
|
||||||
typ, data = imap.search(None, '(SUBJECT "{}" SINCE "{}")'.format(subject,
|
|
||||||
datetime.datetime.today().strftime(
|
# 搜索邮件
|
||||||
date_format)))
|
search_query = '(SUBJECT "{}" SINCE "{}")'.format(subject, datetime.datetime.today().strftime(DATE_FORMAT))
|
||||||
|
typ, data = imap.search(None, search_query)
|
||||||
|
|
||||||
for i in data[0].split():
|
for i in data[0].split():
|
||||||
# fetch the email message by ID
|
try:
|
||||||
res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)")
|
# 获取邮件内容
|
||||||
body = ''
|
res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)")
|
||||||
for response in msg:
|
|
||||||
if isinstance(response, tuple):
|
# 解析邮件
|
||||||
# parse a bytes email into a message object
|
for response in msg:
|
||||||
msg = email.message_from_bytes(response[1])
|
if isinstance(response, tuple):
|
||||||
# decode the email subject
|
email_message = email.message_from_bytes(response[1])
|
||||||
subject, subject_encoded = decode_header(msg["Subject"])[0]
|
|
||||||
received_date = msg["Date"]
|
# 解码主题
|
||||||
if isinstance(subject, bytes):
|
subject, subject_encoded = decode_header(email_message["Subject"])[0]
|
||||||
# if it's a bytes, decode to str
|
if isinstance(subject, bytes):
|
||||||
subject = subject.decode(subject_encoded)
|
subject = subject.decode(subject_encoded)
|
||||||
# decode email sender
|
|
||||||
from_address = find_from_mail(decode_header(msg.get("From")))
|
# 解码发件人地址
|
||||||
to_email = find_from_mail(decode_header(msg.get("To")))
|
from_address = find_from_mail(decode_header(email_message.get("From")))
|
||||||
print("Email:", self.login)
|
|
||||||
print("From:", from_address)
|
# 解码收件人地址
|
||||||
print("To:", to_email)
|
to_email = find_from_mail(decode_header(email_message.get("To")))
|
||||||
print("Subject:", subject)
|
|
||||||
# if the email message is multipart
|
print("Email:", self.login)
|
||||||
if msg.is_multipart():
|
print("From:", from_address)
|
||||||
# iterate over email parts
|
print("To:", to_email)
|
||||||
for part in msg.walk():
|
print("Subject:", subject)
|
||||||
try:
|
|
||||||
# get the email body
|
# 获取邮件正文
|
||||||
payloads = part.get_payload()
|
body = self._extract_body(email_message)
|
||||||
if isinstance(payloads, list):
|
|
||||||
for payload in payloads:
|
# 检查是否是预约验证邮件
|
||||||
if isinstance(payload, Message):
|
if VALIDATION_URL_SUBJECT_FR in subject or VALIDATION_URL_SUBJECT_EN in subject:
|
||||||
body = body + payload.get_payload(decode=True).decode("iso-8859-1")
|
mail = MailPojo(
|
||||||
# print(body)
|
subject=subject,
|
||||||
except Exception as Error:
|
body=body,
|
||||||
print(Error)
|
from_address=from_address
|
||||||
else:
|
)
|
||||||
body = msg.get_payload(decode=True).decode()
|
|
||||||
print(body)
|
# 设置收件人地址
|
||||||
if VALIDATION_URL_SUBJECT_fr in subject or VALIDATION_URL_SUBJECT_EN in subject:
|
if to_email is None:
|
||||||
mail = MailPojo(subject=subject, body=body, from_address=from_address)
|
mail.to_address = self.login
|
||||||
if to_email is None:
|
else:
|
||||||
mail.to_address = self.login
|
mail.to_address = to_email
|
||||||
else:
|
|
||||||
mail.to_address = to_email
|
mail.mail_address = self.login
|
||||||
mail.mail_address = self.login
|
mail_messages.append(mail)
|
||||||
mail_messages.append(mail)
|
except Exception as error:
|
||||||
|
print("Error processing email: {}".format(error))
|
||||||
|
|
||||||
return mail_messages
|
return mail_messages
|
||||||
|
|
||||||
def _get_messages_from_folder_for_imapclient(self, imap, folder="INBOX") -> list:
|
def _extract_body(self, email_message: Message) -> str:
|
||||||
|
"""提取邮件正文"""
|
||||||
|
body = ""
|
||||||
|
|
||||||
|
# 遍历邮件部分
|
||||||
|
for part in email_message.walk():
|
||||||
|
try:
|
||||||
|
content_type = part.get_content_type()
|
||||||
|
|
||||||
|
if content_type == "text/html":
|
||||||
|
# 处理HTML内容
|
||||||
|
payload = part.get_payload(decode=True)
|
||||||
|
if payload:
|
||||||
|
body += payload.decode("utf-8", errors="ignore")
|
||||||
|
elif content_type == "text/plain":
|
||||||
|
# 处理纯文本内容
|
||||||
|
payload = part.get_payload()
|
||||||
|
if payload:
|
||||||
|
body += payload
|
||||||
|
except Exception as error:
|
||||||
|
print("Error extracting body part: {}".format(error))
|
||||||
|
|
||||||
|
return body
|
||||||
|
|
||||||
|
def _get_messages_from_folder_for_imapclient(self, imap, folder: str = "INBOX") -> List[MailPojo]:
|
||||||
|
"""从指定文件夹获取邮件(IMAPClient方式)"""
|
||||||
mail_messages = []
|
mail_messages = []
|
||||||
|
|
||||||
|
# 搜索邮件
|
||||||
search_terms = 'SINCE "{}"'.format(
|
search_terms = 'SINCE "{}"'.format(
|
||||||
datetime.datetime.today().strftime(
|
datetime.datetime.today().strftime(DATE_FORMAT))
|
||||||
date_format))
|
print("{}: search terms is {}".format(self.login, search_terms))
|
||||||
print("{}: search terms is {}".format(self.login,search_terms))
|
|
||||||
imap.select_folder(folder)
|
imap.select_folder(folder)
|
||||||
messages = imap.search(['SINCE', datetime.datetime.today()])
|
messages = imap.search(['SINCE', datetime.datetime.today()])
|
||||||
print("{}: {} messages from our best friend".format(self.login, len(messages)))
|
print("{}: {} messages from our best friend".format(self.login, len(messages)))
|
||||||
if len(messages) ==0:
|
|
||||||
|
if len(messages) == 0:
|
||||||
return mail_messages
|
return mail_messages
|
||||||
|
|
||||||
|
# 处理每封邮件
|
||||||
for uid, message_data in imap.fetch(messages, 'RFC822').items():
|
for uid, message_data in imap.fetch(messages, 'RFC822').items():
|
||||||
try:
|
try:
|
||||||
email_message = email.message_from_bytes(message_data[b'RFC822'])
|
email_message = email.message_from_bytes(message_data[b'RFC822'])
|
||||||
|
|
||||||
|
# 获取发件人和主题
|
||||||
from_address = email_message.get('FROM')
|
from_address = email_message.get('FROM')
|
||||||
subject = email_message.get('subject')
|
subject = email_message.get('subject')
|
||||||
body = ""
|
|
||||||
hermes_mail_adress = "no-reply@hermes.com"
|
# 检查是否是Hermes邮件
|
||||||
if hermes_mail_adress in from_address or "outlook.com" in from_address or "hotmail" in from_address:
|
hermes_mail_address = "no-reply@hermes.com"
|
||||||
for part in email_message.walk():
|
if (hermes_mail_address in from_address or
|
||||||
print(part.get_content_type())
|
"outlook.com" in from_address or
|
||||||
if part.get_content_type() == "text/html":
|
"hotmail" in from_address):
|
||||||
body = body + part.get_payload(decode=True).decode("utf-8")
|
|
||||||
elif part.get_content_type() == "text/plain":
|
# 提取邮件正文
|
||||||
body = body + part.get_payload()
|
body = self._extract_body_for_imapclient(email_message)
|
||||||
if VALIDATION_URL_SUBJECT_fr in subject or VALIDATION_URL_SUBJECT_EN in subject or "Votre=20demande=20de=20rendez-vous" in subject or "Votre demande de rendez-vous" in body:
|
|
||||||
mail = MailPojo(subject=subject, body=body, from_address=from_address)
|
# 检查是否是预约验证邮件
|
||||||
|
if (VALIDATION_URL_SUBJECT_FR in subject or
|
||||||
|
VALIDATION_URL_SUBJECT_EN in subject or
|
||||||
|
"Votre=20demande=20de=20rendez-vous" in subject or
|
||||||
|
"Votre demande de rendez-vous" in body):
|
||||||
|
|
||||||
|
mail = MailPojo(
|
||||||
|
subject=subject,
|
||||||
|
body=body,
|
||||||
|
from_address=from_address
|
||||||
|
)
|
||||||
mail.isImapClient = True
|
mail.isImapClient = True
|
||||||
|
|
||||||
print("email is {}".format(self.login))
|
print("email is {}".format(self.login))
|
||||||
print("body is {}".format(body))
|
print("body is {}".format(body))
|
||||||
print("subject is {}".format(subject))
|
print("subject is {}".format(subject))
|
||||||
|
|
||||||
|
# 设置收件人地址
|
||||||
if len(mail.to_address) == 0:
|
if len(mail.to_address) == 0:
|
||||||
if "outlook.com" in from_address or "hotmail.com" in from_address:
|
if "outlook.com" in from_address or "hotmail.com" in from_address:
|
||||||
# it is a transferred email
|
# 转发邮件
|
||||||
mail.to_address = extract_email_from_from_address(from_address)
|
mail.to_address = extract_email_from_from_address(from_address)
|
||||||
else:
|
else:
|
||||||
mail.to_address = self.login
|
mail.to_address = self.login
|
||||||
|
|
||||||
mail_messages.append(mail)
|
mail_messages.append(mail)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
print(error)
|
print("Error trying to read email_Message for {}: {}".format(self.login, error))
|
||||||
print("error trying to read email_Message for {}".format(self.login))
|
|
||||||
return mail_messages
|
return mail_messages
|
||||||
|
|
||||||
|
def _extract_body_for_imapclient(self, email_message: Message) -> str:
|
||||||
|
"""提取IMAPClient邮件正文"""
|
||||||
|
body = ""
|
||||||
|
|
||||||
#
|
for part in email_message.walk():
|
||||||
# Find the ReserveResultPojo object from persisted items of DB
|
content_type = part.get_content_type()
|
||||||
#
|
|
||||||
|
if content_type == "text/html":
|
||||||
|
payload = part.get_payload(decode=True)
|
||||||
|
if payload:
|
||||||
|
body += payload.decode("utf-8", errors="ignore")
|
||||||
|
elif content_type == "text/plain":
|
||||||
|
payload = part.get_payload()
|
||||||
|
if payload:
|
||||||
|
body += payload
|
||||||
|
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
# 邮件处理相关函数
|
||||||
def find_item_by_url(url: str, successful_items) -> Union[None, ReserveResultPojo]:
|
def find_item_by_url(url: str, successful_items) -> Union[None, ReserveResultPojo]:
|
||||||
|
"""根据URL查找预约结果对象"""
|
||||||
print("url is :" + url)
|
print("url is :" + url)
|
||||||
parts = url.split('/')
|
parts = url.split('/')
|
||||||
_id = parts[5]
|
_id = parts[5]
|
||||||
|
|
||||||
if len(_id) == 6:
|
if len(_id) == 6:
|
||||||
for item in successful_items:
|
for item in successful_items:
|
||||||
if item.id == _id:
|
if item.id == _id:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def need_to_valid_url(url: str, item: Union[ReserveResultPojo, None]) -> bool:
|
def need_to_valid_url(url: str, item: Union[ReserveResultPojo, None]) -> bool:
|
||||||
|
"""判断是否需要验证URL"""
|
||||||
print("url is :" + url)
|
print("url is :" + url)
|
||||||
parts = url.split('/')
|
parts = url.split('/')
|
||||||
id = parts[5]
|
_id = parts[5]
|
||||||
if len(id) == 6:
|
|
||||||
|
if len(_id) == 6:
|
||||||
if item:
|
if item:
|
||||||
if item.url_validated is not None:
|
if item.url_validated is not None:
|
||||||
return not item.url_validated
|
return not item.url_validated
|
||||||
else:
|
else:
|
||||||
# if url_validated is None
|
# 如果url_validated为None,需要验证
|
||||||
return True
|
return True
|
||||||
return True
|
return True
|
||||||
else:
|
|
||||||
print("id not valid:{}".format(id))
|
print("id not valid:{}".format(_id))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def need_to_check_email(mail: str, successful_items) -> bool:
|
def need_to_check_email(mail: str, successful_items) -> bool:
|
||||||
|
"""判断是否需要检查邮件"""
|
||||||
print("successful_items size is " + str(len(successful_items)))
|
print("successful_items size is " + str(len(successful_items)))
|
||||||
if mail =="saigecong1990@pissmail.com":
|
|
||||||
return True
|
# 特殊处理
|
||||||
filtered_items = list(filter(lambda item: item.email == mail, successful_items))
|
if mail == "saigecong1990@pissmail.com":
|
||||||
# has validated value
|
|
||||||
if len(filtered_items) > 0:
|
|
||||||
validated_items = list(filter(
|
|
||||||
lambda filtered_item: filtered_item.url_validated is not None and filtered_item.url_validated is True,
|
|
||||||
filtered_items))
|
|
||||||
if len(validated_items) > 0:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# 过滤已验证的项目
|
||||||
|
filtered_items = [item for item in successful_items if item.email == mail]
|
||||||
|
|
||||||
def find_links_to_validate_from_mail_list(mail_list: list, logger):
|
# 检查是否有已验证的项目
|
||||||
|
validated_items = [item for item in filtered_items
|
||||||
|
if item.url_validated is not None and item.url_validated is True]
|
||||||
|
|
||||||
|
return len(validated_items) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def find_links_to_validate_from_mail_list(mail_list: List[MailAddress], logger) -> None:
|
||||||
|
"""从邮件列表中查找需要验证的链接"""
|
||||||
if not mail_list:
|
if not mail_list:
|
||||||
return
|
return
|
||||||
# check time before start checking emails
|
|
||||||
|
# 检查时间前开始检查邮件
|
||||||
contact_to_book_list = MONGO_STORE_MANAGER.get_all_contact_to_book_list()
|
contact_to_book_list = MONGO_STORE_MANAGER.get_all_contact_to_book_list()
|
||||||
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
||||||
|
|
||||||
mails_messages = []
|
mails_messages = []
|
||||||
with ThreadPoolExecutor(max_workers=200) as executor:
|
|
||||||
|
# 使用线程池处理邮件
|
||||||
|
with ThreadPoolExecutor(max_workers=100) as executor:
|
||||||
|
futures = []
|
||||||
|
|
||||||
for mail in mail_list:
|
for mail in mail_list:
|
||||||
# check whether we need to read mail
|
# 检查是否需要读取邮件
|
||||||
if need_to_check_email(mail.mail, successful_items):
|
if need_to_check_email(mail.mail, successful_items):
|
||||||
mail_reader = MailReader(mail.mail, mail.password)
|
mail_reader = MailReader(mail.mail, mail.password)
|
||||||
executor.submit(mail_reader.read_emails, mails_messages)
|
future = executor.submit(mail_reader.read_emails, mails_messages)
|
||||||
|
futures.append(future)
|
||||||
|
|
||||||
|
# 等待所有任务完成
|
||||||
|
for future in futures:
|
||||||
|
try:
|
||||||
|
future.result()
|
||||||
|
except Exception as e:
|
||||||
|
print("Error processing mail: {}".format(e))
|
||||||
|
|
||||||
|
# 刷新成功的项目
|
||||||
_refreshed_successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
_refreshed_successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
||||||
|
|
||||||
|
# 处理邮件中的链接
|
||||||
for mail in mails_messages:
|
for mail in mails_messages:
|
||||||
match = re.search(VALIDATION_URL_REGEX, mail.body)
|
match = re.search(VALIDATION_URL_REGEX, mail.body)
|
||||||
if match:
|
if match:
|
||||||
url = match.group(0)
|
url = match.group(0)
|
||||||
_item = find_item_by_url(url, _refreshed_successful_items)
|
_item = find_item_by_url(url, _refreshed_successful_items)
|
||||||
|
|
||||||
if need_to_valid_url(url, _item):
|
if need_to_valid_url(url, _item):
|
||||||
logger.info("need to validate url: " + url)
|
logger.info("need to validate url: " + url)
|
||||||
_model = ""
|
_model = ""
|
||||||
|
_used_ip = ""
|
||||||
if _item:
|
if _item:
|
||||||
_model = _item.model
|
_model = _item.model
|
||||||
MONGO_STORE_MANAGER.save_links_to_validate(url, mail.to_address, model=_model,
|
_used_ip = _item.current_ip
|
||||||
_all_contact_list=contact_to_book_list)
|
|
||||||
|
MONGO_STORE_MANAGER.save_links_to_validate(
|
||||||
|
url,
|
||||||
|
mail.to_address,
|
||||||
|
model=_model,
|
||||||
|
_all_contact_list=contact_to_book_list, _used_ip= _used_ip)
|
||||||
else:
|
else:
|
||||||
logger.info("do not need to click url --> {}".format(mail.mail_address))
|
logger.info("do not need to click url --> {}".format(mail.mail_address))
|
||||||
|
|
||||||
|
|
||||||
|
# 主函数
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# mail_address1 = MailAddress(mail="tinagonzales685585@aol.com", password="yhihvdkrbxnksema")
|
# 读取联系人列表
|
||||||
# mail_list = [mail_address1]
|
|
||||||
contact_to_book_list = read_contacts(
|
contact_to_book_list = read_contacts(
|
||||||
# file_name="/Users/rdv/Desktop/contact_list_not_used_contacts.xlsx")
|
file_name="~/Desktop/contact_list_2025-11-28.xlsx")
|
||||||
# file_name="/Users/lpan/Desktop/contact_list_not_used_contacts.xlsx")
|
# file_name="~/Desktop/contact_list_all.xlsx")
|
||||||
# file_name="/Users/rdv/Desktop/real_name_contacts_100_hotmail.xlsx")
|
# file_name="~/Desktop/contact_list_2025-11-06.xlsx")
|
||||||
# file_name="~/Desktop/contact_list_2025-07-11.xlsx")
|
|
||||||
file_name="~/Desktop/contact_list_all_studio.xlsx")
|
# 获取目标邮箱列表
|
||||||
# file_name="/Users/rdv/Desktop/contact_list_all_studo_gmx_us.xlsx")
|
|
||||||
# file_name="/Users/rdv/Desktop/contact_list_2025-05-24.xlsx")
|
|
||||||
all_mail_list = MONGO_STORE_MANAGER.get_destination_emails()
|
all_mail_list = MONGO_STORE_MANAGER.get_destination_emails()
|
||||||
|
|
||||||
|
# 筛选需要检查的邮件列表
|
||||||
mail_list_to_check = []
|
mail_list_to_check = []
|
||||||
for contact in contact_to_book_list:
|
for contact in contact_to_book_list:
|
||||||
for mail in all_mail_list:
|
for mail in all_mail_list:
|
||||||
if contact.mail == mail.mail:
|
if contact.mail == mail.mail:
|
||||||
mail_list_to_check.append(mail)
|
mail_list_to_check.append(mail)
|
||||||
|
|
||||||
|
# 设置日志记录器
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
# 获取已验证的链接列表
|
||||||
_all_links = MONGO_STORE_MANAGER.get_links_to_validate()
|
_all_links = MONGO_STORE_MANAGER.get_links_to_validate()
|
||||||
|
|
||||||
|
# 过滤掉已处理的邮件
|
||||||
filter_mail = []
|
filter_mail = []
|
||||||
for mail_pojo in mail_list_to_check:
|
for mail_pojo in mail_list_to_check:
|
||||||
_to_add = True
|
_to_add = True
|
||||||
@@ -317,6 +440,6 @@ if __name__ == '__main__':
|
|||||||
_to_add = False
|
_to_add = False
|
||||||
if _to_add:
|
if _to_add:
|
||||||
filter_mail.append(mail_pojo)
|
filter_mail.append(mail_pojo)
|
||||||
filter_mail.append(MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@"))
|
# filter_mail = [MailAddress("utatapi@gmx.net", "RSAzHAFek8s")]
|
||||||
# filter_mail = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
|
# 处理邮件
|
||||||
find_links_to_validate_from_mail_list(filter_mail, logger)
|
find_links_to_validate_from_mail_list(filter_mail, logger)
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ from queue_message.CookiesPublisher import MORNING_DATA_CACHE_2, MORNING_DATA_CA
|
|||||||
from workers.MessagerTransporter import migrate_message_to_queue
|
from workers.MessagerTransporter import migrate_message_to_queue
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# p1 = Process(target=migrate_message_to_queue, args=(MORNING_DATA_CACHE_2, MORNING_DATA_CACHE_BAK))
|
p1 = Process(target=migrate_message_to_queue, args=(MORNING_DATA_CACHE_2, MORNING_DATA_CACHE_BAK))
|
||||||
# p1.start()
|
p1.start()
|
||||||
p2 = Process(target=migrate_message_to_queue, args=(MORNING_DATA_CACHE, MORNING_DATA_CACHE_BAK))
|
p2 = Process(target=migrate_message_to_queue, args=(MORNING_DATA_CACHE, MORNING_DATA_CACHE_BAK))
|
||||||
p2.start()
|
p2.start()
|
||||||
# p2.join()
|
p2.join()
|
||||||
# migrate_message_to_queue(from_queue=MORNING_DATA_CACHE_2)
|
# migrate_message_to_queue(from_queue=MORNING_DATA_CACHE_2)
|
||||||
# migrate_message_to_queue(from_queue=MORNING_DATA_CACHE)
|
# migrate_message_to_queue(from_queue=MORNING_DATA_CACHE)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class PublishType(Enum):
|
|||||||
@dataclass_json
|
@dataclass_json
|
||||||
@dataclass
|
@dataclass
|
||||||
class ReserveResultPojo:
|
class ReserveResultPojo:
|
||||||
type: PublishType = PublishType.ERROR
|
|
||||||
phone: str = ""
|
phone: str = ""
|
||||||
message: str = ""
|
message: str = ""
|
||||||
url: str = ""
|
url: str = ""
|
||||||
@@ -38,14 +37,10 @@ class ReserveResultPojo:
|
|||||||
proxy: str = None
|
proxy: str = None
|
||||||
ua: str = None
|
ua: str = None
|
||||||
current_ip: str = ""
|
current_ip: str = ""
|
||||||
|
timestampInS: list = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_firestore_dict(source):
|
def from_firestore_dict(source):
|
||||||
publish_type = PublishType.ERROR
|
|
||||||
if 'type' in source:
|
|
||||||
publish_type = source['type']
|
|
||||||
if publish_type:
|
|
||||||
publish_type = PublishType[publish_type]
|
|
||||||
if 'phone' in source:
|
if 'phone' in source:
|
||||||
phone = source['phone']
|
phone = source['phone']
|
||||||
else:
|
else:
|
||||||
@@ -54,8 +49,6 @@ class ReserveResultPojo:
|
|||||||
url = source['url']
|
url = source['url']
|
||||||
else:
|
else:
|
||||||
url = ""
|
url = ""
|
||||||
if 'id' in source:
|
|
||||||
id = source['id']
|
|
||||||
if '_id' in source:
|
if '_id' in source:
|
||||||
id = source['_id']
|
id = source['_id']
|
||||||
else:
|
else:
|
||||||
@@ -74,7 +67,7 @@ class ReserveResultPojo:
|
|||||||
else:
|
else:
|
||||||
firstName = ""
|
firstName = ""
|
||||||
|
|
||||||
result = ReserveResultPojo(type=publish_type, phone=phone,
|
result = ReserveResultPojo(phone=phone,
|
||||||
url=url, email=email,
|
url=url, email=email,
|
||||||
firstName=firstName, lastName=lastName)
|
firstName=firstName, lastName=lastName)
|
||||||
if 'accepted' in source:
|
if 'accepted' in source:
|
||||||
@@ -113,12 +106,14 @@ class ReserveResultPojo:
|
|||||||
if 'validated_at' in source:
|
if 'validated_at' in source:
|
||||||
validated_at = source['validated_at']
|
validated_at = source['validated_at']
|
||||||
result.validated_at = validated_at
|
result.validated_at = validated_at
|
||||||
|
if 'current_ip' in source:
|
||||||
|
current_ip = source['current_ip']
|
||||||
|
result.current_ip = current_ip
|
||||||
result.id = id
|
result.id = id
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def to_firestore_dict(self):
|
def to_firestore_dict(self):
|
||||||
dest = {
|
dest = {
|
||||||
u'type': self.type.value,
|
|
||||||
u'id': self.id,
|
u'id': self.id,
|
||||||
u'phone': self.phone,
|
u'phone': self.phone,
|
||||||
u'firstName': self.firstName,
|
u'firstName': self.firstName,
|
||||||
@@ -135,6 +130,7 @@ class ReserveResultPojo:
|
|||||||
u'url_validated': self.url_validated,
|
u'url_validated': self.url_validated,
|
||||||
u'proxy': self.proxy,
|
u'proxy': self.proxy,
|
||||||
u'current_ip': self.current_ip,
|
u'current_ip': self.current_ip,
|
||||||
|
u'timestamp_in_s': "-".join(str(x) for x in self.timestampInS),
|
||||||
u'ua': self.ua,
|
u'ua': self.ua,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
|
import random
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from captcha.jspl_encoder_wrapper import encrpte_to_jspl
|
||||||
from models.jsdata_pojo import JsDataPojo
|
from models.jsdata_pojo import JsDataPojo
|
||||||
|
|
||||||
|
|
||||||
@@ -21,9 +23,29 @@ from models.jsdata_pojo import JsDataPojo
|
|||||||
class JsDataLeTypePojo(JsDataPojo):
|
class JsDataLeTypePojo(JsDataPojo):
|
||||||
|
|
||||||
def __init__(self, glrd, glvd, hc, br_oh, ua, br_ow, br_h, br_w, rs_h, rs_w, rs_cd, ars_h, ars_w, plg, eva, plu,
|
def __init__(self, glrd, glvd, hc, br_oh, ua, br_ow, br_h, br_w, rs_h, rs_w, rs_cd, ars_h, ars_w, plg, eva, plu,
|
||||||
vnd, pr, ts_mtp, dvm, m_s_c, m_m_c, m_c_c, m_cm_r, m_ms_r, emd: str):
|
vnd, pr, ts_mtp, dvm, m_s_c, m_m_c, m_c_c, m_cm_r, m_ms_r, emd: str, ccsB,
|
||||||
|
br_iw=513, br_ih=847, pf="Linux armv81", mob=True,
|
||||||
|
lgs=["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"],
|
||||||
|
orf="debug",
|
||||||
|
bchk="3223aeb6721e0d0917e7928181193ac88dcd62fad5cadfbe7a2b2b473ecf58ee70f098dbdb1a1832e8dc6528387b0745971dbcd82384261e9a4e3f",
|
||||||
|
nt_tcp=0, nt_dns=0, nt_rd=0, nt_irt=-3.400000002235174, nt_rt=0, nt_tls=3.400000002235174,
|
||||||
|
nt_ttf=3.099999997764826, nt_swt=3.400000002235174, nt_csd=0, nt_nhp="", nt_rdc=0, nt_it="navigation",
|
||||||
|
nt_prs=0, nt_esc=-3.400000002235174, nt_ttrd=-2, nt_le=0, nt_dcle=0.10000000149011612,
|
||||||
|
nt_di=74.80000000074506, nt_dc=0, ccsT="""Error
|
||||||
|
at S (https://d.digital.hermes/tags.js:173:22)
|
||||||
|
at Un.C (https://d.digital.hermes/tags.js:1252:41
|
||||||
|
at nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%20pour%20Femme%20_%20Herme%CC%80s%20France.html:7:13468)""",
|
||||||
|
ccsH="1050544242",
|
||||||
|
ccsV=",993b46baf0942a343b7e6b02fa3f8eef64727f077d3b0055af56e6994dcaf046", muev=False, prso=True,
|
||||||
|
nhi=",64,true,Nexus 5,Android,6.0,138.0.7204.184,false", k_lyts=48,
|
||||||
|
k_lytk="kg20va`l§'w8mh.71pdfoqcn[zy365x/\,-4bt9siu=j;r]e", tzp="Europe/Paris", isf2=False):
|
||||||
super().__init__(glrd, glvd, hc, br_oh, ua, br_ow, br_h, br_w, rs_h, rs_w, rs_cd, ars_h, ars_w, plg, eva, plu,
|
super().__init__(glrd, glvd, hc, br_oh, ua, br_ow, br_h, br_w, rs_h, rs_w, rs_cd, ars_h, ars_w, plg, eva, plu,
|
||||||
vnd, pr, ts_mtp, dvm, emd=emd)
|
vnd, pr, ts_mtp, dvm, emd=emd, ccsB=ccsB, br_iw=br_iw, br_ih=br_ih, pf=pf, mob=mob, lgs=lgs,
|
||||||
|
orf=orf, bchk=bchk, nt_tcp=nt_tcp, nt_dns=nt_dns, nt_rd=nt_rd, nt_irt=nt_irt, nt_rt=nt_rt,
|
||||||
|
nt_tls=nt_tls, nt_ttf=nt_ttf, nt_swt=nt_swt, nt_csd=nt_csd, nt_nhp=nt_nhp, nt_rdc=nt_rdc,
|
||||||
|
nt_it=nt_it, nt_prs=nt_prs, nt_esc=nt_esc, nt_ttrd=nt_ttrd, nt_le=nt_le, nt_dcle=nt_dcle,
|
||||||
|
nt_di=nt_di, nt_dc=nt_dc, ccsT=ccsT, ccsH=ccsH, ccsV=ccsV, muev=muev, prso=prso, nhi=nhi,
|
||||||
|
k_lyts=k_lyts, k_lytk=k_lytk, tzp=tzp, isf2=isf2)
|
||||||
self.jset = int(time.time()) # override from 4_34_2
|
self.jset = int(time.time()) # override from 4_34_2
|
||||||
self.emd = emd
|
self.emd = emd
|
||||||
self.dcok = ".hermes.com"
|
self.dcok = ".hermes.com"
|
||||||
@@ -50,14 +72,32 @@ class JsDataLeTypePojo(JsDataPojo):
|
|||||||
self.m_c_c = m_c_c
|
self.m_c_c = m_c_c
|
||||||
self.m_cm_r = m_cm_r
|
self.m_cm_r = m_cm_r
|
||||||
self.m_ms_r = m_ms_r
|
self.m_ms_r = m_ms_r
|
||||||
self.cfpfe = "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3" # 4.40.0
|
self.cfpfe = "KHIsbixvLGEpPT57aWYoZVtyXSllW3JdLnB1c2gobik7ZWxzZXt2YXIgcyxjO2lmKHZvaWQgMCE9PW8pZm9yKHZhciB1PWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKSxkPTA7ZDx1Lmxlbmd0aDtkKyspe3ZhciBsPXVbZF07aWYobC5nZXRB" # 5.1.8
|
||||||
self.stcfp = "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IHQuZXhwb3J0cy5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw" # 4.40.0
|
self.stcfp = "JTIwSGVybWUlQ0MlODBzJTIwRnJhbmNlLmh0bTozNDoyNjY4OSkKYXRvIChmaWxlOi8vL1VzZXJzL3BhbmxlaS9Eb3dubG9hZHMvQnJhY2VsZXQlMjBDbGljJTIwSEglMjAtJTIwTWFycm9uJTIwXyUyMEhlcm1lJUNDJTgwcyUyMEZyYW5jZS5odG06MzQ6MzAzNzgp" # 5.1.8
|
||||||
|
|
||||||
|
|
||||||
test_data_json = """{"glvd":"ARM","glrd":"Mali-G57 MC2","hc":5,"br_oh":620,"br_ow":360,"br_h":620,"br_w":360,"rs_h":804,"rs_w":360,"rs_cd":24,"ars_h":804,"ars_w":360,"plg":2,"eva":33,"vnd":"Google Inc.","plu":["eTJjZUp","iZMOHLs1"],"ua":"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36","dvm":4,"acw":"probably","pr":3,"ts_mtp":5,"tz":-120,"emd":"k:ai,vi,ao,vi d:defau,8f9de,defau,24476 g:4e652,f9991,defau,d5801","cookiesStr":"app.sig=_FqS3_SPN2D40Z4Qlq-_ybxzRvQ;datadome=VSGCNMYkY6L81typRJUpurlyd39dHxdfxIYc6DzRWDT7_rtZ8UodGcbow1okQR2zg_t4d_NcP0rC1ZHNz3XSDAGFZCJhFI49lai~x2Nb2unkhOlY8o4E04Wjmde~auDZ;app=eyJmbGFzaCI6e30sImNhY2hlZmxhc2giOltdLCJjc3JmU2VjcmV0IjoiLW9jbktLVXAzMjVTOEFEdFpLUU9kSXlMIn0=;policy=accepted;lang=fr;"}"""
|
test_data_json = """{"glvd":"Google Inc. (ARM)","glrd":"ANGLE (ARM, Mali-G57 MC2, OpenGL ES 3.2)","hc":8,"br_oh":745,"br_ow":393,
|
||||||
|
"br_h":745,"br_w":393,"rs_h":876,"rs_w":393,"rs_cd":24,"ars_h":876,"ars_w":393,"plg":0,"eva":33,
|
||||||
|
"vnd":"Google Inc.","plu":[],"ua":"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36","dvm":4,"acw":"probably",
|
||||||
|
"pr":2.75,"ts_mtp":5,"tz":-120,"emd":"k:ai,vi,ao",
|
||||||
|
"cookiesStr":"rskxRunCookie=0;datadome=GIfiRxEgyr5dwsnV0NoR9WPO3oA0CkMVLsqdvZLmuxHi81JFRbG7LaWKiAkSQRJTBkv3qBkGlCOC3uR00yZ9XSoCQFyE~1FcumXV8W_bgVPxfNzs6uQcZM8Ec61Q72UT;correlation_id=xlvzlpuwkh6syuqdfze05q7n41qle27qop4yjjvuifzapdo4npjlbi43uwbgle2m;ECOM_SESS=f2c2aihm0ocesmvx3dcs06ysh6;rCookie=0f3nn11uqq28ci5bqnveg5wme4bsr6e;lastRskxRun=1754748244881;x-xsrf-token=7ca984dc-6d35-4720-b77b-465392521d1b;__cf_bm=Szm2hZl9.PTO_DQF5DihrAOTq.dSmSrkKHsTqVenUxo-1754748237-1.0.1.1-gfLAB1wWYyHUb_scXGpXzAk6IkrkhvdNalhhsVhujY7xeFm02lwFKGUiTrBknONdwmvV3EKilTfiFORmJUDrjj3st4hoNdnrk0MT0SVed5w;OptanonConsent=isGpcEnabled=0&datestamp=Sat+Aug+09+2025+16%3A04%3A04+GMT%2B0200+(heure+d%E2%80%99%C3%A9t%C3%A9+d%E2%80%99Europe+centrale)&version=6.32.0&isIABGlobal=false&hosts=&landingPath=https%3A%2F%2Fwww.hermes.com%2Ffr%2Ffr%2Fproduct%2Fsac-p-tit-arcon-H085871CKAO%2F&groups=C0001%3A1%2CC0002%3A0%2CC0003%3A0%2CC0004%3A0;","model":"22041219PG",
|
||||||
|
"lgs":"[fr-FR,fr,en-US,en]",
|
||||||
|
"bchk":"3223aeb6721e0d0917e792818d193ac88dcd62fad5cad7bf7a2b2b473ecf58ee60f018dbdb1a5832e8dc6528387b0745971dbcd82387261e9a4e3f",
|
||||||
|
"nt_tcp":0,"nt_dns":0,"nt_rd":0,"nt_irt":-29.600000008940697,"nt_rt":1129,"nt_tls":6.700000002980232,"nt_ttf":1166.7000000029802,"nt_swt":22.900000005960464,
|
||||||
|
"nt_csd":411060,"nt_nhp":"h2","nt_rdc":0,"nt_it":"navigation","nt_prs":6.700000002980232,"nt_esc":0,"nt_ttrd":null,"nt_le":3.0999999940395355,"nt_dcle":141.79999999701977,
|
||||||
|
"nt_di":1415.2000000029802,"nt_dc":2862.6000000089407,"ccsB":"tags.js:1252:41 at nrWrapper (sac-p-tit-arcon-H085871CKAO.html:7:13468)",
|
||||||
|
"muev":false,"pro_t":false,"nhi":",,true,22041219PG,Android,14.0.0,128.0.6613.146,false","k_lyts":0,"k_lytk":"","serial":"fuljaueqguugf6pn"}"""
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_data_dict = json.loads(test_data_json)
|
test_data_dict = json.loads(test_data_json)
|
||||||
|
m_s_c = random.randint(0, 3)
|
||||||
|
m_c_c = random.randint(3, 5) # click count
|
||||||
|
m_m_c = random.randint(3, 5) # move count
|
||||||
|
m_cm_r = m_c_c / m_m_c
|
||||||
|
m_ms_r = -1 # move scroll ratio
|
||||||
|
if m_s_c == 0:
|
||||||
|
m_ms_r = -1
|
||||||
|
else:
|
||||||
|
m_ms_r = m_m_c / m_s_c
|
||||||
le_js_data = JsDataLeTypePojo(glrd=test_data_dict['glrd'], glvd=test_data_dict['glvd'], hc=test_data_dict['hc'],
|
le_js_data = JsDataLeTypePojo(glrd=test_data_dict['glrd'], glvd=test_data_dict['glvd'], hc=test_data_dict['hc'],
|
||||||
ua=test_data_dict['ua'], br_oh=test_data_dict['br_oh'], br_ow=test_data_dict['br_ow'],
|
ua=test_data_dict['ua'], br_oh=test_data_dict['br_oh'], br_ow=test_data_dict['br_ow'],
|
||||||
ars_h=test_data_dict['ars_h'], ars_w=test_data_dict['ars_w'], pr=test_data_dict['pr'],
|
ars_h=test_data_dict['ars_h'], ars_w=test_data_dict['ars_w'], pr=test_data_dict['pr'],
|
||||||
@@ -65,6 +105,23 @@ if __name__ == '__main__':
|
|||||||
plu=test_data_dict['plu'], vnd=test_data_dict['vnd'], dvm=test_data_dict['dvm'],
|
plu=test_data_dict['plu'], vnd=test_data_dict['vnd'], dvm=test_data_dict['dvm'],
|
||||||
ts_mtp=test_data_dict['ts_mtp'], eva=test_data_dict['eva'],
|
ts_mtp=test_data_dict['ts_mtp'], eva=test_data_dict['eva'],
|
||||||
rs_h=test_data_dict['rs_h'],
|
rs_h=test_data_dict['rs_h'],
|
||||||
rs_w=test_data_dict['rs_w'], rs_cd=test_data_dict['rs_cd'], m_s_c=0, m_m_c=3, m_c_c=3,
|
rs_w=test_data_dict['rs_w'], rs_cd=test_data_dict['rs_cd'],
|
||||||
m_cm_r=1, m_ms_r=-1, emd=test_data_dict['emd'])
|
m_s_c=m_s_c, m_m_c=m_m_c, m_c_c=m_c_c, m_cm_r=m_cm_r, m_ms_r=m_ms_r,
|
||||||
|
emd=test_data_dict['emd'],
|
||||||
|
bchk=test_data_dict['bchk'],
|
||||||
|
ccsB=test_data_dict['ccsB'],
|
||||||
|
nt_tcp=test_data_dict['nt_tcp'],
|
||||||
|
nt_dns=test_data_dict['nt_dns'],
|
||||||
|
nt_rd=test_data_dict['nt_rd'], nt_irt=test_data_dict['nt_irt'],
|
||||||
|
nt_rt=test_data_dict['nt_rt'],
|
||||||
|
nt_tls=test_data_dict['nt_tls'], nt_ttf=test_data_dict['nt_ttf'],
|
||||||
|
nt_swt=test_data_dict['nt_swt'],
|
||||||
|
nt_csd=test_data_dict['nt_csd'], nt_nhp=test_data_dict['nt_nhp'],
|
||||||
|
nt_rdc=test_data_dict['nt_rdc'],
|
||||||
|
nt_it=test_data_dict['nt_it'], nt_prs=test_data_dict['nt_prs'],
|
||||||
|
nt_esc=test_data_dict['nt_esc'],
|
||||||
|
nt_ttrd=test_data_dict['nt_ttrd'], nt_le=test_data_dict['nt_le'],
|
||||||
|
nt_dcle=test_data_dict['nt_dcle'], nt_di=test_data_dict['nt_di'],
|
||||||
|
nt_dc=test_data_dict['nt_dc'])
|
||||||
print(le_js_data.to_url_encoded_json())
|
print(le_js_data.to_url_encoded_json())
|
||||||
|
print(encrpte_to_jspl(le_js_data.to_url_encoded_json()))
|
||||||
|
|||||||
+224
-87
@@ -10,8 +10,19 @@ import jsonpickle
|
|||||||
@dataclass
|
@dataclass
|
||||||
class JsDataPojo:
|
class JsDataPojo:
|
||||||
# opts: str
|
# opts: str
|
||||||
ttst: int
|
r3n: int
|
||||||
ifov: bool
|
exp8: int
|
||||||
|
# uid: str
|
||||||
|
bci: bool
|
||||||
|
bcl: float
|
||||||
|
bct: str
|
||||||
|
bdt: str
|
||||||
|
dp0: bool
|
||||||
|
ucdv: bool
|
||||||
|
wdifrm: bool
|
||||||
|
iwgl: str
|
||||||
|
ttst: float
|
||||||
|
# ifov: bool
|
||||||
hc: int
|
hc: int
|
||||||
br_oh: int
|
br_oh: int
|
||||||
br_ow: int
|
br_ow: int
|
||||||
@@ -19,7 +30,12 @@ class JsDataPojo:
|
|||||||
wbd: bool
|
wbd: bool
|
||||||
tagpu: float
|
tagpu: float
|
||||||
wdif: bool
|
wdif: bool
|
||||||
wdifrm: bool
|
wdifpnh: int
|
||||||
|
lg: str
|
||||||
|
isb: bool
|
||||||
|
idp: bool
|
||||||
|
crt: int
|
||||||
|
|
||||||
npmtm: bool
|
npmtm: bool
|
||||||
br_h: int
|
br_h: int
|
||||||
br_w: int
|
br_w: int
|
||||||
@@ -31,7 +47,6 @@ class JsDataPojo:
|
|||||||
phe: bool
|
phe: bool
|
||||||
nm: bool
|
nm: bool
|
||||||
jsf: bool
|
jsf: bool
|
||||||
lg: str
|
|
||||||
pr: int
|
pr: int
|
||||||
ars_h: int
|
ars_h: int
|
||||||
ars_w: int
|
ars_w: int
|
||||||
@@ -109,7 +124,7 @@ class JsDataPojo:
|
|||||||
wdw: bool
|
wdw: bool
|
||||||
cokys: str
|
cokys: str
|
||||||
ecpc: bool
|
ecpc: bool
|
||||||
lgs: bool
|
lgs: list
|
||||||
lgsod: bool
|
lgsod: bool
|
||||||
psn: bool
|
psn: bool
|
||||||
edp: bool
|
edp: bool
|
||||||
@@ -136,69 +151,151 @@ class JsDataPojo:
|
|||||||
jset: int
|
jset: int
|
||||||
|
|
||||||
def __init__(self, glrd, glvd, hc, br_oh, ua, br_ow, br_h, br_w, rs_h, rs_w, rs_cd, ars_h, ars_w, plg, eva, plu,
|
def __init__(self, glrd, glvd, hc, br_oh, ua, br_ow, br_h, br_w, rs_h, rs_w, rs_cd, ars_h, ars_w, plg, eva, plu,
|
||||||
vnd, pr, ts_mtp, dvm, emd):
|
vnd, pr, ts_mtp, dvm, emd,
|
||||||
|
ccsB,
|
||||||
|
br_iw=513, br_ih=847, pf="Linux armv81", mob=True,
|
||||||
|
lgs=["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"],
|
||||||
|
orf="debug",
|
||||||
|
bchk="3223aeb6721e0d0917e7928181193ac88dcd62fad5cadfbe7a2b2b473ecf58ee70f098dbdb1a1832e8dc6528387b0745971dbcd82384261e9a4e3f",
|
||||||
|
nt_tcp=0, nt_dns=0, nt_rd=0, nt_irt=-3.400000002235174, nt_rt=0, nt_tls=3.400000002235174,
|
||||||
|
nt_ttf=3.099999997764826, nt_swt=3.400000002235174, nt_csd=0, nt_nhp="", nt_rdc=0, nt_it="navigation",
|
||||||
|
nt_prs=0, nt_esc=-3.400000002235174, nt_ttrd=-2, nt_le=0, nt_dcle=0.10000000149011612,
|
||||||
|
nt_di=74.80000000074506, nt_dc=0, ccsT="""Error
|
||||||
|
at S (https://d.digital.hermes/tags.js:173:22)
|
||||||
|
at Un.C (https://d.digital.hermes/tags.js:1252:41
|
||||||
|
at nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%20pour%20Femme%20_%20Herme%CC%80s%20France.html:7:13468)""",
|
||||||
|
ccsH="1050544242",
|
||||||
|
ccsV=",993b46baf0942a343b7e6b02fa3f8eef64727f077d3b0055af56e6994dcaf046", muev=False, prso=True,
|
||||||
|
nhi=",64,true,Nexus 5,Android,6.0,138.0.7204.184,false", k_lyts=48,
|
||||||
|
k_lytk="kg20va`l§'w8mh.71pdfoqcn[zy365x/\,-4bt9siu=j;r]e", tzp="Europe/Paris", isf2=False
|
||||||
|
):
|
||||||
# self.opts = "endpoint,ajaxListenerPath"
|
# self.opts = "endpoint,ajaxListenerPath"
|
||||||
self.ttst = (random.randint(5, 46) * 10 ** 16 + random.randint(1 * 10 ** 7, 9 * 10 ** 7)) / 10 ** 16
|
self.nddc = 1
|
||||||
self.ifov = False
|
self.r3n = 33
|
||||||
|
self.exp8 = 0
|
||||||
|
self.uid = None
|
||||||
|
self.bci = True # batteryManager.charging
|
||||||
|
self.bcl = 0.8 # batteryManager.level
|
||||||
|
self.bct = "Infinity" # batteryManager.chargingTime #to check
|
||||||
|
self.bdt = "Infinity" # batteryManager.chargingTime #to check
|
||||||
|
self.dp0 = False
|
||||||
|
self.ucdv = False
|
||||||
|
self.wdifrm = False
|
||||||
|
self.iwgl = "undefined" # to check
|
||||||
|
self.npmtm = False
|
||||||
|
self.wdif = False
|
||||||
|
self.wdifpnh = 2800984568
|
||||||
|
self.lg = "fr-FR"
|
||||||
|
self.isb = False # is brave
|
||||||
|
self.idp = True
|
||||||
|
self.crt = 0
|
||||||
|
self.vnd = vnd
|
||||||
|
self.bid = "NA"
|
||||||
|
self.med = "defined"
|
||||||
|
self.pltod = False
|
||||||
|
self.csssp = ""
|
||||||
|
self.awe = False
|
||||||
|
self.phe = False
|
||||||
|
self.dat = False
|
||||||
|
self.nm = False
|
||||||
|
self.geb = False
|
||||||
|
self.sqt = False
|
||||||
|
self.pf = pf
|
||||||
self.hc = hc
|
self.hc = hc
|
||||||
self.br_oh = br_oh
|
self.br_oh = br_oh
|
||||||
self.br_ow = br_ow
|
self.br_ow = br_ow
|
||||||
self.ua = ua
|
self.ua = ua
|
||||||
self.wbd = False
|
self.wbd = False
|
||||||
tag_pu = random.uniform(1, 10)
|
self.ts_mtp = ts_mtp
|
||||||
while len(str(tag_pu)) != 17:
|
self.mob = mob
|
||||||
tag_pu = random.uniform(1, 10)
|
self.lgs = lgs
|
||||||
self.tagpu = tag_pu
|
self.dvm = dvm
|
||||||
self.wdif = False
|
self.hcovdr = False
|
||||||
self.wdifrm = False
|
self.plovdr = False
|
||||||
self.npmtm = False
|
self.ftsovdr = False
|
||||||
self.br_h = br_h
|
self.orf = orf # to check
|
||||||
|
self.ttst = round(random.random(), 16)
|
||||||
self.br_w = br_w
|
self.br_w = br_w
|
||||||
self.isf = True
|
self.br_h = br_h
|
||||||
self.nddc = 1
|
self.br_iw = br_iw
|
||||||
self.rs_h = rs_h
|
self.br_ih = br_ih
|
||||||
self.rs_w = rs_w
|
|
||||||
self.rs_cd = rs_cd
|
|
||||||
self.phe = False
|
|
||||||
self.nm = False
|
|
||||||
self.jsf = False
|
|
||||||
self.lg = "fr-FR"
|
|
||||||
self.pr = pr
|
|
||||||
self.ars_h = ars_h
|
|
||||||
self.ars_w = ars_w
|
self.ars_w = ars_w
|
||||||
self.tz = -120
|
self.ars_h = ars_h
|
||||||
self.str_ss = True
|
self.rs_w = rs_w
|
||||||
self.str_ls = True
|
self.rs_h = rs_h
|
||||||
self.str_idb = True
|
self.rs_cd = rs_cd
|
||||||
self.str_odb = True
|
self.pr = pr
|
||||||
|
self.so = "portrait-primary"
|
||||||
|
self.vco = ""
|
||||||
|
self.vcots = False
|
||||||
|
self.vch = "probably"
|
||||||
|
self.vchts = True
|
||||||
|
self.vcw = "probably"
|
||||||
|
self.vcwts = True
|
||||||
|
self.vc3 = "maybe"
|
||||||
|
self.vc3ts = False
|
||||||
|
self.vcmp = ""
|
||||||
|
self.vcmpts = False
|
||||||
|
self.vcq = ""
|
||||||
|
self.vcqts = False
|
||||||
|
self.vc1 = "probably"
|
||||||
|
self.vc1ts = True
|
||||||
|
|
||||||
|
self.cssS = "3.93,0.39,12.24,9.75,5.64,10.98,13.46,2.19,6.51"
|
||||||
|
self.css0 = "7, 75, 0"
|
||||||
|
self.css1 = "9.74354, 0.354646, -0.00922698, 0.000685511, 0.203723, -5.61673, -0.755238, 0.0561098, -0.0279023, 0.481607, -10.9534, 0.813777, -0.375565, 6.48243, -147.433, 11.9534"
|
||||||
|
self.cssH = "15px"
|
||||||
|
|
||||||
|
self.plu = str.join(",", plu) if isinstance(plu, list) else plu
|
||||||
self.plgod = False
|
self.plgod = False
|
||||||
self.plg = plg
|
self.plg = plg
|
||||||
self.plgne = "err"
|
self.plgne = "NA"
|
||||||
self.plgre = "err"
|
self.plgre = "NA"
|
||||||
self.plgof = "err"
|
self.plgof = "NA"
|
||||||
self.plggt = "err"
|
self.plggt = "NA"
|
||||||
self.pltod = False
|
|
||||||
self.hcovdr = False
|
|
||||||
self.hcovdr2 = False
|
|
||||||
self.plovdr = False
|
|
||||||
self.plovdr2 = False
|
|
||||||
self.ftsovdr = False
|
|
||||||
self.ftsovdr2 = False
|
|
||||||
self.lb = False
|
|
||||||
self.eva = eva
|
|
||||||
self.lo = False
|
|
||||||
self.ts_mtp = ts_mtp
|
|
||||||
self.ts_tec = True
|
|
||||||
self.ts_tsa = True
|
|
||||||
self.vnd = vnd
|
|
||||||
self.bid = "NA"
|
|
||||||
self.mmt = "empty"
|
self.mmt = "empty"
|
||||||
self.plu = str.join(",", plu) if isinstance(plu, list) else plu
|
self.bchk = bchk
|
||||||
self.hdn = False
|
self.nt_tcp = nt_tcp
|
||||||
self.awe = False
|
self.nt_dns = nt_dns
|
||||||
self.geb = False
|
self.nt_rd = nt_rd
|
||||||
self.dat = False
|
self.nt_irt = nt_irt
|
||||||
self.med = "defined"
|
self.nt_rt = nt_rt
|
||||||
|
self.nt_tls = nt_tls
|
||||||
|
self.nt_ttf = nt_ttf
|
||||||
|
self.nt_swt = nt_swt
|
||||||
|
self.nt_csd = nt_csd
|
||||||
|
self.nt_nhp = nt_nhp
|
||||||
|
self.nt_rdc = nt_rdc
|
||||||
|
self.nt_it = nt_it
|
||||||
|
self.nt_prs = nt_prs
|
||||||
|
self.nt_esc = nt_esc
|
||||||
|
self.nt_ttrd = nt_ttrd
|
||||||
|
self.nt_le = nt_le
|
||||||
|
self.nt_dcle = nt_dcle
|
||||||
|
self.nt_di = nt_di
|
||||||
|
self.nt_dc = nt_dc
|
||||||
|
|
||||||
|
self.ccsT = ccsT
|
||||||
|
self.ccsB = ccsB
|
||||||
|
self.ccsH = ccsH
|
||||||
|
self.ccsV = ccsV
|
||||||
|
self.muev = muev
|
||||||
|
self.pro_t = True
|
||||||
|
self.wglo = True
|
||||||
|
self.prso = prso
|
||||||
|
self.wbst = True
|
||||||
|
self.psn = True
|
||||||
|
self.edp = True
|
||||||
|
self.addt = True
|
||||||
|
self.wsdc = True
|
||||||
|
self.ccsr = True
|
||||||
|
self.nuad = True
|
||||||
|
self.bcda = True
|
||||||
|
self.idn = True
|
||||||
|
self.capi = True
|
||||||
|
self.svde = True
|
||||||
|
self.vpbq = True
|
||||||
|
self.mq = "aptr:coarse, ahvr:none" # to check
|
||||||
self.aco = "probably"
|
self.aco = "probably"
|
||||||
self.acots = False
|
self.acots = False
|
||||||
self.acmp = "probably"
|
self.acmp = "probably"
|
||||||
@@ -220,35 +317,58 @@ class JsDataPojo:
|
|||||||
self.acwm = "maybe"
|
self.acwm = "maybe"
|
||||||
self.acwmts = False
|
self.acwmts = False
|
||||||
self.ocpt = False
|
self.ocpt = False
|
||||||
self.vco = ""
|
self.ckwa = False
|
||||||
self.vcots = False
|
self.spwn = False
|
||||||
self.vch = "probably"
|
self.emt = False
|
||||||
self.vchts = True
|
self.bfr = False
|
||||||
self.vcw = "probably"
|
self.tz = -120
|
||||||
self.vcwts = True
|
self.hdn = False
|
||||||
self.vc3 = "maybe"
|
self.xt1 = False # pdfViewerEnabled
|
||||||
self.vc3ts = False
|
self.cdhf = False # window.hasFocus()
|
||||||
self.vcmp = ""
|
self.eva = eva
|
||||||
self.vcmpts = False
|
self.cokys = ",loadTimes,csi,app"
|
||||||
self.vcq = ""
|
self.ecpc = False
|
||||||
self.vcqts = False
|
self.nhi = nhi
|
||||||
self.vc1 = "probably"
|
self.k_lyts = k_lyts
|
||||||
self.vc1ts = True
|
self.k_lytk = k_lytk
|
||||||
self.dvm = dvm
|
|
||||||
self.set_default_values()
|
|
||||||
self.emd = emd
|
self.emd = emd
|
||||||
|
self.wwl = False
|
||||||
self.glvd = glvd
|
self.glvd = glvd
|
||||||
self.glrd = glrd
|
self.glrd = glrd
|
||||||
self.wwl = False
|
self.tzp = tzp
|
||||||
|
self.isf = True
|
||||||
|
self.isf2 = isf2
|
||||||
|
self.dt = False
|
||||||
|
self.fph = 416468867
|
||||||
|
|
||||||
|
# self.ifov = False
|
||||||
|
# tag_pu = random.uniform(1, 10)
|
||||||
|
# while len(str(tag_pu)) != 17:
|
||||||
|
# tag_pu = random.uniform(1, 10)
|
||||||
|
# self.tagpu = tag_pu
|
||||||
|
# self.jsf = False
|
||||||
|
# self.str_ss = True
|
||||||
|
# self.str_ls = True
|
||||||
|
# self.str_idb = True
|
||||||
|
# self.str_odb = True
|
||||||
|
#
|
||||||
|
# # self.hcovdr2 = False
|
||||||
|
# # self.plovdr2 = False
|
||||||
|
# # self.ftsovdr2 = False
|
||||||
|
# self.lb = False
|
||||||
|
# self.lo = False
|
||||||
|
# self.ts_tec = True
|
||||||
|
# self.ts_tsa = True
|
||||||
|
|
||||||
|
# self.set_default_values()
|
||||||
|
|
||||||
self.jset = int(time.time())
|
self.jset = int(time.time())
|
||||||
|
|
||||||
def set_default_values(self):
|
def set_default_values(self):
|
||||||
self.sqt = False
|
self.sqt = False
|
||||||
self.so = "portrait-primary"
|
self.so = "portrait-primary"
|
||||||
self.wdw = True
|
self.wdw = True
|
||||||
self.cokys = "bG9hZFRpbWVzY3NpL="
|
self.lgs = ["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"]
|
||||||
self.ecpc = False
|
|
||||||
self.lgs = True
|
|
||||||
self.lgsod = False
|
self.lgsod = False
|
||||||
self.psn = True
|
self.psn = True
|
||||||
self.edp = False
|
self.edp = False
|
||||||
@@ -262,21 +382,28 @@ class JsDataPojo:
|
|||||||
self.svde = False
|
self.svde = False
|
||||||
self.vpbq = True
|
self.vpbq = True
|
||||||
self.ucdv = False
|
self.ucdv = False
|
||||||
self.spwn = False
|
|
||||||
self.emt = False
|
|
||||||
self.bfr = False
|
|
||||||
self.dbov = False
|
self.dbov = False
|
||||||
self.cfpfe = "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3" # 4.40.0
|
self.cfpfe = "KHIsbixvLGEpPT57aWYoZVtyXSllW3JdLnB1c2gobik7ZWxzZXt2YXIgcyxjO2lmKHZvaWQgMCE9PW8pZm9yKHZhciB1PWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKSxkPTA7ZDx1Lmxlbmd0aDtkKyspe3ZhciBsPXVbZF07aWYobC5nZXRB" # 5.1.8
|
||||||
self.stcfp = "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IHQuZXhwb3J0cy5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw" # 4.40.0
|
self.stcfp = "JTIwSGVybWUlQ0MlODBzJTIwRnJhbmNlLmh0bTozNDoyNjY4OSkKYXRvIChmaWxlOi8vL1VzZXJzL3BhbmxlaS9Eb3dubG9hZHMvQnJhY2VsZXQlMjBDbGljJTIwSEglMjAtJTIwTWFycm9uJTIwXyUyMEhlcm1lJUNDJTgwcyUyMEZyYW5jZS5odG06MzQ6MzAzNzgp" # 5.1.8
|
||||||
self.ckwa = True
|
|
||||||
|
|
||||||
def to_url_encoded_json(self):
|
def to_url_encoded_json(self):
|
||||||
js_str = jsonpickle.encode(self, unpicklable=False).replace(": ", ":").replace(", ", ",")
|
js_str = jsonpickle.encode(self, unpicklable=False).replace(": ", ":").replace(", ", ",")
|
||||||
_safe_string = urllib.parse.quote(js_str)
|
# _safe_string = urllib.parse.quote(js_str)
|
||||||
return _safe_string
|
return js_str
|
||||||
|
|
||||||
|
|
||||||
test_data_json = """{"glvd":"ARM","glrd":"Mali-G57 MC2","hc":5,"br_oh":620,"br_ow":360,"br_h":620,"br_w":360,"rs_h":804,"rs_w":360,"rs_cd":24,"ars_h":804,"ars_w":360,"plg":2,"eva":33,"vnd":"Google Inc.","plu":["eTJjZUp","iZMOHLs1"],"ua":"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36","dvm":4,"acw":"probably","pr":3,"ts_mtp":5,"tz":-120,"emd":"k:ai,vi,ao,vi d:defau,8f9de,defau,24476 g:4e652,f9991,defau,d5801","cookiesStr":"app.sig=_FqS3_SPN2D40Z4Qlq-_ybxzRvQ;datadome=VSGCNMYkY6L81typRJUpurlyd39dHxdfxIYc6DzRWDT7_rtZ8UodGcbow1okQR2zg_t4d_NcP0rC1ZHNz3XSDAGFZCJhFI49lai~x2Nb2unkhOlY8o4E04Wjmde~auDZ;app=eyJmbGFzaCI6e30sImNhY2hlZmxhc2giOltdLCJjc3JmU2VjcmV0IjoiLW9jbktLVXAzMjVTOEFEdFpLUU9kSXlMIn0=;policy=accepted;lang=fr;"}"""
|
test_data_json = """{"glvd":"Google Inc. (ARM)","glrd":"ANGLE (ARM, Mali-G57 MC2, OpenGL ES 3.2)","hc":8,"br_oh":745,"br_ow":393,
|
||||||
|
"br_h":745,"br_w":393,"rs_h":876,"rs_w":393,"rs_cd":24,"ars_h":876,"ars_w":393,"plg":0,"eva":33,
|
||||||
|
"vnd":"Google Inc.","plu":[],"ua":"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36","dvm":4,"acw":"probably",
|
||||||
|
"pr":2.75,"ts_mtp":5,"tz":-120,"emd":"k:ai,vi,ao",
|
||||||
|
"cookiesStr":"rskxRunCookie=0;datadome=GIfiRxEgyr5dwsnV0NoR9WPO3oA0CkMVLsqdvZLmuxHi81JFRbG7LaWKiAkSQRJTBkv3qBkGlCOC3uR00yZ9XSoCQFyE~1FcumXV8W_bgVPxfNzs6uQcZM8Ec61Q72UT;correlation_id=xlvzlpuwkh6syuqdfze05q7n41qle27qop4yjjvuifzapdo4npjlbi43uwbgle2m;ECOM_SESS=f2c2aihm0ocesmvx3dcs06ysh6;rCookie=0f3nn11uqq28ci5bqnveg5wme4bsr6e;lastRskxRun=1754748244881;x-xsrf-token=7ca984dc-6d35-4720-b77b-465392521d1b;__cf_bm=Szm2hZl9.PTO_DQF5DihrAOTq.dSmSrkKHsTqVenUxo-1754748237-1.0.1.1-gfLAB1wWYyHUb_scXGpXzAk6IkrkhvdNalhhsVhujY7xeFm02lwFKGUiTrBknONdwmvV3EKilTfiFORmJUDrjj3st4hoNdnrk0MT0SVed5w;OptanonConsent=isGpcEnabled=0&datestamp=Sat+Aug+09+2025+16%3A04%3A04+GMT%2B0200+(heure+d%E2%80%99%C3%A9t%C3%A9+d%E2%80%99Europe+centrale)&version=6.32.0&isIABGlobal=false&hosts=&landingPath=https%3A%2F%2Fwww.hermes.com%2Ffr%2Ffr%2Fproduct%2Fsac-p-tit-arcon-H085871CKAO%2F&groups=C0001%3A1%2CC0002%3A0%2CC0003%3A0%2CC0004%3A0;","model":"22041219PG",
|
||||||
|
"lgs":"[fr-FR,fr,en-US,en]",
|
||||||
|
"bchk":"3223aeb6721e0d0917e792818d193ac88dcd62fad5cad7bf7a2b2b473ecf58ee60f018dbdb1a5832e8dc6528387b0745971dbcd82387261e9a4e3f",
|
||||||
|
"nt_tcp":0,"nt_dns":0,"nt_rd":0,"nt_irt":-29.600000008940697,"nt_rt":1129,"nt_tls":6.700000002980232,"nt_ttf":1166.7000000029802,"nt_swt":22.900000005960464,
|
||||||
|
"nt_csd":411060,"nt_nhp":"h2","nt_rdc":0,"nt_it":"navigation","nt_prs":6.700000002980232,"nt_esc":0,"nt_ttrd":null,"nt_le":3.0999999940395355,"nt_dcle":141.79999999701977,
|
||||||
|
"nt_di":1415.2000000029802,"nt_dc":2862.6000000089407,"ccsB":"tags.js:1252:41 at nrWrapper (sac-p-tit-arcon-H085871CKAO.html:7:13468)",
|
||||||
|
"muev":false,"pro_t":false,"nhi":",,true,22041219PG,Android,14.0.0,128.0.6613.146,false","k_lyts":0,"k_lytk":"","serial":"fuljaueqguugf6pn"}"""
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_data_dict = json.loads(test_data_json)
|
test_data_dict = json.loads(test_data_json)
|
||||||
@@ -286,7 +413,17 @@ if __name__ == '__main__':
|
|||||||
plg=test_data_dict['plg'], br_h=test_data_dict['br_h'], br_w=test_data_dict['br_w'],
|
plg=test_data_dict['plg'], br_h=test_data_dict['br_h'], br_w=test_data_dict['br_w'],
|
||||||
plu=test_data_dict['plu'], vnd=test_data_dict['vnd'], dvm=test_data_dict['dvm'],
|
plu=test_data_dict['plu'], vnd=test_data_dict['vnd'], dvm=test_data_dict['dvm'],
|
||||||
ts_mtp=test_data_dict['ts_mtp'], eva=test_data_dict['eva'], rs_h=test_data_dict['rs_h'],
|
ts_mtp=test_data_dict['ts_mtp'], eva=test_data_dict['eva'], rs_h=test_data_dict['rs_h'],
|
||||||
rs_w=test_data_dict['rs_w'], rs_cd=test_data_dict['rs_cd'], emd=test_data_dict['emd'])
|
rs_w=test_data_dict['rs_w'], rs_cd=test_data_dict['rs_cd'], emd=test_data_dict['emd'],
|
||||||
|
bchk=test_data_dict['bchk'],
|
||||||
|
ccsB=test_data_dict['ccsB'],
|
||||||
|
nt_tcp=test_data_dict['nt_tcp'],
|
||||||
|
nt_dns=test_data_dict['nt_dns'],
|
||||||
|
nt_rd=test_data_dict['nt_rd'], nt_irt=test_data_dict['nt_irt'], nt_rt=test_data_dict['nt_rt'],
|
||||||
|
nt_tls=test_data_dict['nt_tls'], nt_ttf=test_data_dict['nt_ttf'], nt_swt=test_data_dict['nt_swt'],
|
||||||
|
nt_csd=test_data_dict['nt_csd'], nt_nhp=test_data_dict['nt_nhp'], nt_rdc=test_data_dict['nt_rdc'],
|
||||||
|
nt_it=test_data_dict['nt_it'], nt_prs=test_data_dict['nt_prs'], nt_esc=test_data_dict['nt_esc'],
|
||||||
|
nt_ttrd=test_data_dict['nt_ttrd'], nt_le=test_data_dict['nt_le'],
|
||||||
|
nt_dcle=test_data_dict['nt_dcle'], nt_di=test_data_dict['nt_di'], nt_dc=test_data_dict['nt_dc'] )
|
||||||
print(js.to_url_encoded_json())
|
print(js.to_url_encoded_json())
|
||||||
# text_file = open("jsdata.txt", "w")
|
# text_file = open("jsdata.txt", "w")
|
||||||
# # write string to file
|
# # write string to file
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
import datetime
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
from threading import Thread
|
|
||||||
|
|
||||||
from db.mongo_manager import MONGO_STORE_MANAGER
|
|
||||||
from excel_reader import read_contacts
|
|
||||||
from models.contact_pojo import ContactPojo
|
|
||||||
from queue_message.CookiesPublisher import CookiesPublisher, SHARED_OBJECT, TEST_QUEUE
|
|
||||||
from queue_message.appointmentrequestsender import AppointmentRequestSender
|
|
||||||
from queue_message.parallel_requestsender import ParallelRequestSender
|
|
||||||
from utiles import is_time_between
|
|
||||||
from utils.AppLogging import init_logger
|
|
||||||
from workers.proxies_constants import MOBILE_PROXY_LIST_FR
|
|
||||||
|
|
||||||
IPFIY = 'http://api.ipify.org'
|
|
||||||
NGROK_TEST = "https://bcc6-193-164-156-53.ngrok-free.app"
|
|
||||||
|
|
||||||
|
|
||||||
def is_already_sent(contact: ContactPojo) -> bool:
|
|
||||||
already_sent_contacts = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
|
||||||
for required_contact in already_sent_contacts:
|
|
||||||
if contact.mail == required_contact.email:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def filter_contacts(_contact_list: list) -> list:
|
|
||||||
already_sent_contacts = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
|
||||||
_link_to_validate_list = MONGO_STORE_MANAGER.get_links_to_validate()
|
|
||||||
_contact_list_to_book = []
|
|
||||||
for contact in _contact_list:
|
|
||||||
_to_add = True
|
|
||||||
for booked in already_sent_contacts:
|
|
||||||
if contact.mail == booked.email:
|
|
||||||
_to_add = False
|
|
||||||
# 如果已经收到链接了,就不要再请求
|
|
||||||
for link_to_validate in _link_to_validate_list:
|
|
||||||
if contact.mail == link_to_validate.email:
|
|
||||||
logger.info("{}: link already received".format(contact.mail))
|
|
||||||
_to_add = False
|
|
||||||
if _to_add:
|
|
||||||
_contact_list_to_book.append(contact)
|
|
||||||
|
|
||||||
return _contact_list_to_book
|
|
||||||
|
|
||||||
|
|
||||||
def is_open():
|
|
||||||
return is_time_between(datetime.time(10, 30), datetime.time(19, 00))
|
|
||||||
|
|
||||||
|
|
||||||
count = 0
|
|
||||||
init_logger()
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
logger.addHandler(logging.StreamHandler(stream=sys.stdout))
|
|
||||||
|
|
||||||
|
|
||||||
def send_appointment_request(message_queue_name, _contact_list):
|
|
||||||
global count
|
|
||||||
count = count + 1
|
|
||||||
for _contact in _contact_list:
|
|
||||||
logger.info(_contact)
|
|
||||||
_cookiesPublisher = CookiesPublisher(queue_name=message_queue_name)
|
|
||||||
_cookiesPublisher.set_up_connection()
|
|
||||||
receiver = ParallelRequestSender(sub_contact_list=_contact_list, proxy_to_use_list=MOBILE_PROXY_LIST_FR,
|
|
||||||
queue_name=message_queue_name, just_send=True,
|
|
||||||
cookiesPublisher=_cookiesPublisher, logger=logger)
|
|
||||||
print("count is " + str(count))
|
|
||||||
receiver.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
contacts_file_path = '~/Desktop/31_03_to_test.xlsx'
|
|
||||||
_contact_list = read_contacts(contacts_file_path)[0:20]
|
|
||||||
_contact_list_to_book = filter_contacts(_contact_list)
|
|
||||||
_segment_number = 1
|
|
||||||
logger.info("{} contacts to book".format(len(_contact_list_to_book)))
|
|
||||||
last_thread = None
|
|
||||||
for i in range(0, _segment_number):
|
|
||||||
logger.info("segment is {}".format(i))
|
|
||||||
_step = int(len(_contact_list_to_book) / _segment_number)
|
|
||||||
_sublist = _contact_list_to_book[i * _step:_step * (i + 1)]
|
|
||||||
_thread1 = Thread(target=send_appointment_request, args=(TEST_QUEUE, _sublist))
|
|
||||||
last_thread = _thread1
|
|
||||||
_thread1.start()
|
|
||||||
last_thread.join()
|
|
||||||
@@ -3,6 +3,8 @@ import random
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from utils.iproayl_stick_proxy_list import FR_IPROYAL_STICKY_PROXY_LIST
|
||||||
|
|
||||||
FR_ASOCKS_MOBILE_PROXY = {
|
FR_ASOCKS_MOBILE_PROXY = {
|
||||||
'http': 'http://11797317-mobile-country-FR:nv958134x@190.2.151.110:14046',
|
'http': 'http://11797317-mobile-country-FR:nv958134x@190.2.151.110:14046',
|
||||||
'https': 'http://11797317-mobile-country-FR:nv958134x@190.2.151.110:14046',
|
'https': 'http://11797317-mobile-country-FR:nv958134x@190.2.151.110:14046',
|
||||||
@@ -54,17 +56,15 @@ FR_MOBILE_ANY_IP_ROTATING = {
|
|||||||
'http': 'http://user_6a7f21,type_residential,country_FR:d5c051@portal.anyip.io:1080',
|
'http': 'http://user_6a7f21,type_residential,country_FR:d5c051@portal.anyip.io:1080',
|
||||||
'https': 'http://user_6a7f21,type_residential,country_FR:d5c051@portal.anyip.io:1080',
|
'https': 'http://user_6a7f21,type_residential,country_FR:d5c051@portal.anyip.io:1080',
|
||||||
}
|
}
|
||||||
# 八分之一用data_impulse
|
FR_RES_IP_ROYAL_ROTATING = {
|
||||||
# MOBILE_PROXY_LIST = [FR_PROXY_MOB_OXY_STICKY, FR_PROXY_MOB_OXY_STICKY, FR_PROXY_MOB_OXY_STICKY, FR_PROXY_MOB_OXY_STICKY,
|
'http': 'http://Uv2qfG3PyhT6Wctw:V45HOlzAIssCYssJ_country-fr@geo.iproyal.com:12321',
|
||||||
# FR_PROXY_MOB_OXY_STICKY, FR_MOBILE_ANY_IP_STICKY, FR_MOBILE_ANY_IP_STICKY, FR_MOBILE_ANY_IP_STICKY,
|
'https': 'http://Uv2qfG3PyhT6Wctw:V45HOlzAIssCYssJ_country-fr@geo.iproyal.com:12321',
|
||||||
# FR_MOBILE_ANY_IP_STICKY, FR_MOBILE_ANY_IP_STICKY,
|
}
|
||||||
# FR_PROXY_RES_OXY_STICKY,
|
|
||||||
# FR_PROXY_DATA_IMPULSE_STICKY]
|
|
||||||
|
|
||||||
|
|
||||||
# MOBILE_PROXY_LIST = [FR_MOBILE_ANY_IP_STICKY, FR_PROXY_MOB_OXY_STICKY]
|
# MOBILE_PROXY_LIST = [FR_MOBILE_ANY_IP_STICKY, FR_PROXY_MOB_OXY_STICKY]
|
||||||
# MOBILE_PROXY_LIST = [FR_PROXY_MOB_OXY_STICKY]
|
MOBILE_PROXY_LIST = [FR_PROXY_MOB_OXY_STICKY]
|
||||||
MOBILE_PROXY_LIST = [FR_MOBILE_ANY_IP_STICKY]
|
# MOBILE_PROXY_LIST = [FR_MOBILE_ANY_IP_STICKY]
|
||||||
|
|
||||||
|
|
||||||
class ProxyManager:
|
class ProxyManager:
|
||||||
@@ -75,19 +75,25 @@ class ProxyManager:
|
|||||||
def get_link_validate_proxy(self, links_to_validate: list) -> list:
|
def get_link_validate_proxy(self, links_to_validate: list) -> list:
|
||||||
# return [FR_PROXY_RES_PARIS_OXY]
|
# return [FR_PROXY_RES_PARIS_OXY]
|
||||||
# return [FR_MOBILE_ANY_IP_ROTATING]
|
# return [FR_MOBILE_ANY_IP_ROTATING]
|
||||||
return [FR_PROXY_RES_OXY]
|
return [FR_RES_IP_ROYAL_ROTATING]
|
||||||
# if len(links_to_validate) > 15:
|
|
||||||
# return [FR_PROXY_RES_OXY, FR_PROXY_MOB_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES]
|
|
||||||
# # return [FR_PROXY_RES_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES, FR_ASOCKS_MOBILE_PROXY]
|
|
||||||
# else:
|
|
||||||
#
|
|
||||||
# return [FR_PROXY_RES_OXY, FR_PROXY_MOB_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES]
|
|
||||||
# return [FR_PROXY_RES_OXY]
|
# return [FR_PROXY_RES_OXY]
|
||||||
|
|
||||||
|
def get_random_sticky_iproyal_proxy(self) -> dict:
|
||||||
|
_session_info = random.choice(FR_IPROYAL_STICKY_PROXY_LIST)
|
||||||
|
_proxy_template = {
|
||||||
|
'http': 'http://{}@geo.iproyal.com:12321',
|
||||||
|
'https': 'http://{}@geo.iproyal.com:12321',
|
||||||
|
}
|
||||||
|
_proxy_to_use = {}
|
||||||
|
_proxy_to_use["http"] = _proxy_template["http"].format(_session_info)
|
||||||
|
_proxy_to_use["https"] = _proxy_template["https"].format(_session_info)
|
||||||
|
return _proxy_to_use
|
||||||
|
|
||||||
def get_result_link_proxy(self):
|
def get_result_link_proxy(self):
|
||||||
return [FR_PROXY_RES_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES, FR_ASOCKS_MOBILE_PROXY]
|
return [FR_PROXY_RES_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES, FR_ASOCKS_MOBILE_PROXY]
|
||||||
|
|
||||||
def get_proxy_for_appointment_request(self) -> dict:
|
def get_proxy_for_appointment_request(self) -> dict:
|
||||||
|
# return self.get_random_sticky_iproyal_proxy()
|
||||||
_chosen_proxy = random.choice(MOBILE_PROXY_LIST)
|
_chosen_proxy = random.choice(MOBILE_PROXY_LIST)
|
||||||
if "oxylabs" in _chosen_proxy["http"]:
|
if "oxylabs" in _chosen_proxy["http"]:
|
||||||
self.logger.info("use oxylabs proxy")
|
self.logger.info("use oxylabs proxy")
|
||||||
@@ -108,7 +114,9 @@ class ProxyManager:
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
_logger = logging.getLogger()
|
_logger = logging.getLogger()
|
||||||
_proxy = ProxyManager(logger=_logger)
|
_proxy = ProxyManager(logger=_logger)
|
||||||
_proxise = _proxy.get_proxy_for_appointment_request()
|
# _proxise = _proxy.get_random_sticky_iproyal_proxy()
|
||||||
|
# _proxise = _proxy.get_proxy_for_appointment_request()
|
||||||
|
_proxise = _proxy.get_link_validate_proxy([])[0]
|
||||||
print(_proxise)
|
print(_proxise)
|
||||||
response = requests.get(
|
response = requests.get(
|
||||||
"https://ip.oxylabs.io/location",
|
"https://ip.oxylabs.io/location",
|
||||||
|
|||||||
@@ -37,4 +37,8 @@ class CookiesPublisher:
|
|||||||
))
|
))
|
||||||
|
|
||||||
def message_count(self):
|
def message_count(self):
|
||||||
|
# try:
|
||||||
return self.channel.queue_declare(queue=self.to_queue, durable=True).method.message_count
|
return self.channel.queue_declare(queue=self.to_queue, durable=True).method.message_count
|
||||||
|
# except Exception as error:
|
||||||
|
# print(error)
|
||||||
|
# return 0
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from typing import Optional
|
|||||||
import pika
|
import pika
|
||||||
|
|
||||||
from db.mongo_manager import MONGO_STORE_MANAGER
|
from db.mongo_manager import MONGO_STORE_MANAGER
|
||||||
from mail.lan_mail_helper import check_mail, check_all_need_to_check_emails
|
|
||||||
from mail.mail_reader_all_contacts import find_links_to_validate_from_mail_list
|
from mail.mail_reader_all_contacts import find_links_to_validate_from_mail_list
|
||||||
from models.ReserveResultPojo import ReserveResultPojo
|
from models.ReserveResultPojo import ReserveResultPojo
|
||||||
from models.contact_pojo import ContactPojo
|
from models.contact_pojo import ContactPojo
|
||||||
@@ -67,7 +66,7 @@ def is_open():
|
|||||||
|
|
||||||
def check_ms_mails(_mail_list_filtered):
|
def check_ms_mails(_mail_list_filtered):
|
||||||
print("check_ms_mails() called.")
|
print("check_ms_mails() called.")
|
||||||
check_all_need_to_check_emails()
|
# check_all_need_to_check_emails()
|
||||||
# for _mail in _mail_list_filtered:
|
# for _mail in _mail_list_filtered:
|
||||||
# if "outlook.com" in _mail.mail or "hotmail.com" in _mail.mail:
|
# if "outlook.com" in _mail.mail or "hotmail.com" in _mail.mail:
|
||||||
# check_mail(_mail.mail)
|
# check_mail(_mail.mail)
|
||||||
@@ -131,9 +130,18 @@ class AppointmentRequestSender(threading.Thread):
|
|||||||
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'], pr=_received_dict['pr'],
|
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'], pr=_received_dict['pr'],
|
||||||
plg=_received_dict['plg'], br_h=_received_dict['br_h'], br_w=_received_dict['br_w'],
|
plg=_received_dict['plg'], br_h=_received_dict['br_h'], br_w=_received_dict['br_w'],
|
||||||
plu=_received_dict['plu'], vnd=_received_dict['vnd'], dvm=_received_dict['dvm'],
|
plu=_received_dict['plu'], vnd=_received_dict['vnd'], dvm=_received_dict['dvm'],
|
||||||
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'],
|
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'], rs_h=_received_dict['rs_h'],
|
||||||
rs_h=_received_dict['rs_h'],
|
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'],
|
||||||
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'])
|
bchk=_received_dict['bchk'],
|
||||||
|
ccsB=_received_dict['ccsB'],
|
||||||
|
nt_tcp=_received_dict['nt_tcp'],
|
||||||
|
nt_dns=_received_dict['nt_dns'],
|
||||||
|
nt_rd=_received_dict['nt_rd'], nt_irt=_received_dict['nt_irt'], nt_rt=_received_dict['nt_rt'],
|
||||||
|
nt_tls=_received_dict['nt_tls'], nt_ttf=_received_dict['nt_ttf'], nt_swt=_received_dict['nt_swt'],
|
||||||
|
nt_csd=_received_dict['nt_csd'], nt_nhp=_received_dict['nt_nhp'], nt_rdc=_received_dict['nt_rdc'],
|
||||||
|
nt_it=_received_dict['nt_it'], nt_prs=_received_dict['nt_prs'], nt_esc=_received_dict['nt_esc'],
|
||||||
|
nt_ttrd=_received_dict['nt_ttrd'], nt_le=_received_dict['nt_le'],
|
||||||
|
nt_dcle=_received_dict['nt_dcle'], nt_di=_received_dict['nt_di'], nt_dc=_received_dict['nt_dc'] )
|
||||||
_received_cookies = _received_dict["cookiesStr"]
|
_received_cookies = _received_dict["cookiesStr"]
|
||||||
# remove already sent contacts
|
# remove already sent contacts
|
||||||
self.contact_list = filter_contacts(self.contact_list, self.already_tried_contact_list)
|
self.contact_list = filter_contacts(self.contact_list, self.already_tried_contact_list)
|
||||||
@@ -178,21 +186,25 @@ class AppointmentRequestSender(threading.Thread):
|
|||||||
else:
|
else:
|
||||||
m_ms_r = m_m_c / m_s_c
|
m_ms_r = m_m_c / m_s_c
|
||||||
|
|
||||||
js_le_data = JsDataLeTypePojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'],
|
js_le_data = JsDataLeTypePojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'], hc=_received_dict['hc'],
|
||||||
hc=_received_dict['hc'],
|
ua=_received_dict['ua'], br_oh=_received_dict['br_oh'], br_ow=_received_dict['br_ow'],
|
||||||
ua=_received_dict['ua'], br_oh=_received_dict['br_oh'],
|
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'], pr=_received_dict['pr'],
|
||||||
br_ow=_received_dict['br_ow'],
|
plg=_received_dict['plg'], br_h=_received_dict['br_h'], br_w=_received_dict['br_w'],
|
||||||
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'],
|
plu=_received_dict['plu'], vnd=_received_dict['vnd'], dvm=_received_dict['dvm'],
|
||||||
pr=_received_dict['pr'],
|
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'], rs_h=_received_dict['rs_h'],
|
||||||
plg=_received_dict['plg'], br_h=_received_dict['br_h'],
|
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'],
|
||||||
br_w=_received_dict['br_w'],
|
bchk=_received_dict['bchk'],
|
||||||
plu=_received_dict['plu'], vnd=_received_dict['vnd'],
|
ccsB=_received_dict['ccsB'],
|
||||||
dvm=_received_dict['dvm'],
|
nt_tcp=_received_dict['nt_tcp'],
|
||||||
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'],
|
nt_dns=_received_dict['nt_dns'],
|
||||||
rs_h=_received_dict['rs_h'],
|
nt_rd=_received_dict['nt_rd'], nt_irt=_received_dict['nt_irt'], nt_rt=_received_dict['nt_rt'],
|
||||||
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'],
|
nt_tls=_received_dict['nt_tls'], nt_ttf=_received_dict['nt_ttf'], nt_swt=_received_dict['nt_swt'],
|
||||||
|
nt_csd=_received_dict['nt_csd'], nt_nhp=_received_dict['nt_nhp'], nt_rdc=_received_dict['nt_rdc'],
|
||||||
|
nt_it=_received_dict['nt_it'], nt_prs=_received_dict['nt_prs'], nt_esc=_received_dict['nt_esc'],
|
||||||
|
nt_ttrd=_received_dict['nt_ttrd'], nt_le=_received_dict['nt_le'],
|
||||||
|
nt_dcle=_received_dict['nt_dcle'], nt_di=_received_dict['nt_di'], nt_dc=_received_dict['nt_dc'],
|
||||||
m_s_c=m_s_c, m_m_c=m_m_c, m_c_c=m_c_c,
|
m_s_c=m_s_c, m_m_c=m_m_c, m_c_c=m_c_c,
|
||||||
m_cm_r=m_cm_r, m_ms_r=m_ms_r, emd=_received_dict['emd'])
|
m_cm_r=m_cm_r, m_ms_r=m_ms_r)
|
||||||
time.sleep(random.randint(1, 4))
|
time.sleep(random.randint(1, 4))
|
||||||
_new_le_cookies = captchaResultGetter.get_le_valid_cookie(proxy_to_use=_proxy_to_use,
|
_new_le_cookies = captchaResultGetter.get_le_valid_cookie(proxy_to_use=_proxy_to_use,
|
||||||
js_le_type_data=js_le_data,
|
js_le_type_data=js_le_data,
|
||||||
|
|||||||
@@ -1,221 +0,0 @@
|
|||||||
import datetime
|
|
||||||
import json
|
|
||||||
import random
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
from concurrent.futures.thread import ThreadPoolExecutor
|
|
||||||
|
|
||||||
import pika
|
|
||||||
|
|
||||||
from db.mongo_manager import MONGO_STORE_MANAGER
|
|
||||||
from mail.mail_reader_all_contacts import find_links_to_validate_from_mail_list
|
|
||||||
from models.ReserveResultPojo import ReserveResultPojo
|
|
||||||
from models.contact_pojo import ContactPojo
|
|
||||||
from models.jsdata_le_pojo import JsDataLeTypePojo
|
|
||||||
from models.jsdata_pojo import JsDataPojo
|
|
||||||
from models.result_pojo import RequestResult
|
|
||||||
from queue_message.CookiesPublisher import CookiesPublisher
|
|
||||||
from queue_message.appointmentrequestsender import filter_contacts, is_open
|
|
||||||
from utiles import is_time_between
|
|
||||||
from workers.captcha_result_getter import CaptchaResultGetter, HERMES_REGISTER
|
|
||||||
from workers.sender import Sender
|
|
||||||
|
|
||||||
QUEUE_HOST = "appointment.lpaconsulting.fr"
|
|
||||||
REQUEST_DATA_QUEUE = 'REQUEST_DATA'
|
|
||||||
credentials = pika.PlainCredentials('appointment', 'ZyuhJZ2xEYWhElhpJjy7YEpZGZwNYJz2fHIu')
|
|
||||||
|
|
||||||
|
|
||||||
def is_already_sent(contact: ContactPojo) -> bool:
|
|
||||||
already_sent_contacts = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
|
|
||||||
for required_contact in already_sent_contacts:
|
|
||||||
if contact.mail == required_contact.email:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class ParallelRequestSender(threading.Thread):
|
|
||||||
def __init__(self, sub_contact_list: list, proxy_to_use_list, logger, cookiesPublisher: CookiesPublisher,
|
|
||||||
just_send=False,
|
|
||||||
queue_name=REQUEST_DATA_QUEUE):
|
|
||||||
super().__init__()
|
|
||||||
self.connection = None
|
|
||||||
self.just_send = just_send
|
|
||||||
self.logger = logger
|
|
||||||
self.already_tried_contact_list = []
|
|
||||||
self.cookiesPublisher = cookiesPublisher
|
|
||||||
self.channel = None
|
|
||||||
self.valid_csrf = None
|
|
||||||
self.list_to_retrieve_mails = sub_contact_list
|
|
||||||
self.contact_list = sub_contact_list
|
|
||||||
self.queue_name = queue_name
|
|
||||||
self.proxy_to_use_list = proxy_to_use_list
|
|
||||||
self.already_read_emails = False
|
|
||||||
|
|
||||||
def set_up_connection(self):
|
|
||||||
self.connection = pika.BlockingConnection(
|
|
||||||
pika.ConnectionParameters(host=QUEUE_HOST, port=5672, credentials=credentials))
|
|
||||||
self.channel = self.connection.channel()
|
|
||||||
|
|
||||||
def listen_to_queue(self, callback):
|
|
||||||
self.logger.info("listen to queue {}".format(self.queue_name))
|
|
||||||
self.channel.basic_qos(prefetch_count=1)
|
|
||||||
self.channel.basic_consume(queue=self.queue_name, auto_ack=False, on_message_callback=callback)
|
|
||||||
self.channel.start_consuming()
|
|
||||||
|
|
||||||
def send_request(self, _received_cookies, _received_dict, js_data: JsDataPojo, logger,
|
|
||||||
_contact) -> RequestResult:
|
|
||||||
_proxy_to_use = self.generate_proxy()
|
|
||||||
logger.info("send_request for contact: {}, cookies: {}".format(_contact.mail, _received_cookies))
|
|
||||||
logger.info("proxy to use is {}".format(_proxy_to_use))
|
|
||||||
sender = Sender(_received_cookies, cookiesPublisher=self.cookiesPublisher, received_dict=_received_dict,
|
|
||||||
proxy_to_use=_proxy_to_use, logger=logger)
|
|
||||||
# remove already sent contacts
|
|
||||||
if is_open():
|
|
||||||
captchaResultGetter = CaptchaResultGetter()
|
|
||||||
_new_cookies = captchaResultGetter.get_valid_ch_cookie(sender.proxy_to_use, js_data,
|
|
||||||
old_valid_cookie=_received_cookies)
|
|
||||||
# self.contact_list = filter_contacts(self.contact_list)
|
|
||||||
logger.info(_contact.mail)
|
|
||||||
valid_csrf = captchaResultGetter.get_csrf(
|
|
||||||
proxy_to_use=_proxy_to_use, js_data=js_data,
|
|
||||||
cookie=_new_cookies)
|
|
||||||
if isinstance(valid_csrf, str):
|
|
||||||
if _new_cookies is not None:
|
|
||||||
logger.info("new cookie is " + _new_cookies)
|
|
||||||
# m_s_c = f.scroll
|
|
||||||
m_s_c = random.randint(0, 3)
|
|
||||||
m_c_c = random.randint(3, 5) # click count
|
|
||||||
m_m_c = random.randint(3, 5) # move count
|
|
||||||
m_cm_r = m_c_c / m_m_c
|
|
||||||
m_ms_r = random.randint(-1, 1)
|
|
||||||
|
|
||||||
js_le_data = JsDataLeTypePojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'],
|
|
||||||
hc=_received_dict['hc'],
|
|
||||||
ua=_received_dict['ua'], br_oh=_received_dict['br_oh'],
|
|
||||||
br_ow=_received_dict['br_ow'],
|
|
||||||
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'],
|
|
||||||
pr=_received_dict['pr'],
|
|
||||||
plg=_received_dict['plg'], br_h=_received_dict['br_h'],
|
|
||||||
br_w=_received_dict['br_w'],
|
|
||||||
plu=_received_dict['plu'], vnd=_received_dict['vnd'],
|
|
||||||
dvm=_received_dict['dvm'],
|
|
||||||
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'],
|
|
||||||
rs_h=_received_dict['rs_h'],
|
|
||||||
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'],
|
|
||||||
m_s_c=m_s_c, m_m_c=m_m_c, m_c_c=m_c_c,
|
|
||||||
m_cm_r=m_cm_r, m_ms_r=m_ms_r, emd=_received_dict['emd'])
|
|
||||||
time.sleep(random.randint(1, 4))
|
|
||||||
_new_le_cookies = captchaResultGetter.get_le_valid_cookie(proxy_to_use=_proxy_to_use,
|
|
||||||
js_le_type_data=js_le_data,
|
|
||||||
old_valid_cookie=_new_cookies)
|
|
||||||
if _new_le_cookies is not None:
|
|
||||||
# self.logger.info("new le type cookie is " + _new_le_cookies)
|
|
||||||
sender.cookie_str = _new_le_cookies
|
|
||||||
time.sleep(random.randint(1, 3))
|
|
||||||
self.already_tried_contact_list.append(_contact)
|
|
||||||
can_continue = sender.send_request(HERMES_REGISTER, js_data, _contact, csrf=valid_csrf)
|
|
||||||
if can_continue == RequestResult.SUCCESS:
|
|
||||||
# 让服务器读取成功的约会
|
|
||||||
try:
|
|
||||||
self.logger.info("try to remove success contact from list to retrieve mails")
|
|
||||||
self.list_to_retrieve_mails.remove(_contact)
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.info(
|
|
||||||
"exception while remove success contact from list to retrieve mails")
|
|
||||||
print(e)
|
|
||||||
else:
|
|
||||||
can_continue = RequestResult.COOKIES_ERROR
|
|
||||||
else:
|
|
||||||
can_continue = RequestResult.COOKIES_ERROR
|
|
||||||
if can_continue == RequestResult.BLOCKED:
|
|
||||||
self.logger.info("cannot continue, we are blocked " + str(self.valid_csrf))
|
|
||||||
elif can_continue == RequestResult.PROXY_ERROR:
|
|
||||||
self.logger.info("PROXY_ERROR, will not reset valid_csrf")
|
|
||||||
elif can_continue == RequestResult.COOKIES_ERROR:
|
|
||||||
self.logger.info("COOKIES_ERROR, will not reset valid_csrf")
|
|
||||||
else:
|
|
||||||
self.logger.info("can continue, will reset valid_csrf")
|
|
||||||
self.valid_csrf = None
|
|
||||||
return can_continue
|
|
||||||
else:
|
|
||||||
return valid_csrf
|
|
||||||
# return RequestResult.CTRF_ERROR
|
|
||||||
|
|
||||||
def getChTypeJsDataFromDict(self, _received_dict) -> JsDataPojo:
|
|
||||||
return JsDataPojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'], hc=_received_dict['hc'],
|
|
||||||
ua=_received_dict['ua'], br_oh=_received_dict['br_oh'], br_ow=_received_dict['br_ow'],
|
|
||||||
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'], pr=_received_dict['pr'],
|
|
||||||
plg=_received_dict['plg'], br_h=_received_dict['br_h'], br_w=_received_dict['br_w'],
|
|
||||||
plu=_received_dict['plu'], vnd=_received_dict['vnd'], dvm=_received_dict['dvm'],
|
|
||||||
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'],
|
|
||||||
rs_h=_received_dict['rs_h'],
|
|
||||||
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'])
|
|
||||||
|
|
||||||
def generate_proxy(self):
|
|
||||||
_port = random.randint(40001, 49999)
|
|
||||||
_chosen_proxy = random.choice(self.proxy_to_use_list)
|
|
||||||
self.logger.info("generated port is {}".format(_port))
|
|
||||||
_proxy_to_use = {}
|
|
||||||
_proxy_to_use["http"] = _chosen_proxy["http"].format(_port)
|
|
||||||
_proxy_to_use["https"] = _chosen_proxy["https"].format(_port)
|
|
||||||
return _proxy_to_use
|
|
||||||
|
|
||||||
def on_message(self, ch, method, properties, body):
|
|
||||||
_message_count = self.cookiesPublisher.message_count()
|
|
||||||
self.logger.info("message count in queue is {}".format(_message_count))
|
|
||||||
# prepare the contact list
|
|
||||||
if self.just_send:
|
|
||||||
self.contact_list = filter_contacts(self.contact_list, self.already_tried_contact_list)
|
|
||||||
else:
|
|
||||||
self.contact_list = filter_contacts(self.contact_list)
|
|
||||||
# remove already booked contacts
|
|
||||||
random.shuffle(self.contact_list)
|
|
||||||
_received_object = body.decode("UTF-8")
|
|
||||||
self.logger.info(f" [x] Received {_received_object}")
|
|
||||||
step = 5
|
|
||||||
_received_dict = json.loads(_received_object)
|
|
||||||
js_data = self.getChTypeJsDataFromDict(_received_dict)
|
|
||||||
_received_cookies = _received_dict["cookiesStr"]
|
|
||||||
if len(self.contact_list) > step:
|
|
||||||
_sub_list = self.contact_list[0:step]
|
|
||||||
result = None
|
|
||||||
for con in _sub_list:
|
|
||||||
with ThreadPoolExecutor(max_workers=step) as executor:
|
|
||||||
result = executor.submit(self.send_request, _received_cookies, _received_dict, js_data, self.logger,
|
|
||||||
con)
|
|
||||||
self.logger.info("result is: " + str(result.result()))
|
|
||||||
if result.result() == RequestResult.SUCCESS:
|
|
||||||
self.logger.info("Success for {}, with cookies{}".format(con.mail, _received_cookies))
|
|
||||||
if result.result() == RequestResult.BLOCKED or result.result() == RequestResult.CTRF_ERROR:
|
|
||||||
ch.basic_ack(delivery_tag=method.delivery_tag)
|
|
||||||
|
|
||||||
else:
|
|
||||||
ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)
|
|
||||||
else:
|
|
||||||
self.retrieve_invalidate_urls()
|
|
||||||
self.logger.info("empty list")
|
|
||||||
time.sleep(120)
|
|
||||||
self.logger.info("will basic_reject method.delivery_tag: " + str(method.delivery_tag))
|
|
||||||
ch.basic_reject(delivery_tag=method.delivery_tag, requeue=True)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.logger.info(threading.currentThread().name + " starts")
|
|
||||||
self.set_up_connection()
|
|
||||||
self.listen_to_queue(self.on_message)
|
|
||||||
self.channel.start_consuming()
|
|
||||||
|
|
||||||
def retrieve_invalidate_urls(self):
|
|
||||||
if not self.already_read_emails and len(self.list_to_retrieve_mails) > 0:
|
|
||||||
self.logger.info("will retrieve validate urls")
|
|
||||||
time.sleep(30)
|
|
||||||
_mail_list = MONGO_STORE_MANAGER.get_destination_emails()
|
|
||||||
_mail_list_filtered = []
|
|
||||||
for mail in _mail_list:
|
|
||||||
for _contact in self.list_to_retrieve_mails:
|
|
||||||
if _contact.mail == mail.mail:
|
|
||||||
_mail_list_filtered.append(mail)
|
|
||||||
self.logger.info("will call find_links_to_validate_from_mail_list, size = " + str(len(_mail_list_filtered)))
|
|
||||||
find_links_to_validate_from_mail_list(_mail_list_filtered)
|
|
||||||
self.already_read_emails = True
|
|
||||||
else:
|
|
||||||
self.logger.info("already read emails, will not retrieve validate urls")
|
|
||||||
@@ -99,10 +99,9 @@ def send_request_for_file_list(file_list: list, thread_number: int = 20, data_qu
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# file_list = ['~/Desktop/contact_list_2024-05-23.xlsx',
|
# file_list = ['~/Desktop/contact_list_2024-05-23.xlsx',
|
||||||
# '~/Desktop/contact_list_2024-05-21.xlsx',
|
# '~/Desktop/contact_list_2024-05-21.xlsx',
|
||||||
# '~/Desktop/15_05_to_test.xlsx']
|
# file_list = ['~/Desktop/contact_list_2025-10-30.xlsx']
|
||||||
# file_list = ['~/Desktop/15_05_to_test.xlsx', '~/Desktop/16_05_to_test.xlsx']
|
file_list = ['~/Desktop/contact_list_2025-11-28.xlsx']
|
||||||
file_list = ['~/Desktop/contact_list_2025-07-11.xlsx']
|
# file_list = ['~/Desktop/contact_list_2025-11-06.xlsx']
|
||||||
# file_list = ['~/Desktop/contact_list_all_studio.xlsx']
|
# file_list = ['~/Desktop/contact_list_all.xlsx']
|
||||||
# file_list = ['~/Desktop/real_name_contacts_100_27_06.xlsx']
|
|
||||||
send_request_for_file_list(file_list=file_list, thread_number=20,
|
send_request_for_file_list(file_list=file_list, thread_number=20,
|
||||||
data_queue_name=MORNING_DATA_CACHE, stop_at_hour=19, stop_at_mins=50)
|
data_queue_name=MORNING_DATA_CACHE_2, stop_at_hour=19, stop_at_mins=50)
|
||||||
|
|||||||
+4
-1
@@ -1,2 +1,5 @@
|
|||||||
|
APScheduler==3.10.4
|
||||||
curl_cffi==0.7.1
|
curl_cffi==0.7.1
|
||||||
openpyxl
|
openpyxl
|
||||||
|
pika
|
||||||
|
schedule
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
|
||||||
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||||
|
|
||||||
|
from link_validator_executor import start_link_validation
|
||||||
|
|
||||||
|
|
||||||
|
def start_check_results_job(sched):
|
||||||
|
sched.add_job(start_link_validation, 'cron', day_of_week='mon-sun', hour='14',
|
||||||
|
minute='10',
|
||||||
|
misfire_grace_time=10,
|
||||||
|
second='10', timezone='Europe/Paris', max_instances=1, args=[])
|
||||||
|
|
||||||
|
|
||||||
|
def config_and_start_jobs():
|
||||||
|
executors = {
|
||||||
|
'default': ThreadPoolExecutor(1),
|
||||||
|
'processpool': ProcessPoolExecutor(1)
|
||||||
|
}
|
||||||
|
sched = BlockingScheduler(executors=executors)
|
||||||
|
start_check_results_job(sched)
|
||||||
|
sched.print_jobs()
|
||||||
|
sched.start()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
config_and_start_jobs()
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
|
||||||
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||||
|
|
||||||
|
from queue_message.CookiesPublisher import MORNING_DATA_CACHE
|
||||||
|
from request_sender_test import send_request_for_file_list
|
||||||
|
|
||||||
|
|
||||||
|
def start_book_appointment():
|
||||||
|
file_list = ['~/Desktop/contact_list_2025-10-30.xlsx']
|
||||||
|
send_request_for_file_list(file_list=file_list, thread_number=2,
|
||||||
|
data_queue_name=MORNING_DATA_CACHE, stop_at_hour=18, stop_at_mins=20)
|
||||||
|
|
||||||
|
|
||||||
|
def start_check_results_job(sched):
|
||||||
|
sched.add_job(start_book_appointment, 'cron', day_of_week='mon-sat', hour='11',
|
||||||
|
minute='40',
|
||||||
|
misfire_grace_time=10,
|
||||||
|
second='10', timezone='Europe/Paris', max_instances=1, args=[])
|
||||||
|
|
||||||
|
|
||||||
|
def config_and_start_jobs():
|
||||||
|
executors = {
|
||||||
|
'default': ThreadPoolExecutor(30),
|
||||||
|
'processpool': ProcessPoolExecutor(12)
|
||||||
|
}
|
||||||
|
sched = BlockingScheduler(executors=executors)
|
||||||
|
start_check_results_job(sched)
|
||||||
|
sched.print_jobs()
|
||||||
|
sched.start()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
config_and_start_jobs()
|
||||||
+5
-4
@@ -6,13 +6,14 @@ from request_sender_test import send_request_for_file_list
|
|||||||
|
|
||||||
|
|
||||||
def start_book_appointment():
|
def start_book_appointment():
|
||||||
file_list = ['~/Desktop/contact_list_2025-07-11.xlsx']
|
# file_list = ['~/Desktop/contact_list_2025-09-08.xlsx']
|
||||||
send_request_for_file_list(file_list=file_list, thread_number=60,
|
file_list = ['~/Desktop/contact_list_2025-11-28.xlsx']
|
||||||
data_queue_name=MORNING_DATA_CACHE, stop_at_hour=11, stop_at_mins=20)
|
send_request_for_file_list(file_list=file_list, thread_number=73,
|
||||||
|
data_queue_name=MORNING_DATA_CACHE, stop_at_hour=11, stop_at_mins=10)
|
||||||
|
|
||||||
|
|
||||||
def start_check_results_job(sched):
|
def start_check_results_job(sched):
|
||||||
sched.add_job(start_book_appointment, 'cron', day_of_week='mon-sat', hour='10',
|
sched.add_job(start_book_appointment, 'cron', day_of_week='mon-sun', hour='10',
|
||||||
minute='30',
|
minute='30',
|
||||||
misfire_grace_time=10,
|
misfire_grace_time=10,
|
||||||
second='10', timezone='Europe/Paris', max_instances=1, args=[])
|
second='10', timezone='Europe/Paris', max_instances=1, args=[])
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from db.mongo_manager import MONGO_DB_URL
|
||||||
|
|
||||||
|
# ================= 配置区域 =================
|
||||||
|
# 数据库连接信息
|
||||||
|
MONGO_HOST = "mongo.lpaconsulting.fr"
|
||||||
|
MONGO_PORT = "27017"
|
||||||
|
MONGO_DB_NAME = "appointment" # 你要备份/恢复的数据库名
|
||||||
|
|
||||||
|
# Get MongoDB credentials from environment variables
|
||||||
|
MONGO_USER = os.getenv(
|
||||||
|
"MONGO_USER", "appointment"
|
||||||
|
) # Default to 'appointment' if not set
|
||||||
|
MONGO_PASS = os.getenv("MONGO_PASS", "Rdv@2022") # Default to 'Rdv@2022' if not set
|
||||||
|
|
||||||
|
# 备份存放的根目录
|
||||||
|
BACKUP_DIR_ROOT = "./mongo_backups"
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
|
||||||
|
|
||||||
|
def get_auth_args():
|
||||||
|
"""构建认证参数列表"""
|
||||||
|
args = []
|
||||||
|
if MONGO_USER and MONGO_PASS:
|
||||||
|
args.extend(
|
||||||
|
[
|
||||||
|
"--username",
|
||||||
|
MONGO_USER,
|
||||||
|
"--password",
|
||||||
|
MONGO_PASS,
|
||||||
|
"--authenticationDatabase",
|
||||||
|
"appointment",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def backup_mongo():
|
||||||
|
"""执行备份操作"""
|
||||||
|
# 1. 创建带有时间戳的备份文件夹
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||||
|
backup_path = os.path.join(BACKUP_DIR_ROOT, timestamp)
|
||||||
|
|
||||||
|
if not os.path.exists(backup_path):
|
||||||
|
os.makedirs(backup_path)
|
||||||
|
|
||||||
|
print(f"[*] 开始备份数据库: {MONGO_DB_NAME} 到 {backup_path} ...")
|
||||||
|
|
||||||
|
# 2. 构建 mongodump 命令
|
||||||
|
# 命令格式: mongodump --host <host> --port <port> --db <db> --out <path> [auth]
|
||||||
|
cmd = [
|
||||||
|
"mongodump",
|
||||||
|
"--host",
|
||||||
|
MONGO_HOST,
|
||||||
|
"--port",
|
||||||
|
MONGO_PORT,
|
||||||
|
"--db",
|
||||||
|
MONGO_DB_NAME,
|
||||||
|
"--out",
|
||||||
|
backup_path,
|
||||||
|
]
|
||||||
|
|
||||||
|
# 添加认证参数
|
||||||
|
cmd.extend(get_auth_args())
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 3. 执行命令
|
||||||
|
result = subprocess.run(cmd, check=True, text=True, capture_output=True)
|
||||||
|
print(f"[+] 备份成功!")
|
||||||
|
print(f" 存储路径: {backup_path}")
|
||||||
|
print(f" 日志: {result.stderr}") # mongodump 通常把进度输出到 stderr
|
||||||
|
return backup_path
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"[-] 备份失败: {e}")
|
||||||
|
print(f" 错误信息: {e.stderr}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def restore_mongo(backup_source_path):
|
||||||
|
"""
|
||||||
|
执行恢复操作
|
||||||
|
backup_source_path: 备份文件夹的路径 (例如 ./mongo_backups/2023-10-27_10-00-00)
|
||||||
|
"""
|
||||||
|
# mongodump 的输出结构通常是: backup_dir/db_name/collection.bson
|
||||||
|
# 所以我们需要指向具体的数据库文件夹,或者指向父文件夹并指定 --db
|
||||||
|
|
||||||
|
target_dir = os.path.join(backup_source_path, MONGO_DB_NAME)
|
||||||
|
|
||||||
|
if not os.path.exists(target_dir):
|
||||||
|
print(
|
||||||
|
f"[-] 错误: 在路径 {backup_source_path} 下找不到数据库 {MONGO_DB_NAME} 的备份文件。"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"[*] 开始恢复数据库: {MONGO_DB_NAME} 从 {target_dir} ...")
|
||||||
|
|
||||||
|
# 构建 mongorestore 命令
|
||||||
|
# 命令格式: mongorestore --host <host> --port <port> --db <db> <path_to_bson_files> [auth]
|
||||||
|
cmd = [
|
||||||
|
"mongorestore",
|
||||||
|
"--host",
|
||||||
|
MONGO_HOST,
|
||||||
|
"--port",
|
||||||
|
MONGO_PORT,
|
||||||
|
"--db",
|
||||||
|
MONGO_DB_NAME,
|
||||||
|
"--drop", # 警告:这会在恢复前删除现有集合,确保数据干净。根据需要移除此项。
|
||||||
|
target_dir,
|
||||||
|
]
|
||||||
|
|
||||||
|
cmd.extend(get_auth_args())
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = subprocess.run(cmd, check=True, text=True, capture_output=True)
|
||||||
|
print(f"[+] 恢复成功!")
|
||||||
|
print(f" 日志: {result.stderr}")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"[-] 恢复失败: {e}")
|
||||||
|
print(f" 错误信息: {e.stderr}")
|
||||||
|
|
||||||
|
|
||||||
|
# ================= 主程序入口 =================
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("请选择操作:")
|
||||||
|
print("1. 备份数据库 (Backup)")
|
||||||
|
print("2. 恢复数据库 (Restore)")
|
||||||
|
|
||||||
|
choice = input("请输入数字 (1/2): ").strip()
|
||||||
|
|
||||||
|
if choice == "1":
|
||||||
|
backup_mongo()
|
||||||
|
elif choice == "2":
|
||||||
|
# 列出所有备份供用户选择
|
||||||
|
if not os.path.exists(BACKUP_DIR_ROOT):
|
||||||
|
print("[-] 没有找到备份目录。")
|
||||||
|
else:
|
||||||
|
backups = sorted(os.listdir(BACKUP_DIR_ROOT))
|
||||||
|
if not backups:
|
||||||
|
print("[-] 目录为空。")
|
||||||
|
else:
|
||||||
|
print("\n可用备份:")
|
||||||
|
for idx, name in enumerate(backups):
|
||||||
|
print(f"{idx + 1}. {name}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
idx_choice = int(input("\n请选择要恢复的备份编号: ")) - 1
|
||||||
|
if 0 <= idx_choice < len(backups):
|
||||||
|
selected_backup = os.path.join(
|
||||||
|
BACKUP_DIR_ROOT, backups[idx_choice]
|
||||||
|
)
|
||||||
|
restore_mongo(selected_backup)
|
||||||
|
else:
|
||||||
|
print("[-] 无效的选择。")
|
||||||
|
except ValueError:
|
||||||
|
print("[-] 请输入数字。")
|
||||||
|
else:
|
||||||
|
print("[-] 无效输入,退出。")
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def get_ip_geolocation(ip_address=None):
|
||||||
|
"""
|
||||||
|
使用 FreeIPAPI 查询指定 IP 地址的地理位置信息。
|
||||||
|
如果没有提供 IP 地址,将查询请求本身的公网 IP。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ip_address (str, optional): 要查询的 IP 地址。默认为 None。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含 IP 信息的字典,如果请求失败则返回 None。
|
||||||
|
"""
|
||||||
|
base_url = "https://freeipapi.com/api/json"
|
||||||
|
|
||||||
|
if ip_address:
|
||||||
|
# 如果指定了 IP,则在 URL 中添加 IP
|
||||||
|
url = f"{base_url}/{ip_address}"
|
||||||
|
else:
|
||||||
|
# 如果未指定 IP,则查询发起请求的 IP
|
||||||
|
url = base_url
|
||||||
|
|
||||||
|
print(f"正在查询 IP: {ip_address if ip_address else '当前公网 IP'}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 发送 GET 请求,设置超时时间
|
||||||
|
response = requests.get(url, timeout=10)
|
||||||
|
|
||||||
|
# 检查 HTTP 状态码,如果不是 200 则抛出异常
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# 解析 JSON 响应
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# 检查 API 是否返回了错误信息(FreeIPAPI 在某些情况下会返回 status: 404)
|
||||||
|
if data.get('status') == 404:
|
||||||
|
print(f"查询失败:FreeIPAPI 报告未找到该 IP 地址的信息。")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"请求失败,发生网络错误: {e}")
|
||||||
|
return None
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print("响应解析失败,可能不是有效的 JSON 格式。")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def display_ip_info(data):
|
||||||
|
"""
|
||||||
|
格式化并打印 IP 地址信息。
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
print("无法获取 IP 信息。")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("\n--- IP 地理位置信息 ---")
|
||||||
|
|
||||||
|
# 使用 .get() 方法安全地获取数据,避免 KeyError
|
||||||
|
print(f"IP 地址: {data.get('ipAddress', 'N/A')}")
|
||||||
|
print(f"国家: {data.get('countryName', 'N/A')}")
|
||||||
|
print(f"国家代码: {data.get('countryCode', 'N/A')}")
|
||||||
|
print(f"城市: {data.get('cityName', 'N/A')}")
|
||||||
|
print(f"邮编: {data.get('zipCode', 'N/A')}")
|
||||||
|
print(f"时区: {data.get('timeZone', 'N/A')}")
|
||||||
|
# 经纬度
|
||||||
|
latitude = data.get('latitude', 'N/A')
|
||||||
|
longitude = data.get('longitude', 'N/A')
|
||||||
|
print(f"纬度/经度: {latitude} / {longitude}")
|
||||||
|
print(f"ISP/组织: {data.get('isp', 'N/A')}")
|
||||||
|
print("------------------------")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
主执行函数。可以接受命令行参数作为要查询的 IP 地址。
|
||||||
|
"""
|
||||||
|
# 检查是否有命令行参数传入
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
# 取第一个参数作为要查询的 IP 地址
|
||||||
|
ip_to_query = sys.argv[1]
|
||||||
|
print(f"检测到命令行参数: {ip_to_query}")
|
||||||
|
|
||||||
|
ip_info = get_ip_geolocation(ip_to_query)
|
||||||
|
display_ip_info(ip_info)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# 1. 查询当前公网 IP (不传参数)
|
||||||
|
print("\n--- 示例 1: 查询当前公网 IP ---")
|
||||||
|
my_ip_info = get_ip_geolocation()
|
||||||
|
display_ip_info(my_ip_info)
|
||||||
|
|
||||||
|
# 2. 查询特定 IP 地址 (例如:Google 的 DNS 服务器 8.8.8.8)
|
||||||
|
print("\n--- 示例 2: 查询特定 IP 地址 (8.8.8.8) ---")
|
||||||
|
google_dns_ip = "8.8.8.8"
|
||||||
|
google_ip_info = get_ip_geolocation(google_dns_ip)
|
||||||
|
display_ip_info(google_ip_info)
|
||||||
|
|
||||||
|
|
||||||
|
# 脚本入口点
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ip_info = get_ip_geolocation("80.13.246.205")
|
||||||
|
print(ip_info)
|
||||||
|
display_ip_info(ip_info)
|
||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user