Compare commits
10 Commits
f7cb4da37c
...
v1.6.1
| Author | SHA1 | Date | |
|---|---|---|---|
| f841780ed9 | |||
| c22c2fb254 | |||
| 4fe2922e5a | |||
| 4f1d5442be | |||
| 45d5200e61 | |||
| 10de4507af | |||
| a37d54cd2e | |||
| abc7742b75 | |||
| 05369a6661 | |||
| 948de12bc5 |
@@ -14,10 +14,28 @@ jobs:
|
|||||||
- name: Run linter
|
- name: Run linter
|
||||||
run: make lint
|
run: make lint
|
||||||
|
|
||||||
deploy:
|
deploy-chrome:
|
||||||
|
needs: lint
|
||||||
runs-on: linux
|
runs-on: linux
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
- name: Deploy project
|
- name: Deploy project to Chrome Webstore
|
||||||
run: make deploy
|
env:
|
||||||
|
CLIENT_ID: ${{ vars.CHROME_CLIENT_ID }}
|
||||||
|
CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
|
||||||
|
EXTENSION_ID: ${{ vars.CHROME_EXTENSION_ID }}
|
||||||
|
REFRESH_TOKEN: ${{ secrets.CHROME_REFRESH_TOKEN }}
|
||||||
|
run: make deploy_chrome
|
||||||
|
|
||||||
|
deploy-firefox:
|
||||||
|
needs: lint
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Deploy project to Firefox Addons
|
||||||
|
env:
|
||||||
|
WEB_EXT_API_KEY: ${{ vars.FIREFOX_API_KEY }}
|
||||||
|
WEB_EXT_API_SECRET: ${{ secrets.FIREFOX_API_SECRET }}
|
||||||
|
run: make deploy_firefox
|
||||||
|
|||||||
41
CHANGELOG.md
41
CHANGELOG.md
@@ -1,5 +1,46 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### 1.6.1 (2025-11-15)
|
||||||
|
|
||||||
|
- correction du bug de sélection de village dans le marché
|
||||||
|
|
||||||
|
## 1.5.1 (2025-11-13)
|
||||||
|
|
||||||
|
- fonctionnalité de multi-attaques dans la même seconde
|
||||||
|
|
||||||
|
## 1.4.14 (2025-11-13)
|
||||||
|
|
||||||
|
- correction affichage menu avec rapports
|
||||||
|
|
||||||
|
## 1.4.13 (2025-11-13)
|
||||||
|
|
||||||
|
- déploiement automatique sur chrome
|
||||||
|
|
||||||
|
## 1.4.12 (2025-11-11)
|
||||||
|
|
||||||
|
- correction bug menu
|
||||||
|
|
||||||
|
## 1.4.11 (2025-11-11)
|
||||||
|
|
||||||
|
- ajout des data collection permissions
|
||||||
|
|
||||||
|
## 1.4.10 (2025-11-11)
|
||||||
|
|
||||||
|
- correction du fichier metadata.json
|
||||||
|
|
||||||
|
## 1.4.9 (2025-11-11)
|
||||||
|
|
||||||
|
- test déploiement manuel
|
||||||
|
|
||||||
|
## 1.4.8 (2025-11-11)
|
||||||
|
|
||||||
|
- suppression de data_collection_permissions car non supporté pour Android
|
||||||
|
|
||||||
|
## 1.4.7 (2025-11-11)
|
||||||
|
|
||||||
|
- correction du déploiement automatisé
|
||||||
|
- ajout de data_collection_permissions dans manifest.json
|
||||||
|
|
||||||
## 1.4.6 (2025-11-11)
|
## 1.4.6 (2025-11-11)
|
||||||
|
|
||||||
- déploiement automatisé sur firefox
|
- déploiement automatisé sur firefox
|
||||||
|
|||||||
5
Makefile
5
Makefile
@@ -4,7 +4,10 @@ build:
|
|||||||
lint:
|
lint:
|
||||||
web-ext lint
|
web-ext lint
|
||||||
|
|
||||||
deploy:
|
deploy_chrome:
|
||||||
|
chrome-webstore-upload
|
||||||
|
|
||||||
|
deploy_firefox:
|
||||||
web-ext sign --channel listed --amo-metadata metadata.json
|
web-ext sign --channel listed --amo-metadata metadata.json
|
||||||
|
|
||||||
help:
|
help:
|
||||||
|
|||||||
@@ -1,36 +1,45 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "KAplus",
|
"name": "KAplus",
|
||||||
"version": "1.4.6",
|
"version": "1.6.1",
|
||||||
|
|
||||||
"author": "Samuel Campos - netoik.io",
|
"developer": {
|
||||||
"description": "Extension développée pour améliorer l'expérience de jeu KingsAge (fonctionne avec ou sans premium)",
|
"name": "Samuel Campos",
|
||||||
|
"url": "https://git.netoik.io/samuel/kaplus"
|
||||||
|
},
|
||||||
|
"description": "Extension développée pour améliorer l'expérience de jeu KingsAge (fonctionne avec ou sans premium)",
|
||||||
|
|
||||||
"browser_specific_settings": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "{e750d6a9-86ff-4129-aed6-542de03deb79}"
|
"id": "{e750d6a9-86ff-4129-aed6-542de03deb79}",
|
||||||
}
|
"data_collection_permissions": {
|
||||||
},
|
"required": [
|
||||||
|
"websiteContent",
|
||||||
|
"websiteActivity"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["https://*.kingsage.gameforge.com/*"],
|
"matches": ["https://*.kingsage.gameforge.com/*"],
|
||||||
"js": ["src/kaplus.js"],
|
"js": ["src/kaplus.js"],
|
||||||
"css": ["src/kaplus.css"]
|
"css": ["src/kaplus.css"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
"web_accessible_resources": [
|
"web_accessible_resources": [
|
||||||
{
|
{
|
||||||
"matches": ["https://*.kingsage.gameforge.com/*"],
|
"matches": ["https://*.kingsage.gameforge.com/*"],
|
||||||
"resources": ["images/*.svg"]
|
"resources": ["images/*.svg"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
"icons": {
|
"icons": {
|
||||||
"32": "icons/kaplus32.png",
|
"32": "icons/kaplus32.png",
|
||||||
"64": "icons/kaplus64.png",
|
"64": "icons/kaplus64.png",
|
||||||
"100": "icons/kaplus.png",
|
"100": "icons/kaplus.png",
|
||||||
"128": "icons/kaplus128.png"
|
"128": "icons/kaplus128.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
{
|
{
|
||||||
"compatibility": [
|
"version": {
|
||||||
"android",
|
"compatibility": [
|
||||||
"firefox"
|
"android",
|
||||||
],
|
"firefox"
|
||||||
"release_notes": {
|
],
|
||||||
"fr": "- déploiement automatisé sur firefox\n- correction du bug d'affichage du menu Messages et Rapports"
|
"release_notes": {
|
||||||
|
"fr": "- correction du bug de sélection de village dans le marché",
|
||||||
|
"en-US": "- fix bug on selecting village in market"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
252
src/kaplus.js
252
src/kaplus.js
@@ -32,103 +32,175 @@ function createRow(key, value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function shortcutElementReplace(elt, img, text) {
|
function shortcutElementReplace(elt, img, text) {
|
||||||
let imgElements = elt.getElementsByTagName("img");
|
// If more than one hyperlink element found,
|
||||||
for (let i=0; i<imgElements.length; i++) {
|
// then keep the last one but with href of the first one.
|
||||||
if (i === 0) {
|
let aElements = elt.getElementsByTagName("a");
|
||||||
elt.getElementsByTagName("a")[0].classList.add("has_notif");
|
let imgElements = elt.getElementsByTagName("img");
|
||||||
}
|
if (aElements.length > 1 || imgElements.length > 0) {
|
||||||
imgElements[i].remove();
|
aElements[aElements.length - 1].classList.add("has_notif");
|
||||||
i --;
|
aElements[aElements.length - 1].setAttribute("href", aElements[0].getAttribute("href"));
|
||||||
}
|
for (let i = imgElements.length - 1; i >= 0; i--) {
|
||||||
|
imgElements[i].remove();
|
||||||
|
}
|
||||||
|
for (let i = aElements.length - 2; i >= 0; i--) {
|
||||||
|
aElements[i].remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let aElements = elt.getElementsByTagName("a");
|
let spanImageElement = document.createElement("span");
|
||||||
for (i=0; i<aElements.length; i++) {
|
spanImageElement.classList.add("shortcut_element_image");
|
||||||
if (i > 0) {
|
|
||||||
aElements[i].remove();
|
|
||||||
i --;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let spanImageElement = document.createElement("span");
|
let imgElement = document.createElement("img");
|
||||||
spanImageElement.classList.add("shortcut_element_image");
|
imgElement.setAttribute("src", chrome.runtime.getURL("images/" + img + ".svg"));
|
||||||
|
spanImageElement.appendChild(imgElement);
|
||||||
|
|
||||||
let imgElement = document.createElement("img");
|
aElements[0].textContent = "";
|
||||||
imgElement.setAttribute("src", chrome.runtime.getURL("images/"+img+".svg"));
|
aElements[0].appendChild(spanImageElement);
|
||||||
spanImageElement.appendChild(imgElement);
|
|
||||||
|
|
||||||
aElements[0].textContent = "";
|
if (text) {
|
||||||
aElements[0].appendChild(spanImageElement);
|
let spanDescElement = document.createElement("span");
|
||||||
|
spanDescElement.classList.add("shortcut_element_desc");
|
||||||
if (text) {
|
spanDescElement.textContent = text;
|
||||||
let spanDescElement = document.createElement("span");
|
aElements[0].appendChild(spanDescElement);
|
||||||
spanDescElement.classList.add("shortcut_element_desc");
|
}
|
||||||
spanDescElement.textContent = text;
|
|
||||||
aElements[0].appendChild(spanDescElement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Improve main menu display */
|
function main() {
|
||||||
let layCastleTopElements = document.getElementsByClassName("lay_castle_top");
|
/* Exit immediately if not on game page */
|
||||||
if (layCastleTopElements.length === 1) {
|
let layCastleTopElements = document.getElementsByClassName("lay_castle_top");
|
||||||
document.getElementById("banner_skyscraper").remove();
|
if (layCastleTopElements.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let shortcutElements = layCastleTopElements[0].getElementsByClassName("shortcut_element");
|
/* Remove iframe banner */
|
||||||
shortcutElementReplace(shortcutElements[0], "ranking", shortcutElements[0].textContent.replace(/[^0-9]/g, ""));
|
document.getElementById("banner_skyscraper").remove();
|
||||||
shortcutElementReplace(shortcutElements[1], "ally", "");
|
|
||||||
shortcutElementReplace(shortcutElements[2], "profile", "");
|
|
||||||
shortcutElementReplace(shortcutElements[3], "premium", "");
|
|
||||||
shortcutElementReplace(shortcutElements[4], "messages", "");
|
|
||||||
shortcutElementReplace(shortcutElements[5], "tools", "");
|
|
||||||
shortcutElementReplace(shortcutElements[6], "favorites", "");
|
|
||||||
|
|
||||||
let shortcutContainers = layCastleTopElements[0].getElementsByClassName("shortcut_container");
|
/* Improve navbar icons */
|
||||||
shortcutContainers[0].classList.add("shortcut_container_left");
|
let shortcutElements = layCastleTopElements[0].getElementsByClassName("shortcut_element");
|
||||||
shortcutContainers[2].classList.add("shortcut_container_right");
|
shortcutElementReplace(shortcutElements[0], "ranking", shortcutElements[0].textContent.replace(/[^0-9]/g, ""));
|
||||||
|
shortcutElementReplace(shortcutElements[1], "ally", "");
|
||||||
|
shortcutElementReplace(shortcutElements[2], "profile", "");
|
||||||
|
shortcutElementReplace(shortcutElements[3], "premium", "");
|
||||||
|
shortcutElementReplace(shortcutElements[4], "messages", "");
|
||||||
|
shortcutElementReplace(shortcutElements[5], "tools", "");
|
||||||
|
shortcutElementReplace(shortcutElements[6], "favorites", "");
|
||||||
|
|
||||||
|
/* Center navbar */
|
||||||
|
let shortcutContainers = layCastleTopElements[0].getElementsByClassName("shortcut_container");
|
||||||
|
shortcutContainers[0].classList.add("shortcut_container_left");
|
||||||
|
shortcutContainers[2].classList.add("shortcut_container_right");
|
||||||
|
|
||||||
|
/* Parse url params and switch case */
|
||||||
|
let urlParams = new URLSearchParams(window.location.search);
|
||||||
|
let section = urlParams.get("s");
|
||||||
|
let module = urlParams.get("m");
|
||||||
|
let sub = urlParams.get("sub");
|
||||||
|
|
||||||
|
/* Display unit-points on user profile */
|
||||||
|
if (section === "info_player" && (module === "profile" || module === null)) {
|
||||||
|
let mainContentPane = document.getElementsByClassName("contentpane")[1];
|
||||||
|
let borderLists = mainContentPane.getElementsByClassName("borderlist");
|
||||||
|
|
||||||
|
let playerPropertiesTable = borderLists[0];
|
||||||
|
let playerPropertiesRows = playerPropertiesTable.getElementsByTagName("tr");
|
||||||
|
let totalPoints = num(playerPropertiesRows[2].getElementsByTagName("td")[1].textContent);
|
||||||
|
let villagesCount = num(playerPropertiesRows[4].getElementsByTagName("td")[1].textContent);
|
||||||
|
|
||||||
|
let villagesTable = borderLists[1];
|
||||||
|
let villagesRows = villagesTable.getElementsByTagName("tr");
|
||||||
|
let villagesPoints = 0;
|
||||||
|
for (let i = 1; i < villagesRows.length; i += 1) {
|
||||||
|
villagesPoints += num(villagesRows[i].getElementsByTagName("td")[2].textContent);
|
||||||
|
}
|
||||||
|
let villagesBonus = 2250 * Math.max(0, villagesCount - 1);
|
||||||
|
|
||||||
|
let armyPoints = totalPoints - villagesPoints - villagesBonus;
|
||||||
|
let armyPercent = "-";
|
||||||
|
if (villagesCount > 0) {
|
||||||
|
armyPercent = (Math.round(armyPoints / villagesCount) / 100).toString() + " %";
|
||||||
|
}
|
||||||
|
|
||||||
|
playerPropertiesTable.appendChild(createRow("Points troupes:", str(armyPoints)));
|
||||||
|
playerPropertiesTable.appendChild(createRow("% points troupes:", armyPercent));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display unit-points on village overview */
|
||||||
|
if (section === "overview") {
|
||||||
|
let settlements = document.getElementById("settlement").textContent.split("|");
|
||||||
|
let noBorderRows = document.getElementsByClassName("noborder");
|
||||||
|
let villagePointsRow = noBorderRows[0];
|
||||||
|
for (let i = 0; i < noBorderRows.length; i++) {
|
||||||
|
if (noBorderRows[i].textContent.startsWith("Points:")) {
|
||||||
|
villagePointsRow = noBorderRows[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let unitPointsRow = villagePointsRow.cloneNode(true);
|
||||||
|
villagePointsRow.getElementsByTagName("td")[1].textContent = "Points village: " + settlements[3];
|
||||||
|
unitPointsRow.getElementsByTagName("td")[1].textContent = "Points troupes: " + settlements[4];
|
||||||
|
villagePointsRow.after(unitPointsRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow multiple attacks */
|
||||||
|
if (section === "build_barracks" && module === "command" && sub === "send") {
|
||||||
|
let table = document.createElement("table");
|
||||||
|
table.classList.add("borderlist");
|
||||||
|
let tbody = document.createElement("tbody");
|
||||||
|
let tr = document.createElement("tr");
|
||||||
|
let th = document.createElement("th");
|
||||||
|
th.textContent = "Nombre d'attaques:";
|
||||||
|
tr.appendChild(th)
|
||||||
|
let td = document.createElement("td");
|
||||||
|
let input = document.createElement("input");
|
||||||
|
input.setAttribute("type", "number");
|
||||||
|
input.setAttribute("name", "attack_count");
|
||||||
|
input.setAttribute("value", "1");
|
||||||
|
td.appendChild(input);
|
||||||
|
tr.appendChild(td);
|
||||||
|
tbody.appendChild(tr);
|
||||||
|
table.appendChild(tbody);
|
||||||
|
|
||||||
|
let form = document.getElementsByTagName("form")[0];
|
||||||
|
let firstInput = form.getElementsByTagName("input")[0];
|
||||||
|
form.insertBefore(table, firstInput);
|
||||||
|
form.addEventListener("submit", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
let formData = new FormData(this);
|
||||||
|
let attackCount = parseInt(formData.get("attack_count").toString());
|
||||||
|
formData.delete("attack_count");
|
||||||
|
|
||||||
|
let sent = 0;
|
||||||
|
for (let i = 0; i < attackCount; i++) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.onload = function () {
|
||||||
|
sent++;
|
||||||
|
if (sent === attackCount) {
|
||||||
|
window.location.replace(xhr.responseURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhr.open(this.method, this.action, true);
|
||||||
|
xhr.send(formData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix select bug in market */
|
||||||
|
if (section === "build_market" && (module === "send" || module === null)) {
|
||||||
|
let select = document.getElementsByName("village_name")[0];
|
||||||
|
select.removeAttribute("onchange");
|
||||||
|
select.addEventListener("change", function () {
|
||||||
|
let sendX = document.getElementById("send_x");
|
||||||
|
let sendY = document.getElementById("send_y");
|
||||||
|
if (this.selectedIndex === 0) {
|
||||||
|
sendX.value = "";
|
||||||
|
sendY.value = "";
|
||||||
|
} else {
|
||||||
|
let xy = this.value.split("|");
|
||||||
|
sendX.value = xy[0];
|
||||||
|
sendY.value = xy[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display unit-points on user profile */
|
main();
|
||||||
if (document.body.id === "info_player") {
|
|
||||||
let mainContentPane = document.getElementsByClassName("contentpane")[1];
|
|
||||||
let borderLists = mainContentPane.getElementsByClassName("borderlist");
|
|
||||||
|
|
||||||
let playerPropertiesTable = borderLists[0];
|
|
||||||
let playerPropertiesRows = playerPropertiesTable.getElementsByTagName("tr");
|
|
||||||
let totalPoints = num(playerPropertiesRows[2].getElementsByTagName("td")[1].textContent);
|
|
||||||
let villagesCount = num(playerPropertiesRows[4].getElementsByTagName("td")[1].textContent);
|
|
||||||
|
|
||||||
let villagesTable = borderLists[1];
|
|
||||||
let villagesRows = villagesTable.getElementsByTagName("tr");
|
|
||||||
let villagesPoints = 0;
|
|
||||||
for (let i=1; i<villagesRows.length; i+=1) {
|
|
||||||
villagesPoints += num(villagesRows[i].getElementsByTagName("td")[2].textContent);
|
|
||||||
}
|
|
||||||
let villagesBonus = 2250 * Math.max(0, villagesCount - 1);
|
|
||||||
|
|
||||||
let armyPoints = totalPoints - villagesPoints - villagesBonus;
|
|
||||||
let armyPercent = "-";
|
|
||||||
if (villagesCount > 0) {
|
|
||||||
armyPercent = (Math.round(armyPoints / villagesCount) / 100).toString() + " %";
|
|
||||||
}
|
|
||||||
|
|
||||||
playerPropertiesTable.appendChild(createRow("Points troupes:", str(armyPoints)));
|
|
||||||
playerPropertiesTable.appendChild(createRow("% points troupes:", armyPercent));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display unit-points on village overview */
|
|
||||||
if (document.body.id === "overview") {
|
|
||||||
let settlements = document.getElementById("settlement").textContent.split("|");
|
|
||||||
let noBorderRows = document.getElementsByClassName("noborder");
|
|
||||||
let villagePointsRow = noBorderRows[0];
|
|
||||||
for (let i=0; i<noBorderRows.length; i++) {
|
|
||||||
if (noBorderRows[i].textContent.startsWith("Points:")) {
|
|
||||||
villagePointsRow = noBorderRows[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let unitPointsRow = villagePointsRow.cloneNode(true);
|
|
||||||
villagePointsRow.getElementsByTagName("td")[1].textContent = "Points village: " + settlements[3];
|
|
||||||
unitPointsRow.getElementsByTagName("td")[1].textContent = "Points troupes: " + settlements[4];
|
|
||||||
villagePointsRow.after(unitPointsRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user