import requestCreator from './libs/requestCreator'; import InADayParser from './libs/InADayParser'; import getIDFromURL from './utils/getIDFromURL'; import getCurrentServer from './utils/getCurrentServer'; import formatDate from './utils/formatDate'; import { formatPlayerURL } from './utils/twstats'; import { setItem, getItem } from './utils/localStorage'; // ==UserScript== // @name Extended Player Profile // @namespace https://gist.github.com/Kichiyaki/3c273582cc6856512e22c86c375f795a // @version 0.1 // @description Extended Player Profile // @author Kichiyaki http://dawid-wysokinski.pl/ // @match *://*.plemiona.pl/game.php*&screen=info_player* // @match *://*.tribalwars.net/game.php*&screen=info_player* // @grant none // ==/UserScript== const SERVER = getCurrentServer(); let PLAYER_ID = getIDFromURL(window.location.search); const CURRENT_PLAYER_ID = parseInt(game_data.player.id); if (isNaN(PLAYER_ID) || !PLAYER_ID) { PLAYER_ID = CURRENT_PLAYER_ID; } const LOCAL_STORAGE_KEY = 'kichiyaki_extended_player_profile' + PLAYER_ID; const query = ` query pageData($server: String!, $id: Int!, $filter: DailyPlayerStatsFilter) { player(server: $server, id: $id) { id name servers joinedAt nameChanges { oldName newName changeDate } dailyGrowth } dailyPlayerStats(server: $server, filter: $filter) { items { rank rankAtt rankDef rankSup rankTotal points scoreAtt scoreAtt scoreDef scoreSup scoreTotal villages } } } `; const profileInfoTBody = document.querySelector('#player_info > tbody'); const otherElementsContainer = document.querySelector( PLAYER_ID === CURRENT_PLAYER_ID ? '#content_value > table:nth-child(7) > tbody > tr > td:nth-child(2)' : '#content_value > table > tbody > tr > td:nth-child(2)' ); const loadDataFromCache = () => { return getItem(LOCAL_STORAGE_KEY); }; const cachePlayerData = (data = {}) => { setItem(LOCAL_STORAGE_KEY, data); }; const loadInADayRankAndScore = async (name, playerID, type) => { try { const response = await fetch( TribalWars.buildURL('', { screen: 'ranking', mode: 'in_a_day', type, name, }) ); const html = await response.text(); const res = new InADayParser(html, { playerID }).parse(); if (res.length === 0) { throw new Error(); } return res[0]; } catch (error) { return { rank: 0, playerID: 0, score: 0, tribeID: 0, date: new Date(), }; } }; const loadData = async () => { const data = await requestCreator({ query, variables: { server: SERVER, id: PLAYER_ID, filter: { sort: 'createDate DESC', limit: 1, playerID: [PLAYER_ID], }, }, }); if (data.player) { const inADay = {}; inADay.att = await loadInADayRankAndScore( data.player.name, data.player.id, 'kill_att' ); inADay.def = await loadInADayRankAndScore( data.player.name, data.player.id, 'kill_def' ); inADay.sup = await loadInADayRankAndScore( data.player.name, data.player.id, 'kill_sup' ); inADay.lootRes = await loadInADayRankAndScore( data.player.name, data.player.id, 'loot_res' ); inADay.lootVil = await loadInADayRankAndScore( data.player.name, data.player.id, 'loot_vil' ); inADay.scavenge = await loadInADayRankAndScore( data.player.name, data.player.id, 'scavenge' ); inADay.conquer = await loadInADayRankAndScore( data.player.name, data.player.id, 'conquer' ); data.player.inADay = inADay; } cachePlayerData(data); return data; }; const renderTr = ({ title, data, id }) => { let tr = document.querySelector('#' + id); if (!tr) { tr = document.createElement('tr'); tr.id = id; tr.appendChild(document.createElement('td')); tr.appendChild(document.createElement('td')); profileInfoTBody.append(tr); } tr.children[0].innerHTML = title; tr.children[1].innerHTML = data; }; const renderPlayerServers = (player) => { let playerServers = document.querySelector('#playerServers'); if (!playerServers) { playerServers = document.createElement('table'); playerServers.id = 'playerServers'; playerServers.classList.add('vis'); playerServers.width = '100%'; playerServers.innerHTML = ` Player's Servers `; otherElementsContainer.prepend(playerServers); } playerServers.querySelector('td').innerHTML = player.servers .sort() .map( (server) => `${server}` ) .join(''); }; const renderPlayerOtherNames = (player) => { let playerOtherNames = document.querySelector('#playerOtherNames'); if (!playerOtherNames) { playerOtherNames = document.createElement('div'); playerOtherNames.id = 'playerOtherNames'; playerOtherNames.width = '100%'; otherElementsContainer.prepend(playerOtherNames); } playerOtherNames.innerHTML = ` ${player.nameChanges .map((nameChange) => { return ` `; }) .join('')}
Old name New name Date
${nameChange.oldName} ${nameChange.newName} ${formatDate(nameChange.changeDate, { year: 'numeric', month: 'numeric', day: 'numeric', })}
`; }; const renderTodaysStats = (stats) => { let todaysStats = document.querySelector('#todaysStats'); if (!todaysStats) { todaysStats = document.createElement('div'); todaysStats.id = 'todaysStats'; todaysStats.width = '100%'; otherElementsContainer.prepend(todaysStats); } const statIncreaseStyle = 'color: #000; background-color: #0f0'; const statDecreaseStyle = 'color: #000; background-color: #f00'; todaysStats.innerHTML = `
Today's stats
Points ${Math.abs(stats.points).toLocaleString()}
Rank ${Math.abs(stats.rank)}
Villages ${Math.abs(stats.villages).toLocaleString()}
ODA ${Math.abs(stats.scoreAtt).toLocaleString()}
Rank (ODA) ${Math.abs(stats.rankAtt)}
ODD ${Math.abs(stats.scoreDef).toLocaleString()}
Rank (ODD) ${Math.abs(stats.rankDef)}
ODS ${Math.abs(stats.scoreSup).toLocaleString()}
Rank (ODS) ${Math.abs(stats.rankSup)}
OD ${Math.abs(stats.scoreTotal).toLocaleString()}
Rank (OD) ${Math.abs(stats.rankTotal)}
`; }; const renderInADayRanks = (player) => { let inADayRanks = document.querySelector('#inADayRanks'); if (!inADayRanks) { inADayRanks = document.createElement('div'); inADayRanks.id = 'inADayRanks'; inADayRanks.width = '100%'; otherElementsContainer.prepend(inADayRanks); } inADayRanks.innerHTML = `
'In a day' best scores
Units defeated while attacking: ${player.inADay.att.score.toLocaleString()} (${ player.inADay.att.rank }.)
Units defeated while defending: ${player.inADay.def.score.toLocaleString()} (${ player.inADay.def.rank }.)
Units defeated while supporting: ${player.inADay.sup.score.toLocaleString()} (${ player.inADay.sup.rank }.)
Resources plundered: ${player.inADay.lootRes.score.toLocaleString()} (${ player.inADay.lootRes.rank }.)
Villages plundered: ${player.inADay.lootVil.score.toLocaleString()} (${ player.inADay.lootVil.rank }.)
Resources gathered: ${player.inADay.scavenge.score.toLocaleString()} (${ player.inADay.scavenge.rank }.)
Villages conquered: ${player.inADay.conquer.score.toLocaleString()} (${ player.inADay.conquer.rank }.)
`; }; const render = ({ player, dailyPlayerStats }) => { [ { title: 'Joined at:', data: formatDate(player.joinedAt), id: 'joined_at', }, { title: 'Daily growth:', data: player.dailyGrowth.toLocaleString(), id: 'dg', }, ].forEach((data) => { renderTr(data); }); renderInADayRanks(player); if (dailyPlayerStats && dailyPlayerStats.items.length > 0) { renderTodaysStats(dailyPlayerStats.items[0]); } if (player.nameChanges.length > 0) { renderPlayerOtherNames(player); } if (player.servers.length > 0) { renderPlayerServers(player); } }; (async function () { try { const dataFromCache = loadDataFromCache(); if (dataFromCache && dataFromCache.player) { render(dataFromCache); } const dataFromAPI = await loadData(); if (dataFromAPI) { render(dataFromAPI); } console.log(dataFromAPI); } catch (error) { console.log('extended player profile', error); } })();