Greasy Fork is available in English.
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.1.0
// @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
// @run-at document-end
// @noframes
// ==/UserScript==
'use strict';
const W = unsafeWindow || window;
const MINUTE = 60 * 1000;
const UNIXTIME = 1000;
class Cache {
constructor() {
this.default = { uts: 0, expires: 0 };
this.data = new Map();
}
get(key) {
const exist = this.data.get(key);
if (exist) return exist;
return this.default;
}
set(key, value) {
const expires = Date.now() + MINUTE;
this.data.set(key, { uts: value, expires });
}
}
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) / UNIXTIME);
return uts;
};
const extract = () => {
const { options, peer } = window.cur;
const id = peer || (options && options.user_id);
return id || 0;
};
const start = () => {
const id = extract();
if (id === 0 || Math.sign(id) === -1) return;
const { expires, uts } = cache.get(id);
if (expires > Date.now()) {
render(uts);
return;
}
request(`/foaf.php?id=${id}`, (body) => {
const uts = extractTimestamp(body);
if (uts === 0) return;
render(uts);
cache.set(id, uts);
});
};
const observable = (target) => {
const handlers = [];
const observe = (handler) => {
handlers.push(handler);
};
const proxy = new Proxy(target, {
get(...args) {
const output = Reflect.get(...args);
if (output) {
handlers.forEach((fn) => fn(output));
}
return output;
},
});
return [proxy, observe];
};
const throttle = (timeout, fn) => {
let timer;
let wait = false;
let wrapped = null;
const throttled = () => {
timer = undefined;
if (wait) wrapped();
};
wrapped = (...args) => {
if (!timer) {
timer = setTimeout(throttled, timeout);
wait = false;
return fn(...args);
} else {
wait = true;
}
};
return wrapped;
};
const throttledStart = throttle(3000, start);
const types = {
object: throttledStart,
};
const [instance, observe] = observable(W.nav);
W.nav = instance;
observe((data) => {
const type = typeof data;
const fn = types[type];
if (fn) fn();
});
const cache = new Cache();
throttledStart();