Feat : add species whitelist (#110)

* Add white_list to server.py

https://github.com/Nachtzuster/BirdNET-Pi/issues/108

* Create whitelist_list.php

* Add whitelist to views

* Make more explicit the usage

* Update views.php

* Align with uppercase

* Align with "species"

https://github.com/Nachtzuster/BirdNET-Pi/issues/108

* Update views.php

* Correct python code

https://github.com/Nachtzuster/BirdNET-Pi/issues/108

* Align clear_all_data.sh

* Align install_services.sh

* Embed whitelist_species_list in PREDICTED_SPECIES_LIST

* Only embed whitelist in predicted list

* Correct python append @dalogue1

https://github.com/Nachtzuster/BirdNET-Pi/issues/108#issuecomment-2183508903

* Update scripts/server.py

Co-authored-by: Nachtzuster <Nachtzuster@users.noreply.github.com>

* Use preexisting functions

Co-authored-by: Nachtzuster <Nachtzuster@users.noreply.github.com>

* Alert not a recommended WoW

---------

Co-authored-by: Nachtzuster <Nachtzuster@users.noreply.github.com>
This commit is contained in:
Alexandre
2024-06-30 10:18:32 +02:00
committed by GitHub
parent 8a92469f45
commit 18693fae06
5 changed files with 138 additions and 0 deletions
+28
View File
@@ -142,6 +142,7 @@ if(isset($_GET['view'])){
<button type=\"submit\" name=\"view\" value=\"Webterm\" form=\"views\">Web Terminal</button>
<button type=\"submit\" name=\"view\" value=\"Included\" form=\"views\">Custom Species List</button>
<button type=\"submit\" name=\"view\" value=\"Excluded\" form=\"views\">Excluded Species List</button>
<button type=\"submit\" name=\"view\" value=\"Whitelisted\" form=\"views\">White-listed Species List</button>
</form>
</div>";
}
@@ -204,6 +205,33 @@ if(isset($_GET['view'])){
}
include('./scripts/exclude_list.php');
}
if($_GET['view'] == "Whitelisted"){
ensure_authenticated();
if(isset($_GET['species']) && isset($_GET['add'])){
$file = './scripts/whitelist_species_list.txt';
$str = file_get_contents("$file");
$str = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $str);
file_put_contents("$file", "$str");
foreach ($_GET['species'] as $selectedOption)
file_put_contents("./scripts/whitelist_species_list.txt", htmlspecialchars_decode($selectedOption, ENT_QUOTES)."\n", FILE_APPEND);
} elseif (isset($_GET['species']) && isset($_GET['del'])){
$file = './scripts/whitelist_species_list.txt';
$str = file_get_contents("$file");
$str = preg_replace('/^\h*\v+/m', '', $str);
file_put_contents("$file", "$str");
foreach($_GET['species'] as $selectedOption) {
$content = file_get_contents("./scripts/whitelist_species_list.txt");
$newcontent = str_replace($selectedOption, "", "$content");
$newcontent = str_replace(htmlspecialchars_decode($selectedOption, ENT_QUOTES), "", "$content");
file_put_contents("./scripts/whitelist_species_list.txt", "$newcontent");
}
$file = './scripts/whitelist_species_list.txt';
$str = file_get_contents("$file");
$str = preg_replace('/^\h*\v+/m', '', $str);
file_put_contents("$file", "$str");
}
include('./scripts/whitelist_list.php');
}
if($_GET['view'] == "File"){
echo "<iframe src='scripts/filemanager/filemanager.php'></iframe>";
}
+1
View File
@@ -24,6 +24,7 @@ echo "Re-creating necessary directories"
sudo -u ${USER} ln -fs $(dirname $my_dir)/exclude_species_list.txt $my_dir
sudo -u ${USER} ln -fs $(dirname $my_dir)/include_species_list.txt $my_dir
sudo -u ${USER} ln -fs $(dirname $my_dir)/whitelist_species_list.txt $my_dir
sudo -u ${USER} ln -fs $(dirname $my_dir)/homepage/* ${EXTRACTED}
sudo -u ${USER} ln -fs $(dirname $my_dir)/model/labels.txt ${my_dir}
sudo -u ${USER} ln -fs $my_dir ${EXTRACTED}
+1
View File
@@ -66,6 +66,7 @@ create_necessary_dirs() {
sudo -u ${USER} ln -fs $my_dir/exclude_species_list.txt $my_dir/scripts
sudo -u ${USER} ln -fs $my_dir/include_species_list.txt $my_dir/scripts
sudo -u ${USER} ln -fs $my_dir/whitelist_species_list.txt $my_dir/scripts
sudo -u ${USER} ln -fs $my_dir/homepage/* ${EXTRACTED}
sudo -u ${USER} ln -fs $my_dir/model/labels.txt ${my_dir}/scripts
sudo -u ${USER} ln -fs $my_dir/scripts ${EXTRACTED}
+3
View File
@@ -135,6 +135,9 @@ def predictSpeciesList(lat, lon, week):
# if there's a custom user-made include list, we only want to use the species in that
if (len(INCLUDE_LIST) == 0):
PREDICTED_SPECIES_LIST.append(s[1])
WHITELIST_LIST = loadCustomSpeciesList(os.path.expanduser("~/BirdNET-Pi/whitelist_species_list.txt"))
for species in WHITELIST_LIST:
PREDICTED_SPECIES_LIST.append(species)
def loadCustomSpeciesList(path):
+105
View File
@@ -0,0 +1,105 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
<div class="customlabels column1">
<form action="" method="GET" id="add">
<h3>All Species Labels</h3>
<input autocomplete="off" size="18" type="text" placeholder="Search Species..." id="whitelist_species_searchterm" name="whitelist_species_searchterm">
<br>
<span>Once the desired species has been highlighted, click it and then click ADD to have it whitelisted. This species will be detected even if below the Species Occurence Frequency Threshold defined in the settings.
This is not a recommended way of working : it is preferable to first try first both Species Occurence models (v1 and v2.4).</span>
<select name="species[]" id="species" multiple size="25">
<?php
error_reporting(E_ALL);
ini_set('display_errors',1);
$filename = './scripts/labels.txt';
$eachline = file($filename, FILE_IGNORE_NEW_LINES);
foreach($eachline as $lines){echo
"<option value=\"".$lines."\">$lines</option>";}
?>
</select>
<input type="hidden" name="add" value="add">
</form>
<div class="customlabels smaller">
<button type="submit" name="view" value="Whitelisted" form="add">>>ADD>></button>
</div>
</div>
<div class="customlabels column2">
<table><td>
<button type="submit" name="view" value="Whitelisted" form="add">>>ADD>></button>
<br><br>
<button type="submit" name="view" value="Whitelisted" form="del">REMOVE</button>
</td></table>
</div>
<div class="customlabels column3">
<form action="" method="GET" id="del">
<h3>Whitelisted Species List</h3>
<br><br><br>
<select name="species[]" id="value2" multiple size="25">
<option disabled value="base">Please Select</option>
<?php
$filename = './scripts/whitelist_species_list.txt';
$eachline = file($filename, FILE_IGNORE_NEW_LINES);
foreach($eachline as $lines){
echo
"<option value=\"".$lines."\">$lines</option>";
}?>
</select>
<input type="hidden" name="del" value="del">
</form>
<div class="customlabels smaller">
<button type="submit" name="view" value="Whitelisted" form="del">REMOVE</button>
</div>
</div>
<script>
// Store the original list of options in a variable
var originalOptions = {};
document.getElementById("add").addEventListener("submit", function(event) {
var speciesSelect = document.getElementById("species");
if (speciesSelect.selectedIndex < 0) {
alert("Please click the species you want to add.");
document.querySelector('.views').style.opacity = 1;
event.preventDefault();
}
});
var search_term = document.querySelector("input#whitelist_species_searchterm");
search_term.addEventListener("keyup", function() {
filterOptions("species");
});
// Function to filter options in a select element
function filterOptions(id) {
var input = document.getElementById("whitelist_species_searchterm");
var filter = input.value.toUpperCase();
var select = document.getElementById(id);
var options = select.getElementsByTagName("option");
// If the original list of options for this select element hasn't been stored yet, store it
if (!originalOptions[id]) {
originalOptions[id] = Array.from(options).map(option => option.value);
}
// Clear the select element
while (select.firstChild) {
select.removeChild(select.firstChild);
}
// Populate the select element with the filtered labels
originalOptions[id].forEach(label => {
if (label.toUpperCase().indexOf(filter) > -1) {
let option = document.createElement('option');
option.value = label;
option.text = label;
select.appendChild(option);
}
});
}
</script>