7 Commits

Author SHA1 Message Date
f841780ed9 Fix bug select in market
All checks were successful
Continuous Deployment / lint (push) Successful in 28s
Continuous Deployment / deploy-chrome (push) Successful in 32s
Continuous Deployment / deploy-firefox (push) Successful in 1m50s
2025-11-15 13:17:40 +01:00
c22c2fb254 Feature multi-attack in same second
All checks were successful
Continuous Deployment / lint (push) Successful in 26s
Continuous Deployment / deploy-chrome (push) Successful in 32s
Continuous Deployment / deploy-firefox (push) Successful in 5m36s
2025-11-13 20:13:50 +01:00
4fe2922e5a Fix display navbar with reports
All checks were successful
Continuous Deployment / lint (push) Successful in 26s
Continuous Deployment / deploy-chrome (push) Successful in 31s
Continuous Deployment / deploy-firefox (push) Successful in 2m43s
2025-11-13 10:31:12 +01:00
4f1d5442be Continuous deployment on Chrome
Some checks failed
Continuous Deployment / lint (push) Successful in 28s
Continuous Deployment / deploy-chrome (push) Successful in 31s
Continuous Deployment / deploy-firefox (push) Failing after 26s
2025-11-13 01:17:56 +01:00
45d5200e61 Fix bug menu
All checks were successful
Continuous Deployment / lint (push) Successful in 29s
Continuous Deployment / deploy (push) Successful in 5m8s
2025-11-11 23:39:57 +01:00
10de4507af Add data collection permissions
All checks were successful
Continuous Deployment / lint (push) Successful in 30s
Continuous Deployment / deploy (push) Successful in 56s
2025-11-11 17:34:00 +01:00
a37d54cd2e Fix metadata.json format
All checks were successful
Continuous Deployment / lint (push) Successful in 30s
Continuous Deployment / deploy (push) Successful in 3m20s
2025-11-11 16:36:50 +01:00
6 changed files with 240 additions and 106 deletions

View File

@@ -14,13 +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
env: env:
WEB_EXT_API_KEY: ${{ vars.WEB_EXT_API_KEY }} CLIENT_ID: ${{ vars.CHROME_CLIENT_ID }}
WEB_EXT_API_SECRET: ${{ secrets.WEB_EXT_API_SECRET }} CLIENT_SECRET: ${{ secrets.CHROME_CLIENT_SECRET }}
run: make deploy 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

View File

@@ -1,5 +1,37 @@
# 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) ## 1.4.8 (2025-11-11)
- suppression de data_collection_permissions car non supporté pour Android - suppression de data_collection_permissions car non supporté pour Android

View File

@@ -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:

View File

@@ -1,14 +1,23 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "KAplus", "name": "KAplus",
"version": "1.4.8", "version": "1.6.1",
"author": "Samuel Campos - netoik.io", "developer": {
"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)", "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"
]
}
} }
}, },

View File

@@ -1,9 +1,12 @@
{ {
"compatibility": [ "version": {
"android", "compatibility": [
"firefox" "android",
], "firefox"
"release_notes": { ],
"fr": "- suppression de data_collection_permissions car non supporté pour Android" "release_notes": {
"fr": "- correction du bug de sélection de village dans le marché",
"en-US": "- fix bug on selecting village in market"
}
} }
} }

View File

@@ -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);
}