Преглед на файлове

fix 兼容奈飞获取验证码

zoujiajian преди 2 седмици
родител
ревизия
823c477cd3
променени са 1 файла, в които са добавени 54 реда и са изтрити 14 реда
  1. 54 14
      netflix-service/src/main/java/com/cyksj/service/mail/impl/CommonMailServiceImpl.java

+ 54 - 14
netflix-service/src/main/java/com/cyksj/service/mail/impl/CommonMailServiceImpl.java

@@ -40,6 +40,9 @@ import java.util.regex.Pattern;
 @RequiredArgsConstructor
 @Slf4j
 public class CommonMailServiceImpl implements CommonMailService {
+	private static final String LQQQ_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36";
+	private static final String LQQQ_ACCEPT_LANGUAGE = "zh-CN,zh;q=0.9,en;q=0.8";
+
 	private final CuiQiuMailService cuiQiuMailService;
 
 	private final MailLuService mailLuService;
@@ -124,12 +127,12 @@ public class CommonMailServiceImpl implements CommonMailService {
 				|| (linkType == 1 && Boolean.TRUE.equals(isReturnDeviceUrl)))) {
 			try {
 				String url = "https://ms.lqqq.cc/web/" + account + "----" + emailPwd;
-				HttpRequest post = HttpUtil.createGet(url).timeout(Constant.CONNECT_MILLISECONDS);
+				HttpRequest post = createLqqqRequest(url, null);
 				HttpResponse execute = post.execute();
 				String body = execute.body();
 				String code = linkType != null && linkType == 1
-						? getNetflixHouseholdDeviceUrlByLqqqMail(account, body)
-						: getNetflixVerifyCodeByLqqqMail(account, body);
+						? getNetflixHouseholdDeviceUrlByLqqqMail(account, body, url)
+						: getNetflixVerifyCodeByLqqqMail(account, body, url);
 				if (StrUtil.isNotBlank(code)) {
 					return code;
 				}
@@ -151,7 +154,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 		return yhMailService.getVerifyCode(account, relateEmail, goodsId, type, linkType, Boolean.TRUE.equals(isReturnDeviceUrl));
 	}
 
-	private String getNetflixVerifyCodeByLqqqMail(String account, String body) {
+	private String getNetflixVerifyCodeByLqqqMail(String account, String body, String mailboxUrl) {
 		if (StrUtil.isBlank(body)) {
 			return StrUtil.EMPTY;
 		}
@@ -160,7 +163,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 		}
 		Matcher matcher = Pattern.compile("<a\\b[^>]*href=\"([^\"]*/show_email/[^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE).matcher(body);
 		while (matcher.find()) {
-			String href = matcher.group(1);
+				String href = decodeHtmlEntities(matcher.group(1));
 			String emailItem = getMailListItemHtml(body, matcher.start());
 			if (!emailItem.contains(Constant.NETFLIX) || !isNetflixLoginCodeMail(emailItem)) {
 				continue;
@@ -172,7 +175,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 			}
 			try {
 				String detailUrl = href.startsWith("http") ? href : "https://ms.lqqq.cc" + href;
-				HttpResponse detailResp = HttpUtil.createGet(detailUrl).timeout(Constant.CONNECT_MILLISECONDS).execute();
+				HttpResponse detailResp = createLqqqRequest(detailUrl, mailboxUrl).execute();
 				code = getNetflixVerifyCode(detailResp.body());
 				if (StrUtil.isNotBlank(code)) {
 					log.info("Netflix {} get verify code from lqqq mail detail: {}", account, code);
@@ -185,7 +188,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 		return StrUtil.EMPTY;
 	}
 
-	private String getNetflixHouseholdDeviceUrlByLqqqMail(String account, String body) {
+	private String getNetflixHouseholdDeviceUrlByLqqqMail(String account, String body, String mailboxUrl) {
 		if (StrUtil.isBlank(body)) {
 			return StrUtil.EMPTY;
 		}
@@ -202,7 +205,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 			try {
 				String href = decodeHtmlUrl(matcher.group(1));
 				String detailUrl = href.startsWith("http") ? href : "https://ms.lqqq.cc" + href;
-				HttpResponse detailResp = HttpUtil.createGet(detailUrl).timeout(Constant.CONNECT_MILLISECONDS).execute();
+				HttpResponse detailResp = createLqqqRequest(detailUrl, mailboxUrl).execute();
 				url = getNetflixHouseholdDeviceUrl(detailResp.body());
 				if (StrUtil.isNotBlank(url)) {
 					log.info("Netflix {} get household device url from lqqq mail detail", account);
@@ -238,6 +241,17 @@ public class CommonMailServiceImpl implements CommonMailService {
 		return StrUtil.EMPTY;
 	}
 
+	private HttpRequest createLqqqRequest(String url, String referer) {
+		HttpRequest request = HttpUtil.createGet(url)
+				.timeout(Constant.CONNECT_MILLISECONDS)
+				.header("User-Agent", LQQQ_USER_AGENT)
+				.header("Accept-Language", LQQQ_ACCEPT_LANGUAGE);
+		if (StrUtil.isNotBlank(referer)) {
+			request.header("Referer", referer);
+		}
+		return request;
+	}
+
 	private String decodeHtmlUrl(String url) {
 		return StrUtil.blankToDefault(url, StrUtil.EMPTY)
 				.replace("&amp;", "&")
@@ -276,7 +290,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 		};
 		for (String startStr : startStrs) {
 			if (text.contains(startStr)) {
-				String verifyCode = getNetflixCodePattern(StrUtil.subAfter(text, startStr, false));
+				String verifyCode = getNetflixCodePattern(StrUtil.subAfter(text, startStr, true));
 				if (StrUtil.isNotBlank(verifyCode)) {
 					return verifyCode;
 				}
@@ -299,6 +313,7 @@ public class CommonMailServiceImpl implements CommonMailService {
 		if (StrUtil.isBlank(body)) {
 			return StrUtil.EMPTY;
 		}
+		body = decodeHtmlEntities(body);
 		String code = getNetflixCodeFromHtml(body);
 		if (StrUtil.isNotBlank(code)) {
 			return code;
@@ -311,7 +326,8 @@ public class CommonMailServiceImpl implements CommonMailService {
 		};
 		for (String startStr : startStrs) {
 			if (body.contains(startStr)) {
-				code = cleanMailHtml(StrUtil.subAfter(body, startStr, false));
+				// Netflix 邮件会先放一段隐藏预览,再出现真实正文标题;从最后一个标题开始解析,避免命中预览后的 CSS 数字。
+				code = cleanMailHtml(StrUtil.subAfter(body, startStr, true));
 				String verifyCode = getNetflixCodePattern(code);
 				if (StrUtil.isNotBlank(verifyCode)) {
 					return verifyCode;
@@ -322,9 +338,11 @@ public class CommonMailServiceImpl implements CommonMailService {
 	}
 
 	private String getNetflixCodeFromHtml(String body) {
-		Matcher matcher = Pattern.compile("<td\\b[^>]*(?:font-size\\s*:\\s*28px|letter-spacing\\s*:\\s*6px)[^>]*>\\s*([0-9\\s]{4,30})\\s*</td>", Pattern.CASE_INSENSITIVE).matcher(body);
+		Matcher matcher = Pattern.compile(
+				"<(td|div|span)\\b(?=[^>]*(?:class\\s*=\\s*[\\\"'][^\\\"']*lrg-number[^\\\"']*[\\\"']|letter-spacing\\s*:\\s*6px))[^>]*>\\s*([0-9\\s]{4,30})\\s*</\\1>",
+				Pattern.CASE_INSENSITIVE).matcher(body);
 		while (matcher.find()) {
-			String code = matcher.group(1).replaceAll("\\D", "");
+			String code = matcher.group(2).replaceAll("\\D", "");
 			if (code.length() == 4) {
 				return code;
 			}
@@ -336,17 +354,39 @@ public class CommonMailServiceImpl implements CommonMailService {
 		if (StrUtil.isBlank(body)) {
 			return StrUtil.EMPTY;
 		}
-		return body.replaceAll("<[^>]*>", " ")
+		return decodeHtmlEntities(body).replaceAll("<[^>]*>", " ")
 				.replaceAll("(?i)&nbsp;", " ")
 				.replaceAll("(?i)&#x?[0-9a-f]+;", " ")
 				.replaceAll("(?i)#[0-9a-f]{3,6}", " ");
 	}
 
+	private String decodeHtmlEntities(String body) {
+		String decoded = body;
+		for (int i = 0; i < 3; i++) {
+			String next = decoded
+					.replaceAll("(?i)&lt;", "<")
+					.replaceAll("(?i)&gt;", ">")
+					.replaceAll("(?i)&quot;", "\"")
+					.replaceAll("(?i)&apos;", "'")
+					.replace("&#34;", "\"")
+					.replace("&#39;", "'")
+					.replace("&#x22;", "\"")
+					.replace("&#x27;", "'")
+					.replaceAll("(?i)&nbsp;", " ")
+					.replaceAll("(?i)&amp;", "&");
+			if (next.equals(decoded)) {
+				break;
+			}
+			decoded = next;
+		}
+		return decoded;
+	}
+
 	private String getNetflixCodePattern(String code) {
 		if (StrUtil.isBlank(code)) {
 			return StrUtil.EMPTY;
 		}
-		Matcher spacedMatcher = Pattern.compile("(?<!\\d)(\\d)\\D{1,8}(\\d)\\D{1,8}(\\d)\\D{1,8}(\\d)(?!\\d)").matcher(code);
+		Matcher spacedMatcher = Pattern.compile("(?<!\\d)(\\d)\\s{1,8}(\\d)\\s{1,8}(\\d)\\s{1,8}(\\d)(?!\\d)").matcher(code);
 		while (spacedMatcher.find()) {
 			return spacedMatcher.group(1) + spacedMatcher.group(2) + spacedMatcher.group(3) + spacedMatcher.group(4);
 		}