您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Checks the last online on page user and in dialog
当前为
// ==UserScript== // @name VK: Check Online // @name:ru ВК: Проверка онлайна // @description Checks the last online on page user and in dialog // @description:ru Проверяет последний онлайн пользователя на странице и в диалогe // @namespace vk-check-online.user.js // @license MIT // @author askornot // @version 1.0.6 // @match https://vk.com/* // @connect vk.com // @compatible chrome Violentmonkey 2.12.7 // @compatible firefox Violentmonkey 2.12.7 // @homepageURL https://greasyfork.org/en/scripts/403717-vk-check-online // @supportURL https://greasyfork.org/en/scripts/403717-vk-check-online/feedback // @run-at document-end // @noframes // ==/UserScript== 'use strict'; const USERS = new Map(); const DEFAULT = { uts: 0, expires: 0 }; const ONE_MINUTE = 60 * 1000; const UNIX_TIME = 1000; const request = (url, callback) => { const xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { const container = document.implementation.createHTMLDocument() .documentElement; if (xhr.status === 0 || xhr.status === 200) { container.innerHTML = xhr.responseText; } callback(container); } }; xhr.open('GET', url, true); xhr.send(); }; const render = (uts) => { const online = document.querySelector('.mail_box_label_info') || document.querySelector('.profile_online_lv') || document.querySelector('._im_page_peer_online'); const { lang } = window.vk; const text = lang === 3 ? 'last seen' : 'заходил(а)'; online.textContent = `${text} ${window.getDateText(uts, null)}`; }; const extractTimestamp = (body) => { const [ element ] = body.getElementsByTagName('ya:lastloggedin'); if (!element) return 0; const date = element.getAttribute('dc:date'); const uts = Math.floor(Date.parse(date) / UNIX_TIME); return uts; }; const extractUserId = () => { const { options, peer } = window.cur; const id = peer || (options && options.user_id); return id || 0; }; const getUser = (user) => (USERS.has(user) ? USERS.get(user) : DEFAULT); const setUser = (user, uts) => USERS.set(user, { uts, expires: Date.now() + ONE_MINUTE }); const start = () => { const userId = extractUserId(); if (userId === 0 || Math.sign(userId) === -1) return; const user = getUser(userId); if (user.expires > Date.now()) { render(user.uts); return; } request(`/foaf.php?id=${userId}`, (body) => { const uts = extractTimestamp(body); if (uts === 0) return; render(uts); setUser(userId, uts); }); }; start(); const filterMutsByClassName = (muts) => { return muts.filter( (array, i, self) => self.findIndex( (_array) => array.target.className === _array.target.className ) === i ); }; new MutationObserver((muts) => { muts = filterMutsByClassName(muts); for (const { target, addedNodes } of muts) { const { tagName } = target; if (tagName === 'DIV' || tagName === 'SPAN') { const { classList } = target; if ( (classList.contains('wide_column') && addedNodes.length >= 2) || classList.contains('box_body') || classList.contains('_im_page_peer_online') || classList.contains('im-page-chat-contain') ) { setTimeout(start, 1000); } } } }).observe(document.body || document, { childList: true, subtree: true, });