Revert Duolingo JWT friend streak implementation
This commit is contained in:
@@ -5246,17 +5246,20 @@ function argon_get_duolingo_streak() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取多邻国完整数据(包含今日是否完成)
|
// 获取多邻国完整数据(包含今日是否完成)
|
||||||
function argon_get_duolingo_data() {
|
function argon_get_duolingo_data($force_refresh = false) {
|
||||||
|
if (get_option('argon_show_duolingo_streak', 'false') != 'true') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$username = get_option('argon_duolingo_username', '');
|
$username = get_option('argon_duolingo_username', '');
|
||||||
if (empty($username)) {
|
if (empty($username)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache_key = 'argon_duolingo_v2_' . md5($username);
|
$cache_key = 'argon_duolingo_data_' . md5($username);
|
||||||
$cached = get_transient($cache_key);
|
$cached = get_transient($cache_key);
|
||||||
|
|
||||||
// 如果有缓存
|
if (!$force_refresh && $cached !== false) {
|
||||||
if ($cached !== false) {
|
|
||||||
// 如果今日已完成,直接返回缓存(到第二天0点前不会变)
|
// 如果今日已完成,直接返回缓存(到第二天0点前不会变)
|
||||||
if (isset($cached['today']) && $cached['today']) {
|
if (isset($cached['today']) && $cached['today']) {
|
||||||
// 检查是否还是同一天
|
// 检查是否还是同一天
|
||||||
@@ -5270,28 +5273,16 @@ function argon_get_duolingo_data() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = 'https://www.duolingo.com/2017-06-30/users?username=' . urlencode($username) . '&fields=id,streak,streakData%7BcurrentStreak,previousStreak%7D,quests,friendStreaks,friendships,following';
|
$url = 'https://www.duolingo.com/2017-06-30/users?username=' . urlencode($username) . '&fields=streak,streakData%7BcurrentStreak,previousStreak%7D';
|
||||||
|
|
||||||
$headers = array(
|
|
||||||
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
|
|
||||||
);
|
|
||||||
$jwt = get_option('argon_duolingo_jwt', '');
|
|
||||||
if (!empty($jwt)) {
|
|
||||||
$headers['Authorization'] = 'Bearer ' . $jwt;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = wp_remote_get($url, array(
|
$response = wp_remote_get($url, array(
|
||||||
'timeout' => 15,
|
'timeout' => 15,
|
||||||
'headers' => $headers
|
'headers' => array(
|
||||||
|
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
|
||||||
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
// 如果返回了诸如 401/403 错误,说明可能遭到了 Cloudflare 拦截或者是 JWT 无效
|
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
|
||||||
// 我们直接返回缓存,而不是剥离 JWT 去重试,因为当前服务器 IP 很可能就是被封的
|
|
||||||
if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) !== 200) {
|
|
||||||
return $cached !== false ? $cached : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_wp_error($response)) {
|
|
||||||
// 请求失败时返回旧缓存(如果有)
|
// 请求失败时返回旧缓存(如果有)
|
||||||
return $cached !== false ? $cached : false;
|
return $cached !== false ? $cached : false;
|
||||||
}
|
}
|
||||||
@@ -5317,48 +5308,10 @@ function argon_get_duolingo_data() {
|
|||||||
$end_date = isset($user['streakData']['currentStreak']['endDate']) ? $user['streakData']['currentStreak']['endDate'] : '';
|
$end_date = isset($user['streakData']['currentStreak']['endDate']) ? $user['streakData']['currentStreak']['endDate'] : '';
|
||||||
$is_today_done = ($end_date === $today);
|
$is_today_done = ($end_date === $today);
|
||||||
|
|
||||||
// 尝试解析好友连胜 (Friend Streak)
|
|
||||||
$friend_streak = 0;
|
|
||||||
|
|
||||||
// 只有在 JWT 有效时才继续拉取私密接口
|
|
||||||
if (!empty($jwt)) {
|
|
||||||
// 请求额外的好友连胜数据
|
|
||||||
$user_id = isset($user['id']) ? $user['id'] : 0;
|
|
||||||
if ($user_id) {
|
|
||||||
$friend_url = 'https://www.duolingo.com/2017-06-30/friends/users/' . $user_id . '?fields=friendStreaks';
|
|
||||||
$friend_resp = wp_remote_get($friend_url, array('timeout' => 15, 'headers' => $headers));
|
|
||||||
if (!is_wp_error($friend_resp)) {
|
|
||||||
$friend_body = wp_remote_retrieve_body($friend_resp);
|
|
||||||
$friend_data = json_decode($friend_body, true);
|
|
||||||
|
|
||||||
// 写出诊断日志以便开发者后续找字段
|
|
||||||
$debug_info = array('user_api' => $user, 'friend_api' => $friend_data);
|
|
||||||
file_put_contents(get_template_directory() . '/duolingo_debug.json', json_encode($debug_info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
|
||||||
|
|
||||||
// 暂时尝试猜测常用名字
|
|
||||||
if (isset($user['friendStreaks'])) {
|
|
||||||
// 如果是在 user 对象里
|
|
||||||
foreach ((array)$user['friendStreaks'] as $fs) {
|
|
||||||
if (isset($fs['streakLength']) && $fs['streakLength'] > $friend_streak) $friend_streak = $fs['streakLength'];
|
|
||||||
if (isset($fs['length']) && $fs['length'] > $friend_streak) $friend_streak = $fs['length'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isset($friend_data['friendStreaks'])) {
|
|
||||||
// 如果是在 friends 对象里
|
|
||||||
foreach ((array)$friend_data['friendStreaks'] as $fs) {
|
|
||||||
if (isset($fs['streakLength']) && $fs['streakLength'] > $friend_streak) $friend_streak = $fs['streakLength'];
|
|
||||||
if (isset($fs['length']) && $fs['length'] > $friend_streak) $friend_streak = $fs['length'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = array(
|
$result = array(
|
||||||
'streak' => $streak,
|
'streak' => $streak,
|
||||||
'today' => $is_today_done,
|
'today' => $is_today_done,
|
||||||
'date' => $today,
|
'date' => $today
|
||||||
'friend_streak' => $friend_streak > 0 ? $friend_streak : ''
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 如果今日已完成,缓存到明天0点;否则缓存15分钟
|
// 如果今日已完成,缓存到明天0点;否则缓存15分钟
|
||||||
|
|||||||
BIN
functions_original.php
Normal file
BIN
functions_original.php
Normal file
Binary file not shown.
18
settings.php
18
settings.php
@@ -1529,14 +1529,6 @@ function themeoptions_page(){
|
|||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
|
||||||
<th><label>Duolingo JWT Token</label></th>
|
|
||||||
<td>
|
|
||||||
<input name="argon_duolingo_jwt" type="text" class="regular-text" value="<?php echo get_option('argon_duolingo_jwt', ''); ?>" placeholder="<?php _e('手动填入抓包得到的 jwt', 'argon');?>">
|
|
||||||
<p class="description"><?php _e('在浏览器登录多邻国网页版后,按 F12 并在 Application -> Cookies 里找到 jwt 并填入,用于自动获取友情连胜数据', 'argon');?></p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr><th class="subtitle"><h2 id="section-announcement"><?php _e('博客公告', 'argon');?></h2></th></tr>
|
<tr><th class="subtitle"><h2 id="section-announcement"><?php _e('博客公告', 'argon');?></h2></th></tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
@@ -2870,9 +2862,6 @@ function themeoptions_page(){
|
|||||||
alert('✗ <?php _e('清除失败:', 'argon'); ?> ' + response.data.message);
|
alert('✗ <?php _e('清除失败:', 'argon'); ?> ' + response.data.message);
|
||||||
}
|
}
|
||||||
$btn.prop('disabled', false).html(originalHtml);
|
$btn.prop('disabled', false).html(originalHtml);
|
||||||
}).fail(function() {
|
|
||||||
alert('<?php _e('请求失败,请重试', 'argon'); ?>');
|
|
||||||
$btn.prop('disabled', false).html(originalHtml);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -6890,19 +6879,12 @@ function argon_update_themeoptions(){
|
|||||||
|
|
||||||
argon_update_option('argon_show_duolingo_streak');
|
argon_update_option('argon_show_duolingo_streak');
|
||||||
argon_update_option('argon_duolingo_username');
|
argon_update_option('argon_duolingo_username');
|
||||||
if (isset($_POST['argon_duolingo_jwt'])) {
|
|
||||||
argon_update_option('argon_duolingo_jwt');
|
|
||||||
}
|
|
||||||
delete_option('argon_duolingo_friend_streak');
|
|
||||||
|
|
||||||
// Clean up old transient and options
|
|
||||||
delete_option('argon_duolingo_email');
|
delete_option('argon_duolingo_email');
|
||||||
delete_transient('argon_duo_login_error');
|
delete_transient('argon_duo_login_error');
|
||||||
|
|
||||||
argon_update_option('argon_banner_title');
|
argon_update_option('argon_banner_title');
|
||||||
|
|
||||||
argon_update_option('argon_banner_subtitle');
|
|
||||||
|
|
||||||
argon_update_option('argon_banner_background_url');
|
argon_update_option('argon_banner_background_url');
|
||||||
|
|
||||||
argon_update_option('argon_banner_background_color_type');
|
argon_update_option('argon_banner_background_color_type');
|
||||||
|
|||||||
BIN
settings_original.php
Normal file
BIN
settings_original.php
Normal file
Binary file not shown.
@@ -664,17 +664,10 @@ $author_desc = get_option('argon_sidebar_author_description');
|
|||||||
$duo_data = argon_get_duolingo_data();
|
$duo_data = argon_get_duolingo_data();
|
||||||
if ($duo_data !== false) :
|
if ($duo_data !== false) :
|
||||||
$is_today_done = isset($duo_data['today']) && $duo_data['today'];
|
$is_today_done = isset($duo_data['today']) && $duo_data['today'];
|
||||||
$duo_friend_streak = isset($duo_data['friend_streak']) ? $duo_data['friend_streak'] : '';
|
|
||||||
$tooltip_attr = !empty($duo_friend_streak) ? ' data-toggle="tooltip" data-placement="bottom" title="' . esc_attr(sprintf(__('友情连胜: %s天', 'argon'), $duo_friend_streak)) . '"' : '';
|
|
||||||
?>
|
?>
|
||||||
<span class="duolingo-streak<?php echo $is_today_done ? '' : ' not-done'; ?>"<?php echo $tooltip_attr; ?>>
|
<span class="duolingo-streak<?php echo $is_today_done ? '' : ' not-done'; ?>">
|
||||||
<img src="<?php echo get_template_directory_uri(); ?>/assets/icons/duolingo-streak<?php echo $is_today_done ? '' : '-empty'; ?>.svg" class="duolingo-flame" alt="streak">
|
<img src="<?php echo get_template_directory_uri(); ?>/assets/icons/duolingo-streak<?php echo $is_today_done ? '' : '-empty'; ?>.svg" class="duolingo-flame" alt="streak">
|
||||||
<?php echo $duo_data['streak']; ?>
|
<?php echo $duo_data['streak']; ?>
|
||||||
</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="duolingo-streak not-done" data-toggle="tooltip" data-placement="bottom" title="<?php _e('API 获取失败 / 用户名错误 / 或被频控拦截', 'argon'); ?>">
|
|
||||||
<img src="<?php echo get_template_directory_uri(); ?>/assets/icons/duolingo-streak-empty.svg" class="duolingo-flame" alt="streak">
|
|
||||||
?
|
|
||||||
</span>
|
</span>
|
||||||
<?php endif; endif; ?>
|
<?php endif; endif; ?>
|
||||||
</h6>
|
</h6>
|
||||||
|
|||||||
Reference in New Issue
Block a user