您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Темный скин golos.io с монитором активности пользователей из blockchain
// ==UserScript== // @name Dark Voice // @namespace golos.io // @description Темный скин golos.io с монитором активности пользователей из blockchain // @description:ru Темный скин golos.io с монитором активности пользователей из blockchain // @grant none // @version 0.23 // @include https://golos.io/* // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js // ==/UserScript== // var myname = 'vik'; // Поменяйте на свое имя и переместите сокеты выше - будет работать быстрей :) var socket = new WebSocket('wss://ws.golos.io'), account = myname; startblock = 0; socket.onopen = function(event) { socket.send(JSON.stringify({ id: 1, method: 'get_dynamic_global_properties', 'params': [] })); }; socket.onmessage = function(event) { data = JSON.parse(event.data); startblock = data.result.last_irreversible_block_num; }; // Прописываем CSS и HTML $('.Header__top-steemit').html('<a href="/@vik/">Dark Voice<span class="beta">@vik</span></a>'); var inlinecss = "<style>.Voting__button path,.Voting__button-down a:hover path{fill:#fff}#opclose,.svote a{vertical-align:middle}.Header,body{background-color:#36465d;color:#fff}.VerticalMenu>li>a,.menu a{color:#fff}.VerticalMenu>li>a:hover{color:#101823;line-height:1.5rem}.Header__sub-nav .active a,.Header__sub-nav li:hover a,.PostSummary__header>h2>a,.PostsIndex__topics,.PostsIndex__topics small a,.Topics__title{color:#fff}.Header__sub-nav li>a{color:#fff;border:0;line-height:1.2em;font-size:.9em;background-color:#101823}.Header__sub-nav li{padding:.5rem 0;position:relative;overflow:hidden}.menu .buttons{display:none}.Header__sub-nav li>a:after{content:'';width:0;height:2px;background:#fff;z-index:1;position:absolute;bottom:0;left:0;transition:.6s all ease}.Header__sub-nav li:hover>a:after{content:'';width:100%}.Header .menu,.Header__sub-nav,.Header__top{background-color:#101823;border-bottom:1px solid #0b1119}#content{background:#36465d}.PostsIndex__topics{border-radius:3px;padding:5px;transition:.4s all ease;height:35px;overflow:hidden;position:fixed;top:55px;border:0;right:-160px;background:#184e86;box-shadow:0 0 35px -10px #000;z-index:700}ul.Topics li a{background:#fff;padding:0 3px;border-radius:3px;margin:3px}.PostsIndex__topics:hover{box-shadow:0 0 75px -10px #000;height:450px;overflow:auto;right:-30px}img.PostSummary__image{width:100%;max-width:640px;height:auto;border:0;padding:0;float:none;display:block}.PostSummary{position:relative;margin:0 2% 50px 0;border-radius:3px;box-shadow:0 15px 50px -15px #000;max-width:580px;background:#101823}.PostSummary.with-image .PostSummary__content,.PostSummary.with-image .PostSummary__reblogged_by,.PostSummary__content{margin:.5rem}.PostSummary__collapse{position:absolute;right:5px;top:5px}.PostSummary__body.entry-content{white-space:normal;color:#a6acb5;margin:0 0 30px}.PostSummary__footer{color:#fff}.Voting__inner{border:0}.Voting__button circle{stroke:#fff}.Voting__button-up>a:hover circle,a.confirm_weight:hover circle{fill:#4ba2f2;stroke:#4ba2f2}.Voting__button-up .Icon{box-shadow:0 0 15px rgba(0,0,0,.7);border-radius:100%;transform:scale3d(1,1,1) rotate(0);transition:all 1s cubic-bezier(.4,0,0,1.67)}.PostSummary:hover span.usersg{position:relative;transition:1s all ease}.PostSummary:hover .Voting__button-up .Icon{box-shadow:0 0 25px rgba(0,0,0,.7);transform:scale3d(2.2,2.1,2.6) rotate(720deg)}.dropdown-pane{background:#101823;border:0;box-shadow:0 0 20px #000;transition:1s all ease;color:#fff}.vcard>strong a,span.Author{font-weight:200;text-shadow:none;border-radius:10px;color:#fff}#closeop,.ReplyEditor{box-shadow:0 0 30px -10px #000}.Voting__adjust_weight .weight-display,.Voting__adjust_weight_down .weight-display{margin-left:20px;color:#fff;font-size:1.5rem}.Voting__adjust_weight,.Voting__adjust_weight_down{padding:10px 5px;margin-right:0;width:400px;overflow:hidden}.vcard>strong a{background:#4ba2f2;padding:0 7px 1px}span.Author{position:relative;background:#484848;padding:1px 6px 2px 12px}.Reputation{font-size:.8rem;border:0;border-radius:5px;background:#ffae00;color:#fff;padding:0 6px 0 3px}.vcard>strong a:before{content:'#';font-size:.6rem;margin-right:3px;color:#fff}.PostSummary__time_author_category{font-size:.7rem;border:0}.VotesAndComments{float:right}.PostsIndex.row{max-width:100%}.Voting__inner{margin-right:0}.grid-item{float:left;transition:.4s all ease}.grid-item,.grid-sizer{width:22%}.gutter-sizer{width:4%}#showanswer{position:fixed;right:26px;top:118px;background:#063465;color:#fff;font-size:14px;border-radius:3px;padding:1px 15px;z-index:400}span.usersg{transition:all .4s ease;background:#009c64;padding:1px 5px 2px}#drkloader{width:auto;display:block;height:100%;overflow:auto;overflow-x:hidden}#drkwidget,.answerholder{position:fixed;width:50%}.ReplyEditor{background:#fff;padding:20px 0;border-radius:5px;color:#000}ul#drkstream{margin:0;padding:0 15px;background:rgba(1,14,31,.9);height:90%;overflow-x:auto;overflow-y:auto}#drkstream li{display:none;list-style-type:none;font-size:.8rem}.svote a{background:#5974ff;color:#fff;padding:1px 5px;border-radius:10px;line-height:0;overflow:hidden;font-size:11px;font-weight:700}.scomment i{background:green;font-style:normal;padding:0 4px;border-radius:15px}.Voting span{color:#1dd492;text-shadow:0 0 3px #19943e}.drklog p{line-height:1;margin:0;background:#184e86;padding:10px}.insertsila strong{font-size:20px;background:url(https://golos.io/images/golospower-badge.jpg) no-repeat #fff;background-size:contain;padding:0 15px 0 35px;color:#1b5d9d;border-radius:30px}.drklog{text-align:center}#drkwidget{z-index:100;display:none;background:url(https://s28.postimg.org/bvu4yda25/endless_3d_cube_gif.gif) no-repeat #184e86;background-size:cover;top:110px;right:15px;height:600px;height:calc(100vh - 180px);border-radius:3px;box-shadow:0 0 10px -1px #000;overflow:hidden}ul#drkstream li b{background:rgba(75,162,242,.14);padding:1px 8px;border-radius:10px;font-weight:200}ul#drkstream li strong{background:rgba(114,255,98,.51);padding:1px 8px;border-radius:10px}.scomment div,.svote div{font-size:.8rem;height:.8rem;overflow:hidden;vertical-align:middle;line-height:.8rem;max-width:200px;display:inline-block;color:#3b4a5a}#closeop,#drkmenu,#drkstory,.answertarget .Voting{display:none}#drkmenu{text-align:center}#post_overlay{color:#000}.answerholder{z-index:500;background:#101823;display:none;top:150px;padding:15px;right:14px}#closeop,#opclose{background:#063465;border-radius:3px;font-size:14px}.answertarget{overflow:auto;height:500px;width:740px}#opclose{position:absolute;left:20px;top:10px;padding:3px 15px 5px;line-height:14px}#closeop{z-index:400;position:fixed;top:150px;right:26px;padding:5px 10px}.beforeload{transition:1s all}#drkstream::-webkit-scrollbar,body::-webkit-scrollbar{width:7px;height:9px}#drkstream::-webkit-scrollbar-track,body::-webkit-scrollbar-track{background:#053363}#drkstream::-webkit-scrollbar-thumb,body::-webkit-scrollbar-thumb{background:rgba(255,255,255,.4)}#drkstory{overflow:auto;height:100%;opacity:.98}#drkstory tbody,.UserWallet tbody{border:0!important;background:#101823}#drkstory table tbody tr:nth-child(even),.UserWallet table tbody tr:nth-child(even){background-color:#063465}.UserWallet__balance.row{background:#fff;padding:15px;color:#000;font-weight:700}.reveal.fade.in{background:#20242a;color:#fff;border:0;box-shadow:0 0 50px #000}a.go-top{position:fixed;background:#334258;bottom:10px;left:10px;color:#fff;padding:10px;box-shadow:0 0 20px #000;border-radius:3px}.answertarget .PostSummary{position:relative;margin:10px 0;border-radius:3px;box-shadow:0 15px 50px -15px #000;max-width:660px;background:#101823;color:#fff}.answertarget .PostSummary__body.entry-content{color:#fff;margin:0}.Comment .highlighted { background: #415879; padding: 5px; border-radius: 10px; }.Post a { color: #9cd0ff; }</style>"; var somehtml = '<a href="#0" class="go-top">Вверх</a><div id="drkwidget"><div class="drklog"><p id="silag"><span class="insertsila"><strong>Сила Голоса...</strong></span></p><span id="opclose">Закрыть</span><span id="currblock">Загружаем текущий блок...</span><span id="dwitness"></span></div><div id="drkmenu">Моя история</div><div id="drkstory"></div><ul id="drkstream"><li class="beforeload"><center>Подключаемся к ноде... Для корректной работы используйте только одну вкладку Голоса</center></li><li class="beforeload2"><center>В этой ноде идет трансляция действий пользователей: комментарии, голосование, упоминания, фолловинг и другое. При низком качестве подключения возможны потери событий из трансляции. Для минимизации потерь не открывайте несколько вкладок Голоса одновременно!</center></li></ul></div><div id="closeop">Мониторинг</div>'; $(inlinecss).appendTo("head"); // Устанавливаем CSS стили $(somehtml).appendTo("body"); // Вставляем необходимые html элементы // Меняем в постах маленькие фото на большие: 256x128 > 640x480 function imgtoggle() { var tinyimg = new RegExp('/256x128/'), // Берем ссылки на маленькие превью bigimg = new RegExp('640x480'); // Меняем в ссылка значение разрешения фотографии, обращаясь к проксификатору по ссылке https://imgp.golos.io/640x480/ $('img.PostSummary__image').each(function() { var image = $(this); image.attr('src', image.attr('src').replace(tinyimg, bigimg)); // Тут происходит ранее описанная замена 256x128 на 640x480 }); } imgtoggle(); setTimeout(function() { $('#drkwidget').slideDown(); }, 2000); $('#opclose').on('click', function() { $('#drkwidget').slideUp(); $('.PostsIndex.row' ).css('max-width',' 80%'); $('#closeop').slideDown(); }); $('#closeop').on('click', function() { $('#drkwidget').slideDown(); $(this).slideUp(); $('.PostsIndex.row' ).css('max-width',' 100%'); }); function drkwait() { socket = new WebSocket('wss://ws.golos.io'); account = myname; var movementTotal, silaTotal; socket.onopen = function(event) { socket.send(JSON.stringify({ id: 1, method: 'get_dynamic_global_properties', 'params': [] })); }; socket.onmessage = function(event) { var silaGolosa, powerMovement, data = JSON.parse(event.data), stream = document.getElementById('drkstream'); lastblock = startblock; merkle = data.result.transaction_merkle_root; if (merkle !== 0 && startblock > 100) { if (data.id === 1) { movementTotal = data.result.total_vesting_shares.split(' ')[0]; silaTotal = data.result.total_vesting_fund_steem.split(' ')[0]; socket.send(JSON.stringify({ id: 2, method: 'get_accounts', params: [ [account] ] })); socket.send(JSON.stringify({ id: 3, method: 'get_block', 'params': [lastblock] })); // socket.send(JSON.stringify({ id: 4, method:'get_account_history', params: [ [account] ] })); История аккаунта document.getElementById('currblock').innerHTML = '<span class="insertblock"><strong>' + lastblock + '</strong> Последний блок. </span>'; } if (data.id === 2) { powerMovement = data.result[0].vesting_shares.split(' ')[0]; silaGolosa = silaTotal * (powerMovement / movementTotal); document.getElementById('silag').innerHTML = '<span class="insertsila"><strong>' + silaGolosa + '</strong></span>'; } if (data.id === 3) { tx = data.result.transactions[0].operations[0][1]; wtnss = data.result.witness; drkvoter = JSON.stringify(tx.voter); drkpower = JSON.stringify(tx.weight); drkauthor = JSON.stringify(tx.author); drklink = JSON.stringify(tx.permlink); drkcomm = JSON.stringify(tx.parent_author); drkbodycomm = JSON.stringify(tx.body); drknewbie = JSON.stringify(tx.new_account_name); drkfl = tx.json; // Фолловинг (подписки) mention = JSON.stringify(tx.to); // Mention упоминания mentmemo = JSON.stringify(tx.memo); document.getElementById('dwitness').innerHTML = '<span class="inserwtnss"> В ноде <strong>' + wtnss + '</strong></span>'; if (typeof mentmemo !== "undefined") { memocut = mentmemo.slice(26); stream.insertAdjacentHTML('afterbegin', '<li class="sfollow"><b>' + mention + '</b> упомянул ' + memocut + '</li>'); } if (typeof drknewbie !== "undefined") { stream.insertAdjacentHTML('afterbegin', '<li class="snewbie">Новый пользователь > <strong>' + drknewbie + '</strong>!</li>'); } if (typeof drkcomm !== "undefined" && typeof drkauthor !== "undefined") { stream.insertAdjacentHTML('afterbegin', '<li class="scomment"><b>' + drkauthor + '</b> комментирует пост <strong>' + drkcomm + '</strong> <div>' + drklink + '</div></li>'); } if (typeof drkvoter !== "undefined" && typeof drkauthor !== "undefined") { stream.insertAdjacentHTML('afterbegin', '<li id=' + drkauthor + ' class="svote"><b>' + drkvoter + '</b> <a title=' + drklink + ' href=' + drklink + '>></a> голосует с силой ' + drkpower + ' за <strong>' + drkauthor + '</strong> <div>' + drklink + '</div></li>'); } if (typeof drkfl !== "undefined") { df = JSON.parse(drkfl); dfollower = df[1].follower; dfollowin = df[1].following; stream.insertAdjacentHTML('afterbegin', '<li class="sfollow"><b>' + dfollower + '</b> подписка на <strong>' + dfollowin + '</strong></li>'); } } } }; } // Получаем параметры, который пользователь может добавить в конец своей ссылки на аватар. Синтаксис //domain.tld/img.jpg?css=[css стили] // Так же получаем юзернэйм для которого нужно показывать блок ответов function waitfor() { // Внутри функции будем ждать полной загрузки страницы и проверять когда появятся необходимые нам ссылки var Upic = $('.Userpic'); var userpicUrl = $('.Userpic img').attr('src'); // Проверяем ссылку на аватар var usernameUrl = Upic.parent().attr('href'); // Проеверяем ссылку на юзернэйм. Нам нужно получить из нее ник текущего пользователя, что бы ответы в виджет загружались именно для вас. // Если ссылки уже доступны, выдираем только нужные нам параметры: // Фильтруем и получаем параметры, который пользователь добавил в своем аккаунте в конец ссылки на аватар например //вк.ком/рукалицо.jpg?css=[#content{background:black;}] сделает фон контента черным function getParameterByName(name, url) { if (!url) { url = userpicUrl; } name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&]*)|&||$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); } // Функция с помощью который мы загрузим ответы в будущем. function answerupdate() { $('.answertarget').load(usernameUrl + '/recent-replies/ #posts_list'); } if (Upic.length) { myname = usernameUrl.slice(2); var isVisible = function(obj) { return obj.offsetWidth > 0 && obj.offsetHeight > 0; }; var curry = function(uncurried) { var parameters = Array.prototype.slice.call(arguments, 1); return function() { return uncurried.apply(this, parameters.concat(Array.prototype.slice.call(arguments, 0))); }; }; var getAndAddToCallbacks = function(socket, callbacks, method, params, callback) { callbacks.push(callback); var data = { id: callbacks.length - 1, method: method, params: params }; socket.send(JSON.stringify(data)); }; var runFun = function(funs, id, data) { funs[id](data); }; var socket = new WebSocket('wss://ws.golos.io'), callbacks = []; var getResult = curry(getAndAddToCallbacks, socket, callbacks), runCallback = curry(runFun, callbacks); socket.onopen = function(event) { getResult('get_dynamic_global_properties', [], function(data) { var totalVestingShares = data.result.total_vesting_shares.split(' ')[0], totalVestingFundSteem = data.result.total_vesting_fund_steem.split(' ')[0]; var nodes = [].slice.call(document.querySelectorAll('[itemprop=author] strong')).reduce(function(nodes, node) { if (!isVisible(node) || node.ssp__hasSp) { return nodes; } nodes.push(node); return nodes; }, []); var accounts = nodes.map(function(node) { return node.innerHTML; }); getResult('get_accounts', [accounts], function(data) { data.result.forEach(function(account, i) { var vestingShares = account.vesting_shares.split(' ')[0]; var steemPower = totalVestingFundSteem * (vestingShares / totalVestingShares); var parent = nodes[i].parentNode; console.log(account.name + ' ' + steemPower); nodes[i].outerHTML = '' + account.name + ' <span class="usersg">' + Math.round(steemPower) + '</span>'; nodes[i].ssp__hasSp = true; }); }); }); }; socket.onmessage = function(event) { var data = JSON.parse(event.data); runCallback(data.id, data); }; setInterval(function() { startblock++; drkwait(); imgtoggle(); $('#drkstream li,#drkmenu').slideDown(); }, 5000); // Проверяем новые блоки. $('.Header__top-steemit').html('<a href="/@vik/">Dark Voice<span class="beta">@vik</span></a>'); $('.beforeload').css('opacity', '0'); // Даем возможность обновлять ответы нажатием кнопки "Обновить ответы" $('<div class="answerholder"><p id="answerupdate">Обновить ответы</p><div class="answertarget">Загрузка...</div></div><div id="showanswer">Мои ответы</div>').appendTo("body"); $('#answerupdate').on('click', function() { answerupdate(); }); // Даем возможность открывать/закрывать блок ответов var isActive = true; $('#showanswer').on('click', function() { if (isActive) { answerupdate(); $('.answerholder').slideDown(); } else { $('.answerholder').slideUp(); } isActive = !isActive; }); // моя история $('#answerupdate').on('click', function() { answerupdate(); }); // Даем возможность открывать/закрывать блок ответов $('#drkmenu').on('click', function() { if (isActive) { $('#drkstory').load(usernameUrl + '/transfers/ table'); // загрузка истории $('#drkstory').slideDown(); } else { $('#drkstory').slideUp(); } isActive = !isActive; }); // Получаем то, что после ?css= и перед & // Убираем квадратные скобки по бокам из переменной var cleaning = getParameterByName('css'); if (cleaning !== null) { var stringcss = cleaning.substring(1, cleaning.length - 1); // Оборачиваем в теги стиля // Если параметр существует var cleanCSS = $('<style></style>').append(stringcss); // Подключаем наш кастом стиль. На данный момент он применяется только после полной загрузки страницы, но в следующей версии скрипта я это исправлю. cleanCSS.appendTo("head"); } //C остальными пармаетрами проще. Можно получить параметр после каждого & в формате //вк.ком/рукалицо.jpg?option1=ON&option2=OFF&option3=BIG // Пока опции есть как пример и демо функционала, осталось придумать какие опции могуть быть нужны. Например фиксировать ли кнопки редактора или нет. Или отключить большинсво ненужных элементов. // В качестве примера отключим топики - метки в сайдбаре var notopics = getParameterByName('topics'); if (notopics == 'OFF') { $('.PostsIndex__topics').slideUp(); // Топики улетают // Добавляем кнопку, по нажатию которой топики выпадут вниз $('<div id="slidetopics">Топики</div>').appendTo("body"); $('#slidetopics').on('click', function() { if (isActive) { $('.PostsIndex__topics').slideDown(); } else { $('.PostsIndex__topics').slideUp(); } isActive = !isActive; }); } // Для отключения топиков вставьте в ссылку аватара параметр ¬opics=OFF // В следующей версии скина будет больше параметров и настроек } // Так как мы все еще внутри условия "Если аватарка уже загрузилась" , то если она не загрузилась - мы будем рекурсивно проверять и ждать ее каждую секунду else { setTimeout(waitfor, 1000); } } waitfor(); // Добавляем кнопку-стрелку возвращения в начало страницы $(document).ready(function() { // Show or hide the sticky footer button $(window).scroll(function() { if ($(this).scrollTop() > 200) { $('.go-top').fadeIn(200); } else { $('.go-top').fadeOut(200); } }); // Animate the scroll to top $('.go-top').click(function(event) { event.preventDefault(); $('html, body').animate({ scrollTop: 0 }, 300); }); }); // Сообщение в консоли браузера. console.log('Вы установили userscript от golos.io/@vik и сейчас вы смотрите консоль :) ВНИМАНИЕ! Перед установкой этого или похожего скрипта убедитесь, что вы нашли его в надежном источнике! Если вы не уверены, что скрипт оригинальный - обратитесь к опытным пользователям и попросите проверить его на предмет внедрения вредного кода. Вы можете обратиться ко мне в голосе golos.io/@vik/ ');