// ==UserScript==
// @name DTF Right Aside Redesign Edition
// @namespace ¯\_(ツ)_/¯
// @match https://dtf.ru/*
// @version 0.2.0
// @author ¯\_(ツ)_/¯
// @description ¯\_(ツ)_/¯
// @require https://cdn.socket.io/socket.io-2.3.1.js
// ==/UserScript==
(() => {
//Сортировать ли комментарии по юзерам в подписке?
//вверху списка будут юзеры, на которых подписан пользователь этого скрипта
const SORT_COMMENTS_BY_SUBSCRIPTIONS = true;
//Время обновления ленты комментариев в секундах
const UPDATE_TIME = 20;
const DEBUG = false;
const LOG_NAME = `DTF Right Aside Redesign Edition`;
const _log = DEBUG ? function(d) {
console.log(`${LOG_NAME}:`);
console.log(d);
} : ()=>{};
let last_comments = [];
let right_aside_html = '';
let aside__right__elem;
let subscriptions_user_ids = [];
async function get_subscriptions_user_ids__by_cache() {
const ts = localStorage.getItem('aside_re__get_subscriptions__last_ts');
if (!ts) return false;
if ((new Date().getTime()-parseInt(ts))>24*60*60*1000) return false;
let user_ids_string = localStorage.getItem('aside_re__get_subscriptions__user_ids');
if (!user_ids_string) return false;
let user_ids = JSON.parse(user_ids_string);
if (!user_ids) return false;
subscriptions_user_ids = user_ids;
return true;
}
async function get_subscriptions_user_ids() {
if (await get_subscriptions_user_ids__by_cache()) return;
let ls_user = localStorage.getItem('user');
if (!ls_user) return;
let user = JSON.parse(ls_user);
if (!user || !user.id) return;
const response = await fetch('https://api.dtf.ru/v2.5/subsite/subscriptions?subsiteId=' + user.id);
const response_json = await response.json();
for (let k = 0; k < response_json.result.items.length; k++) {
if (response_json.result.items[k]) {
subscriptions_user_ids.push(response_json.result.items[k].id);
}
}
localStorage.setItem('aside_re__get_subscriptions__user_ids', JSON.stringify(subscriptions_user_ids));
localStorage.setItem('aside_re__get_subscriptions__last_ts', new Date().getTime());
}
async function add_right_aside() {
if (last_comments.length === 0) return;
//удаляем комменты старше 2 минут
last_comments = last_comments.filter(last_comment => ((new Date().getTime() - last_comment.timestamp) < 120000))
//ставим приоритет по наличию юзеров в подписке и по времени
last_comments.forEach(function callback(last_comment) {
last_comment.priority = 0;
if (SORT_COMMENTS_BY_SUBSCRIPTIONS && subscriptions_user_ids.includes(last_comment.user_id)) {
last_comment.priority += 1000000;
}
last_comment.priority += 120000 - (new Date().getTime() - last_comment.timestamp);
});
last_comments.sort(function(comment_1, comment_2){
return comment_2.priority - comment_1.priority;
});
last_comments.slice(0,25);
_log(last_comments);
get_right_aside_html();
aside__right__elem.innerHTML = right_aside_html;
}
function get_right_aside_html() {
let html = `
<div id="player"></div>
<div class="live">
<div class="live__title">Сейчас обсуждают
<button class="icon-button live__title-pause" type="button">
<svg class="icon icon--play_small" width="8" height="8">
<use xlink:href="#play_small"></use>
</svg>
</button>
</div>
<div class="live__main" data-scrollable="">
<div></div>`;
last_comments.forEach(function(comment) {
html+= `
<div class="live-item">
<div class="author" >
<a class="author__avatar" style="height:36px;" href="https://dtf.ru/u/${comment.user_id}" targer_"_blank" >
<div data-loaded="true"
class="andropov-media andropov-media--rounded andropov-media--bordered andropov-media--has-preview andropov-image"
style="aspect-ratio: 1 / 1; width: 36px; height: 36px; max-width: none; --background-color: #dddddd;">
<picture>
<source
srcSet="${comment.user_avatar}-/format/webp, ${comment.user_avatar}-/format/webp 2x"
type="image/webp">
<img
src="${comment.user_avatar}"
srcSet="${comment.user_avatar}, ${comment.user_avatar} 2x"
alt="" loading="lazy">
</picture>
</div>
</a>
<div class="author__main">
<a class="author__name" href="https://dtf.ru/u/${comment.user_id}">${comment.user_name}</a>
<div class="live-item__in-post">в посте</div>
</div>
<div class="author__details">
<a class="live-item__entry-title"
title="Запись в посте "${comment.content_title}""
href="${comment.content_url}">${comment.content_title}
</a>
</div>
</div>
<a class="live-item__main" href="${comment.comment_url}">
<div class="live-item__text"><p>${comment.comment_text}</p></div>
</a>
</div>`;
});
html+= `
</div>
</div>
</div>`;
right_aside_html=html;
}
function add_css() {
let css = `
.live-item{--max-text-lines-count: 3;padding:14px 0}.live-item__in-post{color:var(--theme-color-text-secondary)}.live-item__entry-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:500}@media (hover: hover){.live-item__main:hover{opacity:.72}}.live-item__main{display:block}.live-item__text{font-size:15px;line-height:22px;margin-top:7px;display:-webkit-box;-webkit-line-clamp:var(--max-text-lines-count);-webkit-box-orient:vertical;overflow:hidden}.live-item__text a{color:var(--theme-color-signal-active-default);cursor:pointer}@media (hover: hover){.live-item__text a:hover{color:var(--theme-color-signal-active-dark)}}.live-item__text a{pointer-events:none}.live-item__text .quote{--line-width: 4px;--offset-x: 12px;--offset-y: 8px;display:block;position:relative;padding-left:calc(var(--line-width) + var(--offset-x));margin-bottom:var(--offset-y);margin-top:var(--offset-y)}.live-item__text .quote:before{content:"";flex-shrink:0;width:var(--line-width);position:absolute;top:4px;bottom:4px;left:0;background-color:var(--theme-color-border);border-radius:var(--line-width)}.live-item__text .quote{--offset-y: 4px }.live-item__text .quote:before{background-color:var(--theme-color-border-over-background)}.live-item__media{--border-radius: 10px;display:flex;margin-top:9px}.live-item__media:first-child{margin-top:11px}.live-item .author{gap:0 8px}.live-item .author__avatar{transform:none}.live-item .author__main{font-size:13px;line-height:18px}.live-item .author__details{color:var(--theme-color-text-primary)}:root{--safe-tabbar-height: calc(var(--layout-tabbar-height) + env(safe-area-inset-bottom)) }@keyframes underlay-in{0%{opacity:0}to{opacity:1}}@keyframes modal-enter{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:none}}@keyframes modal-enter-slide{0%{opacity:0;transform:translate3d(0,100%,0)}to{opacity:1;transform:translateZ(0)}}.live{height:100%;display:grid;grid-template-rows:auto 1fr;overflow:hidden;position:relative;z-index:1}.live__title{font-weight:500;padding:0 var(--layout-right-aside-offset) 16px;background-color:var(--theme-color-background);display:flex;align-items:center;justify-content:flex-start}.live__title:after{content:"";position:absolute;top:24px;left:50%;width:100%;height:12px;border-radius:100%;transform:translate(-50%);box-shadow:0 4px 20px var(--theme-color-shadow-over-background);z-index:-1;opacity:0}.live__title--with-shadow:after{opacity:1}.live__title-pause{flex-shrink:0;background-color:var(--theme-color-button-secondary);margin-left:8px;padding:6px;will-change:transform}@media (hover: hover){.live__title-pause:hover{filter:brightness(.94)}}.live__title-pause--animated{animation:button-touched .2s cubic-bezier(.4,0,.2,1) forwards}.live__main{padding:0 var(--layout-right-aside-offset);min-height:0;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.live__main::-webkit-scrollbar{display:none}@keyframes live-item-in{0%{opacity:0}}@keyframes button-touched{50%{transform:scale(1.2)}}
.author { --avatar-size: 36px !important;}
`;
const styleSheet = document.createElement("style");
styleSheet.innerText = css;
document.head.appendChild(styleSheet);
}
window.addEventListener('load', async () => {
add_css();
if (SORT_COMMENTS_BY_SUBSCRIPTIONS) {
await get_subscriptions_user_ids();
}
aside__right__elem = document.querySelector('.aside--right');
setInterval(add_right_aside, UPDATE_TIME * 1000);
})
const socket = io('https://ws-sio.dtf.ru', {
transports: ['websocket']
});
socket.emit('subscribe', {'channel': 'live'});
socket.on('connect', () => {
_log('Connected to Socket');
});
socket.on('disconnect', (reason) => {
_log("client disconnected");
if (reason === 'io server disconnect') {
_log("server disconnected the client, trying to reconnect");
socket.connect();
} else {
_log("trying to reconnect again with server");
}
});
socket.on('connect_error', (err) => {
_log(`connect_error due to ${err.message}`);
});
socket.on('error', (error) => {
_log(error);
});
socket.on('event', (event) => {
socket_event(event);
});
function socket_event(event) {
_log(event);
if (!(event && event.data && event.data.type && event.data.type === 'comment_add'))
return false;
let comment_text = event.data.text;
if (comment_text.length>90) {
comment_text = comment_text.substring(0, 90) + ' ...';
}
let post_title = event.data.content.title;
if (post_title.length>60) {
post_title = post_title.substring(0, 60) + ' ...';
}
let new_data = {
comment_id : event.data.comment_id,
comment_date : event.data.date,
comment_text : comment_text,
comment_url : event.data.url,
user_id : event.data.user.id,
user_url : event.data.user.url,
user_name : event.data.user.name,
user_avatar : 'https://leonardo.osnova.io/' + event.data.user.avatar+ '/-/scale_crop/72x72/',
content_url : event.data.content.url,
content_title : post_title,
timestamp : new Date().getTime(),
priority : 0
}
last_comments.push(new_data);
}
})();
Не знаю зачем вообще возвращать ленту комментариев, юзлесс же
Тут все стремились избавиться от нее, зачем возвращать
Избавиться слишком просто:
(() => {
window.addEventListener('load', async () => {
var aside_right = document.querySelector('.aside--right')
aside_right.parentNode.removeChild(aside_right)
})
})();
А вот вернуть пользователям скрытую за пейволлом подписки фичу - это идейно.
@mr2zeek мамкин программист
Ещё должно работать? У меня не появилась
Всё должно работать. Какой браузер и плагин?