Compare commits

1 Commits

Author SHA1 Message Date
panleicim 8bba5eb2f1 added method to remove message 2024-12-03 18:46:42 +01:00
115 changed files with 1050 additions and 7520 deletions
+1 -3
View File
@@ -3,6 +3,4 @@ __pycache__/
*$py.class *$py.class
.idea .idea
db/__pycache__/* db/__pycache__/*
*.iml *.iml
venv
.env
View File
-445
View File
@@ -1,445 +0,0 @@
// 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);
-189
View File
@@ -1,189 +0,0 @@
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))
+5 -27
View File
@@ -11,7 +11,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://mongo2.lpaconsulting.fr/?timeoutMS=100000" MONGO_DB_URL = "mongodb://mongo.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"
@@ -20,12 +20,11 @@ EMAIL_LIST = "EMAIL_LIST"
DESTINATION_EMAIL_LIST = "DESTINATION_EMAIL_LIST" DESTINATION_EMAIL_LIST = "DESTINATION_EMAIL_LIST"
LINKS_TO_VALIDATE = "LINKS_TO_VALIDATE" LINKS_TO_VALIDATE = "LINKS_TO_VALIDATE"
INVALID_EMAIL_LIST = "INVALID_EMAIL_LIST" INVALID_EMAIL_LIST = "INVALID_EMAIL_LIST"
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@20222021', authSource='appointment') client = MongoClient(MONGO_DB_URL, username='appointment', password='Rdv@2022', authSource='appointment')
self.db = client.appointment self.db = client.appointment
self.logger = logging.getLogger("mongoDb") self.logger = logging.getLogger("mongoDb")
@@ -76,19 +75,10 @@ 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 get_all_contact_serial_list(self) -> list: def save_links_to_validate(self, link: str, mail_address: str, _all_contact_list: list):
result_list = []
cursor = self.db[CONTACT_LIST_SERIAL_MAP]
for document in cursor.find():
result_list.append(ContactPojo.from_firestore_dict(document))
return result_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"
serial = "requests"
# find ip_country info # find ip_country info
for _contact in _all_contact_list: for _contact in _all_contact_list:
if _contact.mail == mail_address: if _contact.mail == mail_address:
@@ -98,20 +88,14 @@ class MongoDbManager:
collection_to_use.replace_one(filter={'_id': mail_address, }, replacement={ collection_to_use.replace_one(filter={'_id': mail_address, }, replacement={
u'url': link, u'url': link,
u'email': mail_address, u'email': mail_address,
u'serial': serial,
u'model': model,
u'ip_country': _ip_country, u'ip_country': _ip_country,
u'_used_ip': _used_ip,
"updated_at": updated_at "updated_at": updated_at
}, },
upsert=True) upsert=True)
else: else:
collection_to_use.replace_one(filter={'_id': link, }, replacement={ collection_to_use.replace_one(filter={'_id': link, }, replacement={
u'url': link, u'url': link,
u'serial': serial,
u'model': model,
u'ip_country': _ip_country, u'ip_country': _ip_country,
u'_used_ip': _used_ip,
"updated_at": updated_at "updated_at": updated_at
}, },
upsert=True) upsert=True)
@@ -168,9 +152,7 @@ class MongoDbManager:
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(self, link: str, linkPojo: LinkPojo, state=True, is_duplicated=False,
is_invalid=False, segement_position=1, ua="", model="", timestamp_in_s: list = None): is_invalid=False, segement_position=1, ua=""):
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]
@@ -192,11 +174,7 @@ class MongoDbManager:
validated_by = "Double" validated_by = "Double"
collection.find_one_and_update({'_id': _id}, { collection.find_one_and_update({'_id': _id}, {
"$set": {"url_validated": state, "validated_at": validated_at, "id": _id, "email": linkPojo.email, "$set": {"url_validated": state, "validated_at": validated_at, "id": _id, "email": linkPojo.email,
"url": link, "url": link, "validated_by_ua": ua,
"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}}, "validated_by": validated_by}},
upsert=True) upsert=True)
# remove the link from db # remove the link from db
@@ -1,130 +0,0 @@
{
"ttst": 5.500000000465661,
"ifov": false,
"hc": 8,
"br_oh": 992,
"br_ow": 1920,
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
"wbd": false,
"tagpu": 1.7174740373540653,
"wdif": false,
"wdifrm": false,
"npmtm": false,
"br_h": 992,
"br_w": 1920,
"isf": true,
"nddc": 1,
"rs_h": 768,
"rs_w": 1024,
"rs_cd": 24,
"phe": false,
"nm": false,
"jsf": false,
"lg": "fr-BE",
"pr": 1,
"ars_h": 743,
"ars_w": 1024,
"tz": -60,
"str_ss": true,
"str_ls": true,
"str_idb": true,
"str_odb": false,
"plgod": false,
"plg": 5,
"plgne": true,
"plgre": true,
"plgof": false,
"plggt": false,
"pltod": false,
"hcovdr": false,
"hcovdr2": false,
"plovdr": false,
"plovdr2": false,
"ftsovdr": false,
"ftsovdr2": false,
"lb": false,
"eva": 33,
"lo": false,
"ts_mtp": 0,
"ts_tec": false,
"ts_tsa": false,
"vnd": "Google Inc.",
"bid": "NA",
"mmt": "application/pdf,text/pdf",
"plu": "PDF Viewer,Chrome PDF Viewer,Chromium PDF Viewer,Microsoft Edge PDF Viewer,WebKit built-in PDF",
"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": 4,
"sqt": false,
"so": "landscape-primary",
"wdw": true,
"cokys": "bG9hZFRpbWVzY3NpYXBwL=",
"ecpc": false,
"lgs": true,
"lgsod": false,
"psn": true,
"edp": true,
"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": "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3",
"stcfp": "cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IE9iamVjdC5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw",
"ckwa": true,
"prm": true,
"cvs": true,
"usb": "defined",
"emd": "k:ai,vi,ao",
"glvd": "Apple Inc.",
"glrd": "Intel HD Graphics 3000 OpenGL Engine",
"wwl": false,
"jset": 1734772335
}
@@ -1,127 +0,0 @@
{
"ttst": 22.000000002793968,
"ifov": false,
"hc": 8,
"br_oh": 763,
"br_ow": 393,
"ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36",
"wbd": false,
"tagpu": 2.3672133588807087,
"wdif": false,
"wdifrm": false,
"npmtm": false,
"br_h": 763,
"br_w": 393,
"isf": true,
"nddc": 1,
"rs_h": 873,
"rs_w": 393,
"rs_cd": 24,
"phe": false,
"nm": false,
"jsf": false,
"lg": "fr-FR",
"pr": 2.75,
"ars_h": 873,
"ars_w": 393,
"tz": -60,
"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": "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3",
"stcfp": "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IHQuZXhwb3J0cy5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw",
"ckwa": true,
"emd": "k:ai,vi,ao",
"glvd": "Qualcomm",
"glrd": "Adreno (TM) 642L",
"wwl": false,
"jset": 1734690551
}
@@ -1,127 +0,0 @@
{
"ttst": 15.000000002047893,
"ifov": false,
"hc": 5,
"br_oh": 620,
"br_ow": 360,
"ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36",
"wbd": false,
"tagpu": 9.136966557013412,
"wdif": false,
"wdifrm": false,
"npmtm": false,
"br_h": 620,
"br_w": 360,
"isf": true,
"nddc": 1,
"rs_h": 804,
"rs_w": 360,
"rs_cd": 24,
"phe": false,
"nm": false,
"jsf": false,
"lg": "fr-FR",
"pr": 3,
"ars_h": 804,
"ars_w": 360,
"tz": -120,
"str_ss": true,
"str_ls": true,
"str_idb": true,
"str_odb": true,
"plgod": false,
"plg": 2,
"plgne": "err",
"plgre": "err",
"plgof": "err",
"plggt": "err",
"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": "eTJjZUp,iZMOHLs1",
"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": 4,
"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": "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3",
"stcfp": "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IHQuZXhwb3J0cy5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw",
"ckwa": true,
"emd": "k:ai,vi,ao,vi d:defau,8f9de,defau,24476 g:4e652,f9991,defau,d5801",
"glvd": "ARM",
"glrd": "Mali-G57 MC2",
"wwl": false,
"jset": 1734775162
}
@@ -1,151 +0,0 @@
{
"ttst": 46.8000000026077,
"ifov": false,
"hc": 8,
"br_oh": 763,
"br_ow": 393,
"ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36",
"wbd": false,
"tagpu": 7.9067645182878366,
"wdif": false,
"wdifrm": false,
"npmtm": false,
"br_h": 763,
"br_w": 393,
"isf": true,
"nddc": 1,
"rs_h": 873,
"rs_w": 393,
"rs_cd": 24,
"phe": false,
"nm": false,
"jsf": false,
"lg": "fr-FR",
"pr": 2.75,
"ars_h": 873,
"ars_w": 393,
"tz": -60,
"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": "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3",
"stcfp": "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IHQuZXhwb3J0cy5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw",
"ckwa": true,
"glvd": "Qualcomm",
"glrd": "Adreno (TM) 642L",
"wwl": false,
"tzp": "Europe/Paris",
"jset": 1734690519,
"emd": "k:ai,vi,ao",
"dcok": ".hermes.com",
"m_fmi": false,
"tbce": 0,
"es_sigmdn": null,
"es_mumdn": null,
"es_distmdn": null,
"es_angsmdn": null,
"es_angemdn": null,
"k_hA": 0,
"k_hSD": 0,
"k_pA": 862.6666666666666,
"k_pSD": 1159.6290594649463,
"k_rA": 862.6666666666666,
"k_rSD": 1159.6290594649463,
"k_ikA": 862.6666666666666,
"k_ikSD": 1159.6290594649463,
"k_kdc": 7,
"k_kuc": 7,
"m_s_c": 30,
"m_m_c": 3,
"m_c_c": 3,
"m_cm_r": 1,
"m_ms_r": 0.1
}
@@ -1,149 +0,0 @@
{
"ttst": 13.000000008223282,
"ifov": false,
"hc": 5,
"br_oh": 620,
"br_ow": 360,
"ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36",
"wbd": false,
"tagpu": 5.501734809203354,
"wdif": false,
"wdifrm": false,
"npmtm": false,
"br_h": 620,
"br_w": 360,
"isf": true,
"nddc": 1,
"rs_h": 804,
"rs_w": 360,
"rs_cd": 24,
"phe": false,
"nm": false,
"jsf": false,
"lg": "fr-FR",
"pr": 3,
"ars_h": 804,
"ars_w": 360,
"tz": -120,
"str_ss": true,
"str_ls": true,
"str_idb": true,
"str_odb": true,
"plgod": false,
"plg": 2,
"plgne": "err",
"plgre": "err",
"plgof": "err",
"plggt": "err",
"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": "eTJjZUp,iZMOHLs1",
"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": 4,
"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": "ZnVuY3Rpb24oKXt2YXIgbj10LGk9ZG9jdW1lbnRbJ1x4NzFceDc1XHg2NVx4NzJceDc5XHg1M1x4NjVceDZjXHg2NVx4NjNceDc0XHg2Zlx4NzInXShuKDQ2MSkpO2lmKGkpeyFmdW5jdGlvbiB0KCl7dHJ5e3ZhciBuPWlbJ1x4NzNceDY4XHg2MVx4NjRceDZmXHg3",
"stcfp": "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4ODYzNSkKICAgIGF0IHQuZXhwb3J0cy5kZF9hZCAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDc3OTYpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjYzNzkw",
"ckwa": true,
"emd": "k:ai,vi,ao,vi d:defau,8f9de,defau,24476 g:4e652,f9991,defau,d5801",
"glvd": "ARM",
"glrd": "Mali-G57 MC2",
"wwl": false,
"jset": 1734775843,
"dcok": ".hermes.com",
"log2": true,
"es_sigmdn": null,
"es_mumdn": null,
"es_distmdn": null,
"es_angsmdn": null,
"es_angemdn": null,
"k_hA": null,
"k_hSD": null,
"k_pA": null,
"k_pSD": null,
"k_rA": null,
"k_rSD": null,
"k_ikA": null,
"k_ikSD": null,
"k_kdc": 0,
"k_kuc": 0,
"m_s_c": 0,
"m_m_c": 3,
"m_c_c": 3,
"m_cm_r": 1,
"m_ms_r": -1
}
-423
View File
@@ -1,423 +0,0 @@
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
View File
@@ -0,0 +1 @@
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
View File
@@ -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, dtype={'passport': str}).to_json(orient='records') contact_list_in_json = pandas.read_excel(file_name).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:
+6 -7
View File
@@ -2,15 +2,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__':
# # link_list = MONGO_STORE_MANAGER.get_links_to_validate()
# validate_with_FR_ip(segment_position=2)
def start_link_validation(): if __name__ == '__main__':
# 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(30)
if __name__ == '__main__':
start_link_validation()
-128
View File
@@ -1,128 +0,0 @@
import logging
import random
import time
import requests
from db.mongo_manager import MONGO_STORE_MANAGER
from mail.mail_reader_all_contacts import find_links_to_validate_from_mail_list
from models.mail_pojo import MailAddress
host = "https://authhk.bhdata.com:30015/bhmailer?uid=482391396&sign=32d7748da00047b9a1054c81a5750365"
is_checking = False
HERMES_EMAIL = "no-reply@hermes.com"
def get_api_info():
_time = str(int(time.time() * 1000))
_api_info = host + "&act=getApiInfo&t=" + _time
print(_api_info)
res = requests.get(_api_info, verify=False)
print(res.text)
def get_mail(mail: str):
_time = str(int(time.time() * 1000))
_hermes_mail = "Votre demande de rendez-vous"
_api_info = host + "&act=getMail&email={}&title={}&t={}".format(mail, _hermes_mail, _time)
print(_api_info)
res = requests.get(_api_info, verify=False)
print(res.text)
def check_mail(mail: str):
print("check_mail called for {}".format(mail))
_time = str(int(time.time() * 1000))
_hermes_mail = HERMES_EMAIL
_subjet = "Votre rendez-vous est confirmé"
_api_info = host + "&act=checkMail&email={}&from={}&title={}&t={}".format(mail, _hermes_mail, _subjet, _time)
print(_api_info)
res = requests.get(_api_info, verify=False)
print(res.text)
def check_appointment_link_mail(mail: str):
print("check_mail called for {}".format(mail))
_time = str(int(time.time() * 1000))
_hermes_mail = HERMES_EMAIL
_subjet = "Votre demande de rendez-vous"
_api_info = host + "&act=checkMail&email={}&from={}&title={}&t={}".format(mail, _hermes_mail, _subjet, _time)
print(_api_info)
res = requests.get(_api_info, verify=False)
print(res.text)
def get_account(mail: str):
_time = str(int(time.time() * 1000))
_api_info = host + "&act=getAccount&email={}&t={}".format(mail, _time)
print(_api_info)
res = requests.get(_api_info, verify=False)
print(res.text)
def filter_mail_with_links(_mail_list_to_filter):
_new_mail_list = []
_link_to_validate_list = MONGO_STORE_MANAGER.get_links_to_validate()
for _mail in _mail_list_to_filter:
_to_add = True
for _link in _link_to_validate_list:
if _link.email == _mail:
_to_add = False
if _to_add:
_new_mail_list.append(_mail)
return _new_mail_list
def get_mail_list_to_check():
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
_mail_list = []
for _item in successful_items:
if _item.url_validated is None or _item.url_validated != True:
_mail_list.append(_item.email)
return _mail_list
def check_confirmed_mails():
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
# _mail_list = []
for _item in successful_items:
if "outlook" in _item.email or "hotmail" in _item.email:
check_mail(_item.email)
time.sleep(random.randint(1, 5))
def check_all_need_to_check_emails():
global is_checking
if not is_checking:
is_checking = True
logger = logging.getLogger()
_mail_list_before_filter = get_mail_list_to_check()
_mails = filter_mail_with_links(_mail_list_before_filter)
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@")]
# find_links_to_validate_from_mail_list(_mail_list, logger)
is_checking = False
def try_to_check_all_mails():
logger = logging.getLogger()
_mail_list_before_filter = get_mail_list_to_check()
_mails = filter_mail_with_links(_mail_list_before_filter)
for _mail in _mails:
if "outlook.com" in _mail or "hotmail.com" in _mail:
check_appointment_link_mail(_mail)
time.sleep(2)
# _mail_list = [MailAddress("saigecong1990@pissmail.com", "cvExXKOP8oY1D@")]
# find_links_to_validate_from_mail_list(_mail_list, logger)
if __name__ == '__main__':
check_all_need_to_check_emails()
# try_to_check_all_mails()
# check_confirmed_mails()
# check_appointment_link_mail("hcunlvi533@outlook.com")
+42 -42
View File
@@ -2,7 +2,6 @@ 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"
@@ -11,9 +10,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"
DOMAIN_BTVM_NE_JP = "btvm.ne.jp" DOMAN_BTVM_NE_JP = "btvm.ne.jp"
DOMAIN_AURORA_DTI_NE_JP = "aurora.dti.ne.jp" DOMAN_AURORA_DTI_NE_JP = "aurora.dti.ne.jp"
DOMAIN_GMAIL = "gmail.com" DOMAN_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"
@@ -28,7 +27,6 @@ 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"
@@ -40,7 +38,6 @@ 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"
@@ -52,17 +49,18 @@ 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_SERVER = "imap.btvm.ne.jp" BTVM_NE_JP = "imap.btvm.ne.jp"
GMAIL_IMAP_SERVER = "imap.gmail.com" SEREVER_GMAIL = "imap.gmail.com"
ONET_IMAP_SERVER = "imap.poczta.onet.pl" SERVER_IMAGE_ONET = "imap.poczta.onet.pl"
GMX_IMAP_SERVER = "imap.gmx.com" SERVER_GMX = "imap.gmx.com"
GMX_NET_IMAP_SERVER = "imap.gmx.net" SERVER_GMX_NET = "imap.gmx.net"
GMX_AT_IMAP_SERVER = "imap.gmx.at" SERVER_GMX_AT = "imap.gmx.at"
FIREMAIL_DE_IMAP_SERVER = "imap.firemail.de" SERVER_FIREMAIL_DE = "imap.firemail.de"
PISS_MAIL_IMAP_SERVER = "mail.pissmail.com" SERVER_PISS_MAIL = "mail.pissmail.com"
INBOX_LV_IMAP_SERVER = "mail.inbox.lv" INBOX_LV = "mail.inbox.lv"
WEB_DE_IMAP_SERVER = "imap.web.de" SERVER_WEB_DE = "imap.web.de"
GAZETA_PL_IMAP_SERVER = "imap.gazeta.pl" IMAP_SERVER_DOMAIN_GAZETA_PL = "imap.gazeta.pl"
def show_folders(imap) -> list: def show_folders(imap) -> list:
folders = [] folders = []
@@ -84,49 +82,51 @@ def show_folders(imap) -> list:
def create_imap(login: str): def create_imap(login: str):
# 创建一个IMAP4类实例 # create an IMAP4 class with SSL
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 = IMAPClient(YAHOO_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(YAHOO_IMAP_SERVER)
elif DOMAIN_FIREMAIL_DE in login: elif DOMAIN_FIREMAIL_DE in login:
imap = IMAPClient(FIREMAIL_DE_IMAP_SERVER, use_uid=True) # imap = imaplib.IMAP4_SSL(SERVER_FIREMAIL_DE)
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 = IMAPClient(GMX_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(SERVER_GMX)
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 = IMAPClient(HOTMAIL_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(HOTMAIL_IMAP_SERVER)
elif DOMAIN_RAMBLER_RU in login: elif DOMAIN_RAMBLER_RU in login:
imap = IMAPClient(RAMBLER_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(RAMBLER_IMAP_SERVER)
elif DOMAIN_BTVM_NE_JP in login: elif DOMAN_BTVM_NE_JP in login:
imap = IMAPClient(BTVM_NE_JP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(BTVM_NE_JP)
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)
elif DOMAIN_ONET in login: elif DOMAIN_ONET in login:
imap = IMAPClient(ONET_IMAP_SERVER, use_uid=True) imap = IMAPClient(SERVER_IMAGE_ONET, use_uid=True)
elif DOMAIN_TIM_IT in login: elif DOMAIN_TIM_IT in login:
imap = IMAPClient(TIME_IT_SERVER, use_uid=True) imap = imaplib.IMAP4(TIME_IT_SERVER)
elif DOMAIN_ALICE_IT in login: elif DOMAIN_ALICE_IT in login:
imap = IMAPClient(ALICE_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4(ALICE_IMAP_SERVER, port=143)
elif DOMAIN_MARS_DTI_NE_JP in login: elif DOMAIN_MARS_DTI_NE_JP in login:
imap = IMAPClient(MARS_DTI_NE_JP_SERVER, use_uid=True) imap = imaplib.IMAP4(MARS_DTI_NE_JP_SERVER, port=143)
elif DOMAIN_AURORA_DTI_NE_JP in login: elif DOMAN_AURORA_DTI_NE_JP in login:
imap = IMAPClient(MARS_DTI_NE_JP_SERVER, use_uid=True) imap = imaplib.IMAP4(MARS_DTI_NE_JP_SERVER, port=143)
elif DOMAIN_NAVER in login: elif DOMAIN_NAVER in login:
imap = IMAPClient(NAVER_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(NAVER_SERVER, port=993)
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 = IMAPClient(GMX_NET_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(SERVER_GMX_NET, port=993)
elif DOMAIN_GMX_AT in login: elif DOMAIN_GMX_AT in login:
imap = IMAPClient(GMX_AT_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(SERVER_GMX_AT, port=993)
elif DOMAIN_GAZETA_PL in login: elif DOMAIN_GAZETA_PL in login:
imap = IMAPClient(GAZETA_PL_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(IMAP_SERVER_DOMAIN_GAZETA_PL, port=993)
elif DOMAIN_INBOX_LV in login: elif DOMAIN_INBOX_LV in login:
imap = IMAPClient(INBOX_LV_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(INBOX_LV, port=993)
elif DOMAIN_WEB_DE in login: elif DOMAIN_WEB_DE in login:
imap = IMAPClient(WEB_DE_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(SERVER_WEB_DE, port=993)
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 = IMAPClient(PISS_MAIL_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(SERVER_PISS_MAIL, port=993)
else: else:
imap = IMAPClient(AOL_IMAP_SERVER, use_uid=True) imap = imaplib.IMAP4_SSL(AOL_IMAP_SERVER)
return imap return imap
Regular → Executable
+170 -347
View File
@@ -2,99 +2,79 @@ 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, 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
from excel_reader import read_contacts
from mail.mail_constants import DOMAIN_HOTMAIL, create_imap from mail.mail_constants import DOMAIN_HOTMAIL, create_imap
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 = r"https:\/\/rendezvousparis.hermes.com\/client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+" VALIDATION_URL_REGEX = """https:\/\/rendezvousparis.hermes.com\/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]+" PART_VALIDATION_URL_REGEX = """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):
def is_valid_email(email: str) -> bool: # pass the regular expression
"""验证邮箱地址是否有效""" # and the string into the fullmatch() method
return re.fullmatch(EMAIL_ADDRESS_REGEX, email) is not None if (re.fullmatch(EMAIL_ADDRESS_REGEX, email)):
print("Valid Email")
return True
else:
print("Invalid Email:" + email)
return False
def extract_email_from_from_address(content: str) -> str: def find_from_mail(param):
"""从邮件地址中提取邮箱"""
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("<")
class MailReader: class MailReader():
"""邮件读取器类""" def __init__(self, login, password):
def __init__(self, login: str, password: str):
self.login = login self.login = login
self.password = password self.password = password
@staticmethod @staticmethod
def show_folders(imap) -> List[str]: def show_folders(imap) -> list:
"""获取邮箱文件夹列表"""
folders = [] folders = []
is_imap_client = isinstance(imap, IMAPClient) isImapClient = 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:
# 处理IMAPClient对象 list = imap.list_folders()
folder_list = imap.list_folders() for i in list:
for i in folder_list:
name = i[-1] name = i[-1]
folders.append(name) folders.append(name)
return folders
return folders def read_emails(self, mails_messages: list) -> list:
def read_emails(self, mails_messages: List[MailPojo]) -> List[MailPojo]:
"""读取邮件"""
imap = create_imap(self.login) imap = create_imap(self.login)
is_imap_client = isinstance(imap, IMAPClient) isImapClient = isinstance(imap, IMAPClient)
print("isImapClient is " + str(isImapClient))
# 登录邮箱 if isImapClient:
if is_imap_client: # authenticate
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:
@@ -103,343 +83,186 @@ 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)
folder_list = self.show_folders(imap) for folder in folder_list:
print("folder is {}".format(folder))
# 处理每个文件夹 mail_list.extend(self._get_messages_from_folder(imap, subject=VALIDATION_URL_SUBJECT_fr,
for folder in folder_list: folder=folder))
print("folder is {}".format(folder)) mail_list.extend(self._get_messages_from_folder(imap, subject=VALIDATION_URL_SUBJECT_EN,
folder=folder))
# 跳过Sent和Drafts文件夹 else:
if folder in ["Sent", "Drafts"]: folder_list = self.show_folders(imap)
continue for folder in folder_list:
print("folder is " + folder)
if is_imap_client: mail_list.extend(self._get_messages_from_folder_for_imapclient(imap, folder=folder))
# 使用IMAPClient处理 if not isImapClient:
mail_list.extend(self._get_messages_from_folder_for_imapclient(imap, folder))
else:
# 使用传统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: str, folder: str = "INBOX") -> List[MailPojo]: def _get_messages_from_folder(self, imap, subject, folder="INBOX") -> list:
"""从指定文件夹获取邮件(传统IMAP方式)"""
imap.select(folder) imap.select(folder)
mail_messages = [] mail_messages = []
typ, data = imap.search(None, '(SUBJECT "{}" SINCE "{}")'.format(subject,
# 搜索邮件 datetime.datetime.today().strftime(
search_query = '(SUBJECT "{}" SINCE "{}")'.format(subject, datetime.datetime.today().strftime(DATE_FORMAT)) date_format)))
typ, data = imap.search(None, search_query)
for i in data[0].split(): for i in data[0].split():
try: # fetch the email message by ID
# 获取邮件内容 res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)")
res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)") body = ''
for response in msg:
# 解析邮件 if isinstance(response, tuple):
for response in msg: # parse a bytes email into a message object
if isinstance(response, tuple): msg = email.message_from_bytes(response[1])
email_message = email.message_from_bytes(response[1]) # decode the email subject
subject, subject_encoded = decode_header(msg["Subject"])[0]
# 解码主题 received_date = msg["Date"]
subject, subject_encoded = decode_header(email_message["Subject"])[0] if isinstance(subject, bytes):
if isinstance(subject, bytes): # if it's a bytes, decode to str
subject = subject.decode(subject_encoded) subject = subject.decode(subject_encoded)
# decode email sender
# 解码发件人地址 from_address = find_from_mail(decode_header(msg.get("From")))
from_address = find_from_mail(decode_header(email_message.get("From"))) to_email = find_from_mail(decode_header(msg.get("To")))
print("Email:", self.login)
# 解码收件人地址 print("From:", from_address)
to_email = find_from_mail(decode_header(email_message.get("To"))) print("To:", to_email)
print("Subject:", subject)
print("Email:", self.login) # if the email message is multipart
print("From:", from_address) if msg.is_multipart():
print("To:", to_email) # iterate over email parts
print("Subject:", subject) for part in msg.walk():
try:
# 获取邮件正文 # get the email body
body = self._extract_body(email_message) payloads = part.get_payload()
if isinstance(payloads, list):
# 检查是否是预约验证邮件 for payload in payloads:
if VALIDATION_URL_SUBJECT_FR in subject or VALIDATION_URL_SUBJECT_EN in subject: if isinstance(payload, Message):
mail = MailPojo( body = body + payload.get_payload(decode=True).decode("iso-8859-1")
subject=subject, # print(body)
body=body, except Exception as Error:
from_address=from_address print(Error)
) else:
body = msg.get_payload(decode=True).decode()
# 设置收件人地址 print(body)
if to_email is None: if VALIDATION_URL_SUBJECT_fr in subject or VALIDATION_URL_SUBJECT_EN in subject:
mail.to_address = self.login mail = MailPojo(subject=subject, body=body, from_address=from_address)
else: if to_email is None:
mail.to_address = to_email mail.to_address = self.login
else:
mail.mail_address = self.login mail.to_address = to_email
mail_messages.append(mail) mail.mail_address = self.login
except Exception as error: mail_messages.append(mail)
print("Error processing email: {}".format(error))
return mail_messages return mail_messages
def _extract_body(self, email_message: Message) -> str: def _get_messages_from_folder_for_imapclient(self, imap, folder="INBOX") -> list:
"""提取邮件正文"""
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(DATE_FORMAT)) datetime.datetime.today().strftime(
print("{}: search terms is {}".format(self.login, search_terms)) date_format))
print("search terms is " + 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("%d messages from our best friend" % len(messages))
if len(messages) == 0:
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')
# print("{}, {},{}".format(from_address, subject, email_message))
# 检查是否是Hermes邮件 body = ""
hermes_mail_address = "no-reply@hermes.com" if "no-reply@hermes.com" in from_address or "appointment2022@aol.com":
if (hermes_mail_address in from_address or for part in email_message.walk():
"outlook.com" in from_address or print(part.get_content_type())
"hotmail" in from_address): if part.get_content_type() == "text/html":
body = body + part.get_payload(decode=True).decode("utf-8")
# 提取邮件正文 elif part.get_content_type() == "text/plain":
body = self._extract_body_for_imapclient(email_message) body = body + part.get_payload()
if VALIDATION_URL_SUBJECT_fr in subject or VALIDATION_URL_SUBJECT_EN in subject or "Validation=20de=20votre=20demande=20de=20rendez-vous" in subject:
# 检查是否是预约验证邮件 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: mail.to_address = self.login
# 转发邮件
mail.to_address = extract_email_from_from_address(from_address)
else:
mail.to_address = self.login
mail_messages.append(mail) mail_messages.append(mail)
except Exception as error: except Exception as error:
print("Error trying to read email_Message for {}: {}".format(self.login, error)) print(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(): def need_to_valid_url(url: str, successful_items) -> bool:
content_type = part.get_content_type() # return True
# if len(successful_items) == 0:
if content_type == "text/html": # return False
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]:
"""根据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 if item.url_validated is not None:
return not item.url_validated
return None else:
# if url_validated is None
return True
def need_to_valid_url(url: str, item: Union[ReserveResultPojo, None]) -> bool:
"""判断是否需要验证URL"""
print("url is :" + url)
parts = url.split('/')
_id = parts[5]
if len(_id) == 6:
if item:
if item.url_validated is not None:
return not item.url_validated
else:
# 如果url_validated为None,需要验证
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)))
filtered_items = list(filter(lambda item: item.email == mail, successful_items))
# 特殊处理 # has validated value
if mail == "saigecong1990@pissmail.com": 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 # check time before start checking emails
if item.url_validated is not None and item.url_validated is True] if len(mail_list) > 0:
contact_to_book_list = MONGO_STORE_MANAGER.get_all_contact_to_book_list()
return len(validated_items) == 0 successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
mails_messages = []
with ThreadPoolExecutor(max_workers=len(mail_list)) as executor:
for mail in mail_list:
# check whether we need to read mail
if need_to_check_email(mail.mail, successful_items):
mail_reader = MailReader(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages)
# for mail in mail_list:
# # check whether we need to read mail
# if need_to_check_email(mail.mail, successful_items):
# mail_reader = MailReader(mail.mail, mail.password)
# mail_reader.read_emails(mails_messages)
_refreshed_successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
for mail in mails_messages:
match = re.search(VALIDATION_URL_REGEX, mail.body)
if match:
url = match.group(0)
if need_to_valid_url(url, _refreshed_successful_items):
logger.info("need to validate url: " + url)
MONGO_STORE_MANAGER.save_links_to_validate(url, mail.to_address,
_all_contact_list=contact_to_book_list)
else:
logger.info("do not need to click url --> {}".format(mail.mail_address))
def find_links_to_validate_from_mail_list(mail_list: List[MailAddress], logger) -> None:
"""从邮件列表中查找需要验证的链接"""
if not mail_list:
return
# 检查时间前开始检查邮件
contact_to_book_list = MONGO_STORE_MANAGER.get_all_contact_to_book_list()
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
mails_messages = []
# 使用线程池处理邮件
with ThreadPoolExecutor(max_workers=100) as executor:
futures = []
for mail in mail_list:
# 检查是否需要读取邮件
if need_to_check_email(mail.mail, successful_items):
mail_reader = MailReader(mail.mail, mail.password)
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()
# 处理邮件中的链接
for mail in mails_messages:
match = re.search(VALIDATION_URL_REGEX, mail.body)
if match:
url = match.group(0)
_item = find_item_by_url(url, _refreshed_successful_items)
if need_to_valid_url(url, _item):
logger.info("need to validate url: " + url)
_model = ""
_used_ip = ""
if _item:
_model = _item.model
_used_ip = _item.current_ip
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:
logger.info("do not need to click url --> {}".format(mail.mail_address))
# 主函数
if __name__ == '__main__': if __name__ == '__main__':
# 读取联系人列表 mail_address1 = MailAddress(mail="tzfhygwwjiwnf@hotmail.com", password="rqO4Pjm7NQ")
contact_to_book_list = read_contacts( mail_list = [mail_address1]
file_name="~/Desktop/contact_list_2025-11-28.xlsx")
# file_name="~/Desktop/contact_list_all.xlsx")
# file_name="~/Desktop/contact_list_2025-11-06.xlsx")
# 获取目标邮箱列表
all_mail_list = MONGO_STORE_MANAGER.get_destination_emails()
# 筛选需要检查的邮件列表
mail_list_to_check = []
for contact in contact_to_book_list:
for mail in all_mail_list:
if contact.mail == mail.mail:
mail_list_to_check.append(mail)
# 设置日志记录器
logger = logging.getLogger() logger = logging.getLogger()
find_links_to_validate_from_mail_list(mail_list, logger)
# 获取已验证的链接列表
_all_links = MONGO_STORE_MANAGER.get_links_to_validate()
# 过滤掉已处理的邮件
filter_mail = []
for mail_pojo in mail_list_to_check:
_to_add = True
for _link in _all_links:
if _link.email == mail_pojo.mail:
_to_add = False
if _to_add:
filter_mail.append(mail_pojo)
# filter_mail = [MailAddress("utatapi@gmx.net", "RSAzHAFek8s")]
# 处理邮件
find_links_to_validate_from_mail_list(filter_mail, logger)
+3 -3
View File
@@ -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)
+2 -2
View File
@@ -3,6 +3,6 @@ from queue_message.CookiesPublisher import MORNING_DATA_CACHE_2, MORNING_DATA_CA
from workers.MessagerTransporter import migrate_message_to_queue, empty_message_just_to from workers.MessagerTransporter import migrate_message_to_queue, empty_message_just_to
if __name__ == '__main__': if __name__ == '__main__':
migrate_message_to_queue(from_queue=MORNING_DATA_CACHE, to_queue=MORNING_DATA_CACHE_BAK) # migrate_message_to_queue(from_queue=MORNING_DATA_CACHE_BAK, to_queue=MORNING_DATA_CACHE)
# empty_message_just_to(2000, queue_name=MORNING_DATA_CACHE_BAK) empty_message_just_to(20000, queue_name=MORNING_DATA_CACHE_BAK)
# migrate_message_to_queue(from_queue=MORNING_DATA_CACHE_BAK,to_queue=REQUEST_DATA_QUEUE_DE) # migrate_message_to_queue(from_queue=MORNING_DATA_CACHE_BAK,to_queue=REQUEST_DATA_QUEUE_DE)
+2 -9
View File
@@ -1,9 +1,7 @@
class LinkPojo(): class LinkPojo():
def __init__(self, url, email, model, serial, updated_at, ip_country): def __init__(self, url, email, updated_at, ip_country):
self.url = url self.url = url
self.email = email self.email = email
self.model = model
self.serial = serial
self.updated_at = updated_at self.updated_at = updated_at
self.ip_country = ip_country self.ip_country = ip_country
@@ -11,14 +9,9 @@ class LinkPojo():
def from_firestore_dict(source): def from_firestore_dict(source):
updated_at = source['updated_at'] updated_at = source['updated_at']
email = source['email'] email = source['email']
model = ""
if 'model' in source:
model = source['model']
serial = source['serial']
url = source['url'] url = source['url']
ip_country = "FR" ip_country = "FR"
if source.get('ip_country'): if source.get('ip_country'):
ip_country = source['ip_country'] ip_country = source['ip_country']
result = LinkPojo(email=email, url=url, model=model, serial=serial, updated_at=updated_at, result = LinkPojo(email=email, url=url, updated_at=updated_at, ip_country=ip_country)
ip_country=ip_country)
return result return result
+12 -11
View File
@@ -16,6 +16,7 @@ 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 = ""
@@ -28,7 +29,6 @@ class ReserveResultPojo:
slot_position = None slot_position = None
sim_position = None sim_position = None
ccid: str = "" ccid: str = ""
model: str = ""
source_from: str = socket.gethostname() source_from: str = socket.gethostname()
store_type = 0 store_type = 0
url_validated = None url_validated = None
@@ -37,10 +37,14 @@ 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:
@@ -49,6 +53,8 @@ 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:
@@ -67,7 +73,7 @@ class ReserveResultPojo:
else: else:
firstName = "" firstName = ""
result = ReserveResultPojo(phone=phone, result = ReserveResultPojo(type=publish_type, 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:
@@ -100,20 +106,15 @@ class ReserveResultPojo:
if 'created_at' in source: if 'created_at' in source:
created_at = source['created_at'] created_at = source['created_at']
result.created_at = created_at result.created_at = created_at
if 'model' in source:
model = source['model']
result.model = model
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,
@@ -121,7 +122,8 @@ class ReserveResultPojo:
u'email': self.email, u'email': self.email,
u'passport': self.passport, u'passport': self.passport,
u'url': self.url, u'url': self.url,
u'model': self.model, # u'sim_position': self.sim_position,
# u'slot_position': self.slot_position,
u'source_from': self.source_from, u'source_from': self.source_from,
u'hostName': self.source_from, u'hostName': self.source_from,
u'created_at': self.created_at, u'created_at': self.created_at,
@@ -130,7 +132,6 @@ 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,
} }
-7
View File
@@ -13,7 +13,6 @@ class ContactPojo:
store: str store: str
note: str note: str
ua: str ua: str
serial: str
def __init__(self, phone_number: str, passport_number: str, last_name: str, first_name: str, mail: str, def __init__(self, phone_number: str, passport_number: str, last_name: str, first_name: str, mail: str,
ccid: str = "", ccid: str = "",
@@ -28,7 +27,6 @@ class ContactPojo:
self.note = "" self.note = ""
self.ua = "" self.ua = ""
self.current_ip = "" self.current_ip = ""
self.serial = "reqeusts"
def to_firestore_dict(self): def to_firestore_dict(self):
dest = { dest = {
@@ -40,7 +38,6 @@ class ContactPojo:
u'store': self.store, u'store': self.store,
u'ccid': self.ccid, u'ccid': self.ccid,
u'position': self.position, u'position': self.position,
u'serial': self.serial,
u'current_ip': self.current_ip, u'current_ip': self.current_ip,
u'ua': self.ua u'ua': self.ua
} }
@@ -55,13 +52,9 @@ class ContactPojo:
last_name = source['last_name'] last_name = source['last_name']
first_name = source['first_name'] first_name = source['first_name']
ip_country = "FR" ip_country = "FR"
if source.get('ip_country'): if source.get('ip_country'):
ip_country = source['ip_country'] ip_country = source['ip_country']
result = ContactPojo(phone_number=phone, passport_number=passport, mail=email, result = ContactPojo(phone_number=phone, passport_number=passport, mail=email,
last_name=last_name, first_name=first_name) last_name=last_name, first_name=first_name)
result.ip_country = ip_country result.ip_country = ip_country
if source.get('serial'):
serial = source['serial']
result.serial = serial
return result return result
+8 -65
View File
@@ -1,8 +1,6 @@
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
@@ -23,29 +21,9 @@ 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, ccsB, vnd, pr, ts_mtp, dvm, m_s_c, m_m_c, m_c_c, m_cm_r, m_ms_r, emd: str):
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, ccsB=ccsB, br_iw=br_iw, br_ih=br_ih, pf=pf, mob=mob, lgs=lgs, vnd, pr, ts_mtp, dvm, emd=emd)
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"
@@ -72,32 +50,14 @@ at nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%
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 = "KHIsbixvLGEpPT57aWYoZVtyXSllW3JdLnB1c2gobik7ZWxzZXt2YXIgcyxjO2lmKHZvaWQgMCE9PW8pZm9yKHZhciB1PWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKSxkPTA7ZDx1Lmxlbmd0aDtkKyspe3ZhciBsPXVbZF07aWYobC5nZXRB" # 5.1.8 self.cfpfe = "ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudFsnXHg3MVx4NzVceDY1XHg3Mlx4NzlceDUzXHg2NVx4NmNceDY1XHg2M1x4NzRceDZmXHg3MiddKCdceDYyXHg3Mlx4NmZceDc3XHg3M1x4NjVceDcyXHg2Nlx4NmNceDZmXHg3N1x4MmRceDYzXHg2Zlx4NmVceDc0XHg2" # 4.35.0
self.stcfp = "JTIwSGVybWUlQ0MlODBzJTIwRnJhbmNlLmh0bTozNDoyNjY4OSkKYXRvIChmaWxlOi8vL1VzZXJzL3BhbmxlaS9Eb3dubG9hZHMvQnJhY2VsZXQlMjBDbGljJTIwSEglMjAtJTIwTWFycm9uJTIwXyUyMEhlcm1lJUNDJTgwcyUyMEZyYW5jZS5odG06MzQ6MzAzNzgp" # 5.1.8 self.stcfp = "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4MjIzMikKICAgIGF0IHQuZXhwb3J0cy5kZF9hYyAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDA3MDEpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjU3ODc0" # 4.35.0
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, 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;"}"""
"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'],
@@ -105,23 +65,6 @@ 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'], 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,
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, m_cm_r=1, m_ms_r=-1, emd=test_data_dict['emd'])
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()))
+85 -222
View File
@@ -10,19 +10,8 @@ import jsonpickle
@dataclass @dataclass
class JsDataPojo: class JsDataPojo:
# opts: str # opts: str
r3n: int ttst: int
exp8: int ifov: bool
# 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
@@ -30,12 +19,7 @@ class JsDataPojo:
wbd: bool wbd: bool
tagpu: float tagpu: float
wdif: bool wdif: bool
wdifpnh: int wdifrm: bool
lg: str
isb: bool
idp: bool
crt: int
npmtm: bool npmtm: bool
br_h: int br_h: int
br_w: int br_w: int
@@ -47,6 +31,7 @@ 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
@@ -124,7 +109,7 @@ class JsDataPojo:
wdw: bool wdw: bool
cokys: str cokys: str
ecpc: bool ecpc: bool
lgs: list lgs: bool
lgsod: bool lgsod: bool
psn: bool psn: bool
edp: bool edp: bool
@@ -151,151 +136,69 @@ 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.nddc = 1 self.ttst = random.randint(38, 148)
self.r3n = 33 self.ifov = False
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
self.ts_mtp = ts_mtp tag_pu = random.uniform(1, 10)
self.mob = mob while len(str(tag_pu)) != 17:
self.lgs = lgs tag_pu = random.uniform(1, 10)
self.dvm = dvm self.tagpu = tag_pu
self.hcovdr = False self.wdif = False
self.plovdr = False self.wdifrm = False
self.ftsovdr = False self.npmtm = False
self.orf = orf # to check
self.ttst = round(random.random(), 16)
self.br_w = br_w
self.br_h = br_h self.br_h = br_h
self.br_iw = br_iw self.br_w = br_w
self.br_ih = br_ih self.isf = True
self.ars_w = ars_w self.nddc = 1
self.ars_h = ars_h
self.rs_w = rs_w
self.rs_h = rs_h self.rs_h = rs_h
self.rs_w = rs_w
self.rs_cd = rs_cd self.rs_cd = rs_cd
self.phe = False
self.nm = False
self.jsf = False
self.lg = "fr-FR"
self.pr = pr self.pr = pr
self.so = "portrait-primary" self.ars_h = ars_h
self.vco = "" self.ars_w = ars_w
self.vcots = False self.tz = -120
self.vch = "probably" self.str_ss = True
self.vchts = True self.str_ls = True
self.vcw = "probably" self.str_idb = True
self.vcwts = True self.str_odb = 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 = "NA" self.plgne = "err"
self.plgre = "NA" self.plgre = "err"
self.plgof = "NA" self.plgof = "err"
self.plggt = "NA" self.plggt = "err"
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.bchk = bchk self.plu = str.join(",", plu) if isinstance(plu, list) else plu
self.nt_tcp = nt_tcp self.hdn = False
self.nt_dns = nt_dns self.awe = False
self.nt_rd = nt_rd self.geb = False
self.nt_irt = nt_irt self.dat = False
self.nt_rt = nt_rt self.med = "defined"
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"
@@ -317,58 +220,35 @@ at nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%
self.acwm = "maybe" self.acwm = "maybe"
self.acwmts = False self.acwmts = False
self.ocpt = False self.ocpt = False
self.ckwa = False self.vco = ""
self.spwn = False self.vcots = False
self.emt = False self.vch = "probably"
self.bfr = False self.vchts = True
self.tz = -120 self.vcw = "probably"
self.hdn = False self.vcwts = True
self.xt1 = False # pdfViewerEnabled self.vc3 = "maybe"
self.cdhf = False # window.hasFocus() self.vc3ts = False
self.eva = eva self.vcmp = ""
self.cokys = ",loadTimes,csi,app" self.vcmpts = False
self.ecpc = False self.vcq = ""
self.nhi = nhi self.vcqts = False
self.k_lyts = k_lyts self.vc1 = "probably"
self.k_lytk = k_lytk self.vc1ts = True
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.tzp = tzp self.wwl = False
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.lgs = ["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"] self.cokys = "bG9hZFRpbWVzY3NpL="
self.ecpc = False
self.lgs = True
self.lgsod = False self.lgsod = False
self.psn = True self.psn = True
self.edp = False self.edp = False
@@ -382,28 +262,21 @@ at nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%
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 = "KHIsbixvLGEpPT57aWYoZVtyXSllW3JdLnB1c2gobik7ZWxzZXt2YXIgcyxjO2lmKHZvaWQgMCE9PW8pZm9yKHZhciB1PWRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKSxkPTA7ZDx1Lmxlbmd0aDtkKyspe3ZhciBsPXVbZF07aWYobC5nZXRB" # 5.1.8 self.cfpfe = "ZnVuY3Rpb24oKXt2YXIgdD1kb2N1bWVudFsnXHg3MVx4NzVceDY1XHg3Mlx4NzlceDUzXHg2NVx4NmNceDY1XHg2M1x4NzRceDZmXHg3MiddKCdceDYyXHg3Mlx4NmZceDc3XHg3M1x4NjVceDcyXHg2Nlx4NmNceDZmXHg3N1x4MmRceDYzXHg2Zlx4NmVceDc0XHg2" # 4.35.0
self.stcfp = "JTIwSGVybWUlQ0MlODBzJTIwRnJhbmNlLmh0bTozNDoyNjY4OSkKYXRvIChmaWxlOi8vL1VzZXJzL3BhbmxlaS9Eb3dubG9hZHMvQnJhY2VsZXQlMjBDbGljJTIwSEglMjAtJTIwTWFycm9uJTIwXyUyMEhlcm1lJUNDJTgwcyUyMEZyYW5jZS5odG06MzQ6MzAzNzgp" # 5.1.8 self.stcfp = "Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6Mjo4MjIzMikKICAgIGF0IHQuZXhwb3J0cy5kZF9hYyAoaHR0cHM6Ly9kLmRpZ2l0YWwuaGVybWVzL3RhZ3MuanM6MjoxMDA3MDEpCiAgICBhdCBodHRwczovL2QuZGlnaXRhbC5oZXJtZXMvdGFncy5qczoyOjU3ODc0" # 4.35.0
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 js_str return _safe_string
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, 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;"}"""
"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)
@@ -413,17 +286,7 @@ 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
+87
View File
@@ -0,0 +1,87 @@
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()
+19 -53
View File
@@ -1,10 +1,5 @@
import logging
import random import random
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',
@@ -14,15 +9,10 @@ FR_PROXY_RES_OXY = {
'http': 'http://customer-rendezvous-cc-FR:Rdv202220212023@pr.oxylabs.io:7777', 'http': 'http://customer-rendezvous-cc-FR:Rdv202220212023@pr.oxylabs.io:7777',
'https': 'http://customer-rendezvous-cc-FR:Rdv202220212023@pr.oxylabs.io:7777' 'https': 'http://customer-rendezvous-cc-FR:Rdv202220212023@pr.oxylabs.io:7777'
} }
FR_PROXY_RES_PARIS_OXY = {
# customer-rendezvous-cc-fr-city-paris:PASSWORD@pr.oxylabs.io:7777
'http': 'http://customer-rendezvous-cc-fr-city-paris:Rdv202220212023@pr.oxylabs.io:7777',
'https': 'http://customer-rendezvous-cc-fr-city-paris:Rdv202220212023@pr.oxylabs.io:7777'
}
FR_PROXY_MOB_OXY = { FR_PROXY_MOB_OXY = {
'http': 'http://customer-rendezvousmob-cc-FR:Rdv+20222021@pr.oxylabs.io:7777', 'http': 'http://customer-rendezvousmob-cc-FR:Rdv202220212023@pr.oxylabs.io:7777',
'https': 'http://customer-rendezvousmob-cc-FR:Rdv+20222021@pr.oxylabs.io:7777' 'https': 'http://customer-rendezvousmob-cc-FR:Rdv202220212023@pr.oxylabs.io:7777'
} }
FR_PROXY_ASOCK_RES_2 = { FR_PROXY_ASOCK_RES_2 = {
@@ -30,8 +20,8 @@ FR_PROXY_ASOCK_RES_2 = {
'https': 'http://zd6fbrujot-res-country-FR-hold-query:8k8avNlnLHQaMsWg@217.23.6.161:9999' 'https': 'http://zd6fbrujot-res-country-FR-hold-query:8k8avNlnLHQaMsWg@217.23.6.161:9999'
} }
FR_PROXY_MOB_OXY_STICKY = { FR_PROXY_MOB_OXY_STICKY = {
'http': 'http://customer-rendezvousmob-cc-fr-sessid-0{}-sesstime-2:Rdv+202220212023@pr.oxylabs.io:7777', 'http': 'http://customer-rendezvousmob-cc-FR:Rdv202220212023@fr-pr.oxylabs.io:{}',
'https': 'http://customer-rendezvousmob-cc-fr-sessid-0{}-sesstime-2:Rdv+202220212023@pr.oxylabs.io:7777' 'https': 'http://customer-rendezvousmob-cc-FR:Rdv202220212023@fr-pr.oxylabs.io:{}'
} }
FR_PROXY_DATA_IMPULSE_STICKY = { FR_PROXY_DATA_IMPULSE_STICKY = {
@@ -52,18 +42,16 @@ FR_MOBILE_ANY_IP_STICKY = {
'http': 'http://user_6a7f21,type_mobile,country_FR,session_{}:d5c051@portal.anyip.io:1080', 'http': 'http://user_6a7f21,type_mobile,country_FR,session_{}:d5c051@portal.anyip.io:1080',
'https': 'http://user_6a7f21,type_mobile,country_FR,session_{}:d5c051@portal.anyip.io:1080', 'https': 'http://user_6a7f21,type_mobile,country_FR,session_{}:d5c051@portal.anyip.io:1080',
} }
FR_MOBILE_ANY_IP_ROTATING = { # 八分之一用data_impulse
'http': 'http://user_6a7f21,type_residential,country_FR:d5c051@portal.anyip.io:1080', MOBILE_PROXY_LIST = [FR_PROXY_MOB_OXY_STICKY, FR_PROXY_MOB_OXY_STICKY, FR_PROXY_MOB_OXY_STICKY, FR_PROXY_MOB_OXY_STICKY,
'https': 'http://user_6a7f21,type_residential,country_FR:d5c051@portal.anyip.io:1080', FR_PROXY_MOB_OXY_STICKY, FR_MOBILE_ANY_IP_STICKY, FR_MOBILE_ANY_IP_STICKY, FR_MOBILE_ANY_IP_STICKY,
} FR_MOBILE_ANY_IP_STICKY, FR_MOBILE_ANY_IP_STICKY,
FR_RES_IP_ROYAL_ROTATING = { FR_PROXY_RES_OXY_STICKY,
'http': 'http://Uv2qfG3PyhT6Wctw:V45HOlzAIssCYssJ_country-fr@geo.iproyal.com:12321', FR_PROXY_DATA_IMPULSE_STICKY]
'https': 'http://Uv2qfG3PyhT6Wctw:V45HOlzAIssCYssJ_country-fr@geo.iproyal.com:12321',
} # MOBILE_PROXY_LIST = [FR_MOBILE_ANY_IP_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_MOBILE_ANY_IP_STICKY] # MOBILE_PROXY_LIST = [FR_MOBILE_ANY_IP_STICKY]
@@ -73,31 +61,22 @@ class ProxyManager:
self.logger = logger self.logger = logger
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] if len(links_to_validate) > 15:
# return [FR_MOBILE_ANY_IP_ROTATING] return [FR_PROXY_RES_OXY, FR_PROXY_MOB_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES]
return [FR_RES_IP_ROYAL_ROTATING] # return [FR_PROXY_RES_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES, FR_ASOCKS_MOBILE_PROXY]
# return [FR_PROXY_RES_OXY] else:
def get_random_sticky_iproyal_proxy(self) -> dict: return [FR_PROXY_RES_OXY, FR_PROXY_MOB_OXY, FR_PROXY_ASOCK_RES_2, FR_DATA_IMPULSE_RES]
_session_info = random.choice(FR_IPROYAL_STICKY_PROXY_LIST) # return [FR_PROXY_RES_OXY]
_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")
_port = random.randint(900000000, 995869818) _port = random.randint(40001, 49999)
elif "anyip" in _chosen_proxy["http"]: elif "anyip" in _chosen_proxy["http"]:
self.logger.info("use anyip proxy") self.logger.info("use anyip proxy")
_port = random.randint(40001, 49999) _port = random.randint(40001, 49999)
@@ -109,16 +88,3 @@ class ProxyManager:
_proxy_to_use["http"] = _chosen_proxy["http"].format(_port) _proxy_to_use["http"] = _chosen_proxy["http"].format(_port)
_proxy_to_use["https"] = _chosen_proxy["https"].format(_port) _proxy_to_use["https"] = _chosen_proxy["https"].format(_port)
return _proxy_to_use return _proxy_to_use
if __name__ == '__main__':
_logger = logging.getLogger()
_proxy = ProxyManager(logger=_logger)
# _proxise = _proxy.get_random_sticky_iproyal_proxy()
# _proxise = _proxy.get_proxy_for_appointment_request()
_proxise = _proxy.get_link_validate_proxy([])[0]
print(_proxise)
response = requests.get(
"https://ip.oxylabs.io/location",
proxies=_proxise)
print(response.content)
+1 -5
View File
@@ -31,14 +31,10 @@ class CookiesPublisher:
self.queue_method = self.channel.queue_declare(queue=self.to_queue, durable=True) self.queue_method = self.channel.queue_declare(queue=self.to_queue, durable=True)
def publish_body(self, body: str): def publish_body(self, body: str):
print("will push to queue {}".format(body)) print("will push to queue {}".format(self.to_queue))
self.channel.basic_publish(exchange='', routing_key=self.to_queue, body=body, properties=pika.BasicProperties( self.channel.basic_publish(exchange='', routing_key=self.to_queue, body=body, properties=pika.BasicProperties(
delivery_mode=pika.spec.PERSISTENT_DELIVERY_MODE delivery_mode=pika.spec.PERSISTENT_DELIVERY_MODE
)) ))
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
+23 -58
View File
@@ -3,8 +3,6 @@ import json
import random import random
import threading import threading
import time import time
from http.cookies import SimpleCookie
from typing import Optional
import pika import pika
@@ -64,24 +62,6 @@ def is_open():
return is_time_between(datetime.time(10, 30), datetime.time(19, 00)) return is_time_between(datetime.time(10, 30), datetime.time(19, 00))
def check_ms_mails(_mail_list_filtered):
print("check_ms_mails() called.")
# check_all_need_to_check_emails()
# for _mail in _mail_list_filtered:
# if "outlook.com" in _mail.mail or "hotmail.com" in _mail.mail:
# check_mail(_mail.mail)
def get_xsfr_token_from_cookies(cookies_str: str) -> Optional[str]:
_simple_cookies = SimpleCookie()
_simple_cookies.load(cookies_str)
if "x-xsrf-token" not in _simple_cookies:
return None
else:
_xsfr_token = _simple_cookies["x-xsrf-token"].value
return _xsfr_token
class AppointmentRequestSender(threading.Thread): class AppointmentRequestSender(threading.Thread):
def __init__(self, sub_contact_list: list, logger, cookiesPublisher: CookiesPublisher, def __init__(self, sub_contact_list: list, logger, cookiesPublisher: CookiesPublisher,
bakeUpCookiesPublisher: CookiesPublisher, bakeUpCookiesPublisher: CookiesPublisher,
@@ -121,8 +101,8 @@ class AppointmentRequestSender(threading.Thread):
_received_object = body.decode("UTF-8") _received_object = body.decode("UTF-8")
self.logger.info(f" [x] Received {_received_object}") self.logger.info(f" [x] Received {_received_object}")
# 同一个COOKIES保持用同一个IP # 同一个COOKIES保持用同一个IP
# _proxy_to_use = self.proxy_manager.get_proxy_for_appointment_request() _proxy_to_use = self.proxy_manager.get_proxy_for_appointment_request()
# print("proxy to use is {}".format(_proxy_to_use)) print("proxy to use is {}".format(_proxy_to_use))
if "glrd" in _received_object: if "glrd" in _received_object:
_received_dict = json.loads(_received_object) _received_dict = json.loads(_received_object)
js_data = JsDataPojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'], hc=_received_dict['hc'], js_data = JsDataPojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'], hc=_received_dict['hc'],
@@ -130,18 +110,9 @@ 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'], rs_h=_received_dict['rs_h'], ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'],
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'], rs_h=_received_dict['rs_h'],
bchk=_received_dict['bchk'], rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'])
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)
@@ -153,8 +124,8 @@ class AppointmentRequestSender(threading.Thread):
# self.contact_list = filter_contacts(self.contact_list) # self.contact_list = filter_contacts(self.contact_list)
can_continue = None can_continue = None
for con in self.contact_list: for con in self.contact_list:
_proxy_to_use = self.proxy_manager.get_proxy_for_appointment_request() # _proxy_to_use = self.proxy_manager.get_proxy_for_appointment_request()
print(_proxy_to_use) # print(_proxy_to_use)
sender = Sender(_received_cookies, cookiesPublisher=self.cookiesPublisher, sender = Sender(_received_cookies, cookiesPublisher=self.cookiesPublisher,
received_dict=_received_dict, received_dict=_received_dict,
proxy_to_use=_proxy_to_use, logger=self.logger) proxy_to_use=_proxy_to_use, logger=self.logger)
@@ -186,25 +157,21 @@ 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'], hc=_received_dict['hc'], js_le_data = JsDataLeTypePojo(glrd=_received_dict['glrd'], glvd=_received_dict['glvd'],
ua=_received_dict['ua'], br_oh=_received_dict['br_oh'], br_ow=_received_dict['br_ow'], hc=_received_dict['hc'],
ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'], pr=_received_dict['pr'], ua=_received_dict['ua'], br_oh=_received_dict['br_oh'],
plg=_received_dict['plg'], br_h=_received_dict['br_h'], br_w=_received_dict['br_w'], br_ow=_received_dict['br_ow'],
plu=_received_dict['plu'], vnd=_received_dict['vnd'], dvm=_received_dict['dvm'], ars_h=_received_dict['ars_h'], ars_w=_received_dict['ars_w'],
ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'], rs_h=_received_dict['rs_h'], pr=_received_dict['pr'],
rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'], emd=_received_dict['emd'], plg=_received_dict['plg'], br_h=_received_dict['br_h'],
bchk=_received_dict['bchk'], br_w=_received_dict['br_w'],
ccsB=_received_dict['ccsB'], plu=_received_dict['plu'], vnd=_received_dict['vnd'],
nt_tcp=_received_dict['nt_tcp'], dvm=_received_dict['dvm'],
nt_dns=_received_dict['nt_dns'], ts_mtp=_received_dict['ts_mtp'], eva=_received_dict['eva'],
nt_rd=_received_dict['nt_rd'], nt_irt=_received_dict['nt_irt'], nt_rt=_received_dict['nt_rt'], rs_h=_received_dict['rs_h'],
nt_tls=_received_dict['nt_tls'], nt_ttf=_received_dict['nt_ttf'], nt_swt=_received_dict['nt_swt'], rs_w=_received_dict['rs_w'], rs_cd=_received_dict['rs_cd'],
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) m_cm_r=m_cm_r, m_ms_r=m_ms_r, emd=_received_dict['emd'])
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,
@@ -246,9 +213,9 @@ class AppointmentRequestSender(threading.Thread):
# 如果在发送请求时出现csrf被拦截的情况,那么就需要重新发布cookie以目前的队列中,因为这个cookie可能重新利用 # 如果在发送请求时出现csrf被拦截的情况,那么就需要重新发布cookie以目前的队列中,因为这个cookie可能重新利用
self.logger.info("csrf blocked, will republish cookie") self.logger.info("csrf blocked, will republish cookie")
self.cookiesPublisher.publish_body(_received_object) self.cookiesPublisher.publish_body(_received_object)
self.logger.info("csrf blocked, will wait 60 seconds")
time.sleep(60)
ch.basic_ack(delivery_tag=method.delivery_tag) ch.basic_ack(delivery_tag=method.delivery_tag)
self.logger.info("csrf blocked, will wait 30 seconds")
time.sleep(30)
elif can_continue is not None and can_continue == RequestResult.BLOCKED: elif can_continue is not None and can_continue == RequestResult.BLOCKED:
self.logger.info("这个cookies可以给点链接用") self.logger.info("这个cookies可以给点链接用")
self.bakeUpCookiesPublisher.publish_body(_received_object) self.bakeUpCookiesPublisher.publish_body(_received_object)
@@ -272,7 +239,6 @@ class AppointmentRequestSender(threading.Thread):
self.channel.start_consuming() self.channel.start_consuming()
def retrieve_invalidate_urls(self): def retrieve_invalidate_urls(self):
self.list_to_retrieve_mails = self.initial_contact_list
# 如果没有已读邮件,而且需要读邮件的联系人表不为空,就读取未读邮件 # 如果没有已读邮件,而且需要读邮件的联系人表不为空,就读取未读邮件
if not self.already_read_emails and len(self.list_to_retrieve_mails) > 0: if not self.already_read_emails and len(self.list_to_retrieve_mails) > 0:
self.logger.info("will retrieve validate urls") self.logger.info("will retrieve validate urls")
@@ -285,7 +251,6 @@ class AppointmentRequestSender(threading.Thread):
self.logger.info("will get mail from " + mail.mail) self.logger.info("will get mail from " + mail.mail)
_mail_list_filtered.append(mail) _mail_list_filtered.append(mail)
self.logger.info("will call find_links_to_validate_from_mail_list, size = " + str(len(_mail_list_filtered))) self.logger.info("will call find_links_to_validate_from_mail_list, size = " + str(len(_mail_list_filtered)))
check_ms_mails(_mail_list_filtered)
find_links_to_validate_from_mail_list(_mail_list_filtered, self.logger) find_links_to_validate_from_mail_list(_mail_list_filtered, self.logger)
self.already_read_emails = True self.already_read_emails = True
else: else:
+221
View File
@@ -0,0 +1,221 @@
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")
+48 -77
View File
@@ -1,40 +1,54 @@
import datetime
import logging import logging
import random
import sys import sys
from threading import Thread from threading import Thread
from db.mongo_manager import MONGO_STORE_MANAGER from db.mongo_manager import MONGO_STORE_MANAGER
from excel_reader import read_contacts from excel_reader import read_contacts
from models.contact_pojo import ContactPojo from models.contact_pojo import ContactPojo
from queue_message.CookiesPublisher import CookiesPublisher, SHARED_OBJECT, TEST_QUEUE, MORNING_DATA_CACHE, \ from queue_message.CookiesPublisher import CookiesPublisher, SHARED_OBJECT, TEST_QUEUE, MORNING_DATA_CACHE_2, \
MORNING_DATA_CACHE_2, MORNING_DATA_CACHE_BAK MORNING_DATA_CACHE
from queue_message.appointmentrequestsender import AppointmentRequestSender from queue_message.appointmentrequestsender import AppointmentRequestSender
from utiles import is_time_between
from utils.AppLogging import init_logger 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: def filter_contacts(_contact_list: list) -> list:
already_sent_contacts = MONGO_STORE_MANAGER.get_all_successful_items_for_day() already_sent_contacts = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
_link_to_validate_list = MONGO_STORE_MANAGER.get_links_to_validate() _link_to_validate_list = MONGO_STORE_MANAGER.get_links_to_validate()
# Optimization: Use sets for O(1) lookup complexity
sent_emails = {booked.email for booked in already_sent_contacts}
validate_emails = {link.email for link in _link_to_validate_list}
_contact_list_to_book = [] _contact_list_to_book = []
for contact in _contact_list: for contact in _contact_list:
if contact.mail in sent_emails: _to_add = True
continue for booked in already_sent_contacts:
if contact.mail == booked.email:
_to_add = False
# 如果已经收到链接了,就不要再请求 # 如果已经收到链接了,就不要再请求
if contact.mail in validate_emails: for link_to_validate in _link_to_validate_list:
logger.info("{}: link already received".format(contact.mail)) if contact.mail == link_to_validate.email:
continue logger.info("{}: link already received".format(contact.mail))
_to_add = False
_contact_list_to_book.append(contact) if _to_add:
_contact_list_to_book.append(contact)
return _contact_list_to_book return _contact_list_to_book
def is_open():
return is_time_between(datetime.time(10, 30), datetime.time(19, 00))
count = 0 count = 0
init_logger() init_logger()
logger = logging.getLogger() logger = logging.getLogger()
@@ -42,79 +56,36 @@ logger = logging.getLogger()
logger.addHandler(logging.StreamHandler(stream=sys.stdout)) logger.addHandler(logging.StreamHandler(stream=sys.stdout))
def send_appointment_request(message_queue_name, _contact_list, stop_at_hour=11, stop_at_mins=30): def send_appointment_request(message_queue_name, _contact_list):
global count global count
count = count + 1 count = count + 1
for _contact in _contact_list: for _contact in _contact_list:
logger.info(_contact) logger.info(_contact)
_cookiesPublisher = CookiesPublisher(queue_name=message_queue_name) _cookiesPublisher = CookiesPublisher(queue_name=message_queue_name)
_cookiesPublisher.set_up_connection() _cookiesPublisher.set_up_connection()
_backUp_cookiesPublisher = CookiesPublisher(queue_name=MORNING_DATA_CACHE_BAK) receiver = AppointmentRequestSender(sub_contact_list=_contact_list, queue_name=message_queue_name,
_backUp_cookiesPublisher.set_up_connection() cookiesPublisher=_cookiesPublisher, logger=logger)
receiver = AppointmentRequestSender(sub_contact_list=_contact_list,
queue_name=message_queue_name,
cookiesPublisher=_cookiesPublisher,
bakeUpCookiesPublisher=_backUp_cookiesPublisher, logger=logger,
stop_at_hour=stop_at_hour, stop_at_mins=stop_at_mins)
print("count is " + str(count)) print("count is " + str(count))
receiver.run() receiver.run()
def start_send_requests(thread_number, contact_list, data_queue_name=MORNING_DATA_CACHE, stop_at_hour=14, def start_send_requests():
stop_at_mins=56):
print("start send requests") print("start send requests")
_contact_list_to_book = filter_contacts(contact_list) contacts_file_path = '~/Desktop/11_05_to_test.xlsx'
_segment_number = thread_number _contact_list = read_contacts(contacts_file_path)[:-1]
total_contacts = len(_contact_list_to_book) _contact_list_to_book = filter_contacts(_contact_list)
logger.info("{} contacts to book".format(total_contacts)) _segment_number = 5
logger.info("{} contacts to book".format(len(_contact_list_to_book)))
if total_contacts == 0: last_thread = None
return for i in range(0, _segment_number):
# Optimization: Better distribution of contacts among threads
thread_list = []
chunk_size = total_contacts // _segment_number
remainder = total_contacts % _segment_number
start_index = 0
for i in range(_segment_number):
# If we have more threads than contacts, some threads will get empty lists, which is fine
if start_index >= total_contacts:
break
logger.info("segment is {}".format(i)) logger.info("segment is {}".format(i))
_step = int(len(_contact_list_to_book) / _segment_number)
# Distribute remainder to the first few threads _sublist = _contact_list_to_book[i * _step:_step * (i + 1)]
current_chunk_size = chunk_size + (1 if i < remainder else 0) _thread1 = Thread(target=send_appointment_request, args=(MORNING_DATA_CACHE, _sublist))
end_index = start_index + current_chunk_size last_thread = _thread1
_thread1.start()
_sublist = _contact_list_to_book[start_index:end_index] last_thread.join()
start_index = end_index
if _sublist:
_thread1 = Thread(target=send_appointment_request, args=(data_queue_name, _sublist, stop_at_hour, stop_at_mins))
thread_list.append(_thread1)
_thread1.start()
for _thread in thread_list:
_thread.join()
def send_request_for_file_list(file_list: list, thread_number: int = 20, data_queue_name=MORNING_DATA_CACHE,
stop_at_hour=11, stop_at_mins=30):
logger.info("stop_at_hour is " + str(stop_at_hour) + " stop_at_mins is " + str(stop_at_mins))
for _file_path in file_list:
logger.info("send request for file: " + _file_path)
_contact_list = read_contacts(_file_path)
random.shuffle(_contact_list)
start_send_requests(thread_number=thread_number, contact_list=_contact_list,
data_queue_name=data_queue_name, stop_at_hour=stop_at_hour, stop_at_mins=stop_at_mins)
if __name__ == '__main__': if __name__ == '__main__':
# file_list = ['~/Desktop/contact_list_2024-05-23.xlsx', start_send_requests()
# '~/Desktop/contact_list_2024-05-21.xlsx',
# file_list = ['~/Desktop/contact_list_2025-10-30.xlsx']
file_list = ['~/Desktop/contact_list_2025-11-28.xlsx']
send_request_for_file_list(file_list=file_list, thread_number=10,
data_queue_name=MORNING_DATA_CACHE_2, stop_at_hour=19, stop_at_mins=50)
+108
View File
@@ -0,0 +1,108 @@
import datetime
import logging
import random
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, MORNING_DATA_CACHE, \
MORNING_DATA_CACHE_2, MORNING_DATA_CACHE_BAK
from queue_message.appointmentrequestsender import AppointmentRequestSender
from utiles import is_time_between
from utils.AppLogging import init_logger
from workers.proxies_constants import MOBILE_PROXY_LIST_FR
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
count = 0
init_logger()
logger = logging.getLogger()
logger.addHandler(logging.StreamHandler(stream=sys.stdout))
def send_appointment_request(message_queue_name, _contact_list, stop_at_hour=11, stop_at_mins=30):
global count
count = count + 1
for _contact in _contact_list:
logger.info(_contact)
_cookiesPublisher = CookiesPublisher(queue_name=message_queue_name)
_cookiesPublisher.set_up_connection()
_backUp_cookiesPublisher = CookiesPublisher(queue_name=MORNING_DATA_CACHE_BAK)
_backUp_cookiesPublisher.set_up_connection()
receiver = AppointmentRequestSender(sub_contact_list=_contact_list,
queue_name=message_queue_name,
cookiesPublisher=_cookiesPublisher,
bakeUpCookiesPublisher=_backUp_cookiesPublisher, logger=logger,
stop_at_hour=stop_at_hour, stop_at_mins=stop_at_mins)
print("count is " + str(count))
receiver.run()
def start_send_requests(thread_number, contact_list, data_queue_name=MORNING_DATA_CACHE, stop_at_hour=14,
stop_at_mins=56):
print("start send requests")
_contact_list_to_book = filter_contacts(contact_list)
_segment_number = thread_number
logger.info("{} contacts to book".format(len(_contact_list_to_book)))
# last_thread = None
thread_list = []
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=(data_queue_name, _sublist, stop_at_hour, stop_at_mins))
thread_list.append(_thread1)
_thread1.start()
for _thread in thread_list:
_thread.join()
def send_request_for_file_list(file_list: list, thread_number: int = 20, data_queue_name=MORNING_DATA_CACHE,
stop_at_hour=11, stop_at_mins=30):
logger.info("stop_at_hour is " + str(stop_at_hour) + " stop_at_mins is " + str(stop_at_mins))
for _file_path in file_list:
logger.info("send request for file: " + _file_path)
_contact_list = read_contacts(_file_path)
random.shuffle(_contact_list)
start_send_requests(thread_number=thread_number, contact_list=_contact_list,
data_queue_name=data_queue_name, stop_at_hour=stop_at_hour, stop_at_mins=stop_at_mins)
if __name__ == '__main__':
# file_list = ['~/Desktop/contact_list_2024-05-23.xlsx',
# '~/Desktop/contact_list_2024-05-21.xlsx',
# '~/Desktop/15_05_to_test.xlsx']
# file_list = ['~/Desktop/15_05_to_test.xlsx', '~/Desktop/16_05_to_test.xlsx']
file_list = ['~/Desktop/contact_list_all.xlsx']
send_request_for_file_list(file_list=file_list, thread_number=1,
data_queue_name=MORNING_DATA_CACHE, stop_at_hour=18, stop_at_mins=30)
-5
View File
@@ -1,5 +0,0 @@
APScheduler==3.10.4
curl_cffi==0.7.1
openpyxl
pika
schedule
-26
View File
@@ -1,26 +0,0 @@
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()

Some files were not shown because too many files have changed in this diff Show More