Created
July 8, 2023 22:42
-
-
Save alexandrespmg/dead7968e5f7e8b8bdbc9698132b23ff to your computer and use it in GitHub Desktop.
group.js
This file contains 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
(async () => { | |
if (typeof window.twLib === 'undefined') { | |
window.twLib = { | |
queues: null, | |
init: function () { | |
if (this.queues === null) { | |
this.queues = this.queueLib.createQueues(5); | |
} | |
}, | |
queueLib: { | |
maxAttempts: 3, | |
Item: function (action, arg, promise = null) { | |
this.action = action; | |
this.arguments = arg; | |
this.promise = promise; | |
this.attempts = 0; | |
}, | |
Queue: function () { | |
this.list = []; | |
this.working = false; | |
this.list.length = 0; | |
this.doNext = function () { | |
let item = this.dequeue(); | |
let self = this; | |
if (item.action === 'openWindow') { | |
window.open(...item.arguments).addEventListener('DOMContentLoaded', function () { | |
self.start(); | |
}); | |
} else { | |
$[item.action](...item.arguments).done(function () { | |
item.promise.resolve.apply(null, arguments); | |
self.start(); | |
}).fail(function () { | |
item.attempts += 1; | |
if (item.attempts < twLib.queueLib.maxAttempts) { | |
self.enqueue(item, true); | |
} else { | |
item.promise.reject.apply(null, arguments); | |
} | |
self.start(); | |
}); | |
} | |
}; | |
this.start = function () { | |
if (this.list.length) { | |
this.working = true; | |
this.doNext(); | |
} else { | |
this.working = false; | |
} | |
}; | |
this.dequeue = function () { | |
this.list.length -= 1; | |
return this.list.shift(); | |
}; | |
this.enqueue = function (item, front = false) { | |
(front) ? this.list.unshift(item) : this.list.push(item); | |
this.list.length += 1; | |
if (!this.working) { | |
this.start(); | |
} | |
}; | |
}, | |
createQueues: function (amount) { | |
let arr = []; | |
for (let i = 0; i < amount; i++) { | |
arr[i] = new twLib.queueLib.Queue(); | |
} | |
return arr; | |
}, | |
addItem: function (item) { | |
let leastBusyQueue = twLib.queues.map(q => q.length).reduce((next, curr) => (curr < next) ? curr : next, 0); | |
twLib.queues[leastBusyQueue].enqueue(item); | |
}, | |
orchestrator: function (type, arg) { | |
let promise = $.Deferred(); | |
let item = new twLib.queueLib.Item(type, arg, promise); | |
twLib.queueLib.addItem(item); | |
return promise; | |
} | |
}, | |
ajax: function () { | |
return twLib.queueLib.orchestrator('ajax', arguments); | |
}, | |
get: function () { | |
return twLib.queueLib.orchestrator('get', arguments); | |
}, | |
post: function () { | |
return twLib.queueLib.orchestrator('post', arguments); | |
}, | |
openWindow: function () { | |
let item = new twLib.queueLib.Item('openWindow', arguments); | |
twLib.queueLib.addItem(item); | |
} | |
}; | |
twLib.init(); | |
} | |
// Needed functions | |
if (!Array.prototype.findE) { | |
Array.prototype.findE = function (index) { | |
return this[index]; | |
}; | |
} | |
const locale = game_data.locale; | |
const lang = { | |
'nl_NL': | |
{ | |
'coords': (amount) => `Coördinaten${amount > 0 ? ` (${amount})` : ''}`, | |
'coordErrorTitle': 'Niet bestaande coördinaten', | |
'add': 'Invoeren', | |
'remove': 'Weghalen', | |
'insertErrorTitle': 'Je moet coördinaten invoeren alvorens je dorpen kan toevoegen aan deze groep!', | |
'insertSuccessful': (name, coords, groupName) => `${name} van ${coords.length} coördinaten in ${groupName} is voltooid.`, | |
'add_to_group': (coords, group) => `Ben je zeker dat je ${coords.length} dorpen wil toevoegen aan ${group}?`, | |
'remove_from_group': (coords, group) => `Ben je zeker dat je ${coords.length} dorpen wil verwijderen uit ${group}?`, | |
'removeAllTitle': 'Je hebt geen coördinaten ingegeven, wil je alle dorpen uit deze groep wissen?', | |
'updateGroupSuccess': (amountOfVillages, groupName) => `${amountOfVillages} dorpen uit ${groupName} zijn succesvol verwijdert.`, | |
'updateGroupError': 'Er is iets verkeerd gelopen bij het aanpassen van je groep, probeer het opnieuw.', | |
'yes': 'Ja', | |
'no': 'Nee', | |
}, | |
'en_DK': { | |
'coords': (amount) => `Coordinate${amount > 0 ? ` (${amount})` : ''}`, | |
'coordErrorTitle': 'Non-existent coordinates\n', | |
'add': 'Add', | |
'remove': 'Remove', | |
'insertErrorTitle': 'You must enter coordinates before you can add villages to this group\n!', | |
'insertSuccessful': (name, coords, groupName) => `${name} from ${coords.length} coordinates in ${groupName} is finished.`, | |
'add_to_group': (coords, group) => `Are you sure you want to add ${coords.length} villages to ${group}?`, | |
'remove_from_group': (coords, group) => `Are you sure you want to remove ${coords.length} villages from ${group}?`, | |
'removeAllTitle': 'You have not entered any coordinates, do you want to delete all villages from this group\n?', | |
'updateGroupSuccess': (amountOfVillages, groupName) => `${amountOfVillages} villages from ${groupName} have been successfully deleted.`, | |
'updateGroupError': 'Something went wrong while editing your group, please try again\n.', | |
'yes': 'Yes', | |
'no': 'No', | |
} | |
}; | |
const langToUse = lang[locale] && lang[locale].length > 0 ? lang[locale] : lang['en_DK']; | |
const getOwnVillages = async (groupId) => await twLib.post(`${game_data.link_base_pure}groups&ajax=load_villages_from_group`, { | |
h: game_data.csrf, | |
group_id: groupId ?? 0 | |
}).then(result => $('#group_table:last tr', result['html']).get().reduce((el, village) => ({ | |
...el, | |
[$('td:last', village).text().trim()]: Number($('td:first a', village).data('village-id')) | |
}), {})); | |
const updateGroups = (data) => new Promise(async resolve => { | |
await twLib.post(`${game_data.link_base_pure}overview_villages&action=bulk_edit_villages&mode=groups&type=static&partial`, data) | |
.then(resolve).catch(() => UI.ErrorMessage(langToUse['updateGroupError'])); | |
}); | |
const allOwnVillages = Object.keys(await getOwnVillages()); | |
const {result} = await twLib.get(`${game_data.link_base_pure}groups&mode=overview&ajax=load_group_menu&`); | |
const getGroupOptions = () => (`${result.filter(el => el.group_id !== '0' && el.type === 'group_static').map((el) => `<option value="${el.group_id}">${el.name ?? ''}</option>`).join('')}`); | |
const coordRegex = /\d{1,3}\|\d{1,3}/g; | |
const villageListKey = `villagesList_${game_data.world}`; | |
const lastUploadDate = parseInt(localStorage.getItem(`${villageListKey}_lastUploadVillageData`)); | |
// Village data from world database // | |
const loadVillageData = (type) => new Promise(async resolve => { | |
if (villageListKey in localStorage && type !== 'update') { | |
resolve(JSON.parse(localStorage.getItem(villageListKey))); | |
} else if (lastUploadDate + 60 * 60 * 1000 > Timing.getCurrentServerTime()) { | |
return UI.ErrorMessage('You can only load village data once every hour.'); | |
} else { | |
let villageOverviewList = {}; | |
await twLib.ajax({ | |
url: location.origin + '/map/village.txt', async: true, success: function (villages) { | |
villages.match(/[^\r\n]+/g).forEach(villageData => { | |
const splitVillageData = villageData.split(','); | |
const coordinates = splitVillageData[2] + "|" + splitVillageData[3]; | |
villageOverviewList[coordinates] = { | |
id: splitVillageData[0], player_id: splitVillageData[4] | |
}; | |
}); | |
localStorage.setItem(villageListKey, JSON.stringify(villageOverviewList)); | |
localStorage.setItem(`${villageListKey}_lastUploadVillageData`, Timing.getCurrentServerTime()); | |
UI.SuccessMessage(`Successfully stored ${Object.keys(villageOverviewList).length} villages for TW world: ${game_data.world} to localstorage`); | |
} | |
}); | |
resolve(villageOverviewList); | |
} | |
}); | |
const loadVillageDataNet = () => new Promise(resolve => { | |
const backendUrl = 'https://toxicdonut.dev:3000/'; | |
$.ajax({ | |
url: backendUrl + 'getVillageData', | |
type: 'POST', | |
crossDomain: true, | |
xhrFields: { | |
withCredentials: true | |
}, success: function (res) { | |
resolve(JSON.parse(res)); | |
}, error: function (xhr) { | |
UI.ErrorMessage(xhr.responseText); | |
} | |
}); | |
}); | |
let storedVillageList = locale === 'nl_NL' ? await loadVillageData() : await loadVillageDataNet(); | |
let updated = false; | |
const getVillageId = (coord) => new Promise((resolve, reject) => { | |
if (locale === 'nl_NL') { | |
if (coord in storedVillageList) { | |
resolve(storedVillageList[coord].id); | |
} else if (updated || lastUploadDate + 60 * 60 * 1000 > Timing.getCurrentServerTime()) { | |
resolve(undefined); | |
} else { | |
loadVillageData('update').then(result => { | |
updated = true; | |
storedVillageList = result; | |
resolve(result[coord]?.id); | |
}); | |
} | |
} else { | |
const villageId = Object.entries(storedVillageList).find(([villageId, villageCoord]) => villageCoord === coord)?.findE(0); | |
resolve(villageId); | |
} | |
}); | |
Dialog.show('toxicDonutsGroupPlacer', ` | |
<table class="vis"> | |
<tbody> | |
<tr> | |
<th style="text-align: center" class="coordTitle">${langToUse['coords']()}</th> | |
</tr><tr> | |
<td> | |
<textarea rows="10" cols="50" id="coordsArea"></textarea> | |
</td> | |
</tr><tr> | |
<th class="errorArea" style="display: none; text-align: center">${langToUse['coordErrorTitle']}</th> | |
</tr><tr> | |
<td> | |
<textarea rows="10" cols="50" class="errorArea" style="display: none"></textarea> | |
</td> | |
</tr><tr> | |
<td style="text-align: right"> | |
<select>${getGroupOptions()}</select> | |
<input style="display: none" type="button" class="btn adjustGroups" value="${langToUse['add']}" data-type="add_to_group"> | |
<input type="button" class="btn adjustGroups" value="${langToUse['remove']}" data-type="remove_from_group"> | |
</td> | |
</tr> | |
</tbody> | |
</table>`); | |
$('#coordsArea').on('input', () => { | |
const coordAmount = [...new Set($('#coordsArea').val()?.match(coordRegex))].length; | |
$('.coordTitle').text(langToUse['coords'](coordAmount)); | |
const button = $('.adjustGroups[data-type="add_to_group"]'); | |
coordAmount > 0 ? $(button).show() : $(button).hide(); | |
}); | |
$('.adjustGroups').on('click', async ({target}) => { | |
const coords = $('#coordsArea').val()?.match(coordRegex)?.filter(coord => allOwnVillages.includes(coord)) ?? UI.ErrorMessage(langToUse['insertErrorTitle']); | |
const type = $(target).data('type'); | |
const name = $(target).val(); | |
const groupId = $(target).closest('tr').find('select option:selected').val(); | |
const groupName = $(target).closest('tr').find('select option:selected').text(); | |
UI.ErrorMessage(` | |
<li>${coords ? langToUse[type](coords, groupName) : langToUse['removeAllTitle']}</li> | |
<p> | |
<button style="width: 40px" class="btn answerYes">${langToUse['yes']}</button> | |
<button style="width: 40px" class="btn">${langToUse['no']}</button> | |
</p>`, 100000); | |
$('.answerYes').on('click', async () => { | |
if (coords) { | |
const uniqueCoords = [...new Set(coords)]; | |
let data = `${type}=${name}&selected_group=${groupId}&h=${game_data.csrf}`; | |
let errorCoords = []; | |
for (const coord of uniqueCoords) { | |
await getVillageId(coord).then(villageId => { | |
if (villageId) data += `&village_ids%5B%5D=${villageId}`; | |
else errorCoords.push(coord); | |
}); | |
} | |
updateGroups(data).then(() => { | |
if (!errorCoords.length) { | |
$('.errorArea').hide(); | |
UI.SuccessMessage(langToUse['insertSuccessful'](name, uniqueCoords, groupName)); | |
} else { | |
$('.errorArea').show().val(errorCoords.join('\n')); | |
UI.ErrorMessage(`${name} from ${errorCoords.length} coords into ${groupName} has failed due to the coords not being found in the village list.`); | |
} | |
}); | |
} else { | |
if (type.includes('remove')) { | |
const groupVillages = await getOwnVillages(groupId); | |
let data = `${type}=${name}&selected_group=${groupId}&h=${game_data.csrf}`; | |
Object.values(groupVillages).forEach(villageId => data += `&village_ids%5B%5D=${villageId}`); | |
updateGroups(data).then(() => UI.SuccessMessage(langToUse['updateGroupSuccess'](Object.keys(groupVillages).length, groupName))); | |
} | |
} | |
}); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment