Greasy Fork is available in English.
Checks the last online on page user and in dialog
当前为
/* globals vk, cur, getDateText, GM, GM_xmlhttpRequest */
/* eslint padded-blocks: ["error", { "blocks": "always" }]
object-curly-spacing: ["error", "always", { "objectsInObjects": false }]
curly: ["error", "multi"] */
// ==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.5
// @match https://vk.com/*
// @connect vk.com
// @compatible chrome Violentmonkey 2.12.7
// @compatible firefox Violentmonkey 2.12.7
// @homepageURL http://greasyfork.icu/en/scripts/403717-vk-check-online
// @supportURL http://greasyfork.icu/en/scripts/403717-vk-check-online/feedback
// @grant GM_xmlhttpRequest
// @grant GM.xmlHttpRequest
// @run-at document-end
// @noframes
// ==/UserScript==
'use strict';
const USERS = new Map();
const request = (id, data = {}) => new Promise((resolve, reject) => {
data.method = 'GET';
data.url = `/foaf.php?id=${id}`;
/* eslint-disable unicorn/prefer-add-event-listener, no-unused-expressions, no-constant-condition, operator-linebreak, new-cap */
data.onload = r => {
const container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = r.responseText;
resolve(container);
};
data.onerror = reject;
typeof !GM && typeof !GM.xmlHttpRequest
? GM.xmlHttpRequest(data)
: GM_xmlhttpRequest(data);
/* eslint-enable */
});
const floor = time => Math.floor(time);
const now = () => (floor(Date.now()));
const render = uts => {
const online = document.querySelector('.mail_box_label_info') ||
document.querySelector('.profile_online_lv') ||
document.querySelector('._im_page_peer_online');
const { lang } = vk;
const text = lang === 3 ? 'last seen' : 'заходил(а)';
online.textContent = `${text} ${getDateText(uts, null)}`;
};
const getTs = body => {
// eslint-disable-next-line unicorn/prefer-query-selector
const [element] = body.getElementsByTagName('ya:lastloggedin');
if (!element) return 0;
const date = element.getAttribute('dc:date');
const uts = floor(Date.parse(date) / 1000); // A getDateText requires unixtime
return uts;
};
const getUser = user => USERS.has(user) ? USERS.get(user) : {};
const start = async () => {
const { options = {}, peer } = cur; // VK object
// eslint-disable-next-line no-prototype-builtins
const userId = (peer ? peer : (options.hasOwnProperty('user_id') ? options.user_id : 0));
if (userId === 0 || Math.sign(userId) === -1) return;
let { expires = 0, uts = 0 } = getUser(userId);
if (expires < now()) { // eslint-disable-line curly
try {
const body = await request(userId);
uts = getTs(body);
USERS.set(userId, {
uts,
expires: now() + 60000 // Every one minute
});
} catch (error) {
console.error(error.stack);
}
}
if (uts === 0) return;
render(uts);
};
start().catch(console.error);
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 ( // eslint-disable-line curly
(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
});