Created
October 28, 2021 18:52
-
-
Save xiaoxiaoflood/6dc7a804d9cce7cc2c3e828dc4970a83 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name VK Xiao - Ordena tópicos no fórum | |
// @namespace https://vk.com/xiaoxiaoflood | |
// @match https://vk.com/board* | |
// @match https://oauth.vk.com/blank.html | |
// @version 1.0 | |
// @grant none | |
// @run-at document-start | |
// ==/UserScript== | |
// baseado na extensão feita por Jônathas Gouveia. | |
let token; | |
let cmm; | |
let initialScrap = 1; | |
let pageLoaded = false; | |
async function checkToken () { | |
if (location.href.startsWith('https://oauth.vk.com/blank.html')) { | |
await GM.setValue('token', location.hash.match(/(?<=access_token=)\w+/)[0]); | |
GM.getValue('redirUrl').then(url => { | |
GM.deleteValue('redirUrl'); | |
location = url; | |
}); | |
} else { | |
token = await GM.getValue('token'); | |
if (!token) | |
getAccessToken(); | |
else | |
init(); | |
} | |
} | |
checkToken(); | |
async function init () { | |
cmm = location.pathname.match(/\d+/)[0]; | |
scrap(); | |
await elementReady('#blst_cont'); | |
pageLoaded = true; | |
if (typeof initialScrap === 'string') | |
document.querySelector('#blst_cont').innerHTML = initialScrap; | |
insertButton(); | |
} | |
async function generateTopicsHTML (topics, profiles) { | |
let newTopics = ''; | |
topics = topics.sort((a, b) => new Date(b.updated) - new Date(a.updated)); | |
topics = topics.sort((a, b) => b.is_fixed - a.is_fixed); | |
let fixed = `<div class="blst_fixed" onmouseover="showTooltip(this, {text: 'Tópico fixado', black: 1, shift: [14, 8, 8]})"></div>`; | |
let closed = `<div class="blst_closed" onmouseover="showTooltip(this, {text: 'Tópico fechado', black: 1, shift: [14, 8, 8]})"></div>`; | |
for (let i = 0; i < topics.length; i++) { | |
let a = topics[i]; | |
let currentProfile = profiles.find(b => b.id === a.updated_by) || profiles.find(b => b.id === 101); | |
let pagination = []; | |
for (let j = 0; a.comments > j * 20; j++) { | |
if (a.comments < 140 || j !== 3) { | |
pagination.push('<a class="blst_page" href="/topic-' + cmm + '_' + a.id + '?offset=' + j * 20 + '">' + (j + 1) + '</a>'); | |
} else if (j == 3) { | |
pagination.push('..'); | |
j = Math.ceil(a.comments / 20) - 4; | |
} | |
} | |
let html = ` | |
<div class="blst_row clear_fix"> | |
<a class="blst_last" href="/topic-${cmm}_${a.id}?offset=last&scroll=1" onclick="return nav.go(this, event)"> | |
<div class="blst_thumb"><img class="blst_img" src="${currentProfile.photo_50}"></div> | |
<div class="blst_mem">${currentProfile.first_name + " " + currentProfile.last_name}</div> | |
<div class="blst_date">${formatDate(a.updated)}</div> | |
</a> | |
<div class="blst_info"> | |
<div class="blst_title_wrap"> | |
<a class="blst_title" href="/topic-${cmm}_${a.id}" onclick="return nav.go(this, event)">${a.title}</a>${a.is_fixed ? fixed : ''}${a.is_closed ? closed : ''} | |
</div> | |
<div class="blst_other"> | |
${a.comments} recado${a.comments ? 's' : ''}${a.comments >= 20 ? `<span class="divider">|</span>Pgs. ${pagination.join(' ')}` : ''} | |
</div> | |
</div> | |
</div> | |
` | |
newTopics += html; | |
} | |
if (pageLoaded) { | |
document.querySelector('#blst_cont').innerHTML = newTopics; | |
initialScrap = 0; | |
} else { | |
initialScrap = newTopics; | |
} | |
} | |
function formatDate (date) { | |
let s = new Intl.DateTimeFormat('pt-BR', { | |
year: 'numeric', | |
month: 'short', | |
day: 'numeric', | |
hour: 'numeric', | |
minute: 'numeric' | |
}).formatToParts(date * 1000); | |
let agora = new Date(); | |
let dia = ('0' + agora.getDate()).slice(-2); | |
let ontem = ('0' + (d => new Date(d.setDate(d.getDate()-1)))(agora).getDate()).slice(-2); | |
let ano = new Date().getFullYear(); | |
let data = s[0].value == dia ? 'hoje' : s[0].value == ontem ? 'ontem' : s[0].value + ' de ' + s[2].value.charAt(0).toUpperCase() + s[2].value.slice(1); | |
let horario = s[4].value == agora.getFullYear() ? 'às ' + s[6].value + ':' + s[8].value : 'de ' + s[4].value; | |
return data + ' ' + horario; | |
}; | |
function scrap () { | |
GM.xmlHttpRequest({ | |
url: 'https://api.vk.com/method/board.getTopics?group_id=' + cmm + '&order=1&extended=1&count=100&offset=0&access_token=' + token + '&v=5.812', | |
onload: response => { | |
let { items: topics, profiles } = JSON.parse(response.responseText).response; | |
generateTopicsHTML(topics.sort((a, b) => a.updated < b.updated), profiles); | |
} | |
}); | |
} | |
function insertButton () { | |
const btn = document.createElement('button'); | |
btn.id = 'buttonAtt' | |
btn.className = 'flat_button' | |
btn.innerHTML = `Atualizar` | |
btn.addEventListener('click', scrap) | |
document.querySelector('._header_extra').appendChild(btn); | |
} | |
function elementReady (selector) { | |
return new Promise(resolve => { | |
let el = document.querySelector(selector); | |
if (el) | |
resolve(el); | |
let observer = new MutationObserver(() => { | |
if (el = document.querySelector(selector)) { | |
resolve(el); | |
observer.disconnect(); | |
} | |
}); | |
observer.observe(document.documentElement, { | |
childList: true, | |
subtree: true | |
}); | |
}); | |
} | |
function getAccessToken () { | |
GM.setValue('redirUrl', location.href); | |
let params = Object.entries({ | |
client_id : 7579150, | |
scope : 'groups,offline', | |
redirect_uri : 'https://oauth.vk.com/blank.html', | |
display : 'popup', | |
v : 5.812, | |
response_type : 'token' | |
}).map(([key, val]) => key + '=' + encodeURIComponent(val)).join('&'); | |
location = 'https://oauth.vk.com/authorize?' + params; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment