Add about_simple updater from github (#2328)

* Generator for updating the about-page in PP from github.

* Fixing typo

* Rename generate_ui-about-simple.ccp.py to generate_ui-about-simple.cpp.py

Rename file, fix typo
This commit is contained in:
Benjamin Møller 2024-11-05 03:41:08 +01:00 committed by GitHub
parent 8df05a57ea
commit da5322765d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 187 additions and 1 deletions

View File

@ -2,7 +2,7 @@
# Convert png icons to bitmap.hpp inspired by
# make_bitmap.py - Copyright (C) 2016 Furrtek
# Convert bitmap.hpp to icons inspyred by
# Convert bitmap.hpp to icons inspired by
# bitmap_arr_reverse_decode.py - Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
# bitmap_arr_reverse_decode.py - Copyleft (ɔ) 2024 zxkmm with the GPL license
# Copysomething (c) 2024 LupusE with the license, needed by the PortaPack project
@ -138,6 +138,8 @@ def pp_write_bitmaphpp(pngicons_path, hpp_outpath):
print("Find your bitmap.hpp at", hpp_outpath)
### Convert from a bitmap.hpp file one or all icons in png.
###########################################################

View File

@ -0,0 +1,184 @@
#!/usr/bin/env python3
# Copysomething (c) 2024 LupusE with the license, needed by the PortaPack project
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
import argparse
import json
import os
import re
import requests
import sys
cppheader = """#include "ui_about_simple.hpp"
namespace ui {
// Information: a line starting with a '#' will be yellow coloured
const std::"""
cppfooter = """
AboutView::AboutView(NavigationView& nav) {
add_children({&menu_view,
&button_ok});
button_ok.on_select = [&nav](Button&) {
nav.pop();
};
menu_view.on_left = [this]() {
button_ok.focus();
};
menu_view.on_right = [this]() {
button_ok.focus();
};
for (const std::string& authors_line : authors_list) {
// if it's starting with #, it's a title and we have to substract the '#' and paint yellow
if (authors_line.size() > 0) {
if (authors_line[0] == '#') {
menu_view.add_item(
{authors_line.substr(1, authors_line.size() - 1),
ui::Theme::getInstance()->fg_yellow->foreground,
nullptr,
nullptr});
} else {
menu_view.add_item(
{authors_line,
Theme::getInstance()->bg_darkest->foreground,
nullptr,
nullptr});
}
}
}
}
void AboutView::focus() {
menu_view.focus();
// put focus on last text line to make it more obvious that list is scrollable
menu_view.set_highlighted(10);
}
} /* namespace ui */
"""
def get_contributors(url):
contributors_list = [] ## Raw list of contributor names
logins = json.loads(requests.get(url).text)
try:
print(f"Could not reach URL - Error: {logins['status']} Messsage: {logins['message']}")
## Status f.ex. 404 / message f.ex. "Not Found" or "API rate limit exceeded for...".
sys.exit()
except:
pass
for gh_user in logins:
clean_ghuser = re.sub('[^a-zA-Z0-9-]', '.', gh_user['login']) ## replace non printable character with .
contributors_list.append(clean_ghuser)
contributor_id = 0
contrib_format = [] ## Formated list of contributors, max 30 char per line
for contributor in contributors_list:
contributor_id +=1
contrib_format.append(contributor)
line_len = len(",".join(contrib_format).split("\n")[-1])
if contributor_id < len(contributors_list) and line_len+len(contributors_list[contributor_id]) >=30:
contrib_format.append("\n")
return(",".join(contrib_format).replace("\n,","\n")) # replace to erase first , in followup lines
def generate_content(projects):
project_contrib = []
project_contrib.append("string authors_list[] = {\n")
project_contrib.append(" \"# * List of contributors * \",\n")
for project in projects:
project_contrib.append(" \" \",\n")
project_contrib.append(f" \"#{project[0]}:\",\n")
url = f"https://api.github.com/repos/{project[1]}/{project[2]}/contributors?per_page={project[3]}"
contrib_mayhem = get_contributors(url).split("\n")
for line in contrib_mayhem:
project_contrib.append(f" \"{line}\",\n")
project_contrib.append(" \" \"};\n")
return("".join(project_contrib))
def pp_create_ui_about_simple_cpp(cpp_file, cppheader, cppcontent, cppfooter):
uiaboutsimplecpp_file = []
uiaboutsimplecpp_file.append(cppheader)
uiaboutsimplecpp_file.append(cppcontent)
uiaboutsimplecpp_file.append(cppfooter)
with open(cpp_file, "w", encoding="utf-8") as file:
file.writelines(uiaboutsimplecpp_file)
print("Find your ui_simple_about.cpp at", cpp_file)
def pp_change_ui_about_simple_cpp(cpp_file, cppcontent):
content = []
content_pattern = re.compile(r"string authors_list\[\] = {\n(?:\s+(?:.*,\n)+\s+.*};\n)", re.MULTILINE)
# Read original file
with open(cpp_file, 'r') as file:
filedata = file.read()
# Replace regex content with generated list
for match in content_pattern.finditer(filedata):
content.append(match[0])
filedata = filedata.replace(content[0], cppcontent)
# Write new file
with open(cpp_file, 'w') as file:
file.write(filedata)
projects = []
## Format: Project title, Github name, Github repo, Amount of contributors
projects.append(["Mayhem-Firmware","portapack-mayhem","mayhem-firmware","50"])
projects.append(["Havoc","furrtek","portapack-havoc","50"])
projects.append(["PortaPack","sharebrained","portapack-hackrf","50"])
projects.append(["HackRF","mossmann","hackrf","15"])
## processing
#############
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="This tool updates the ui_about_simple.cpp from PortaPack firmware from Github contributors. If no file is given, the file will be generated.",
)
parser.add_argument("--cpp", help="Path of the source ui_about_simple.cpp to update.", default="ui_about_simple.cpp")
parser.add_argument("--new","-n", help="Generate a new file")
args = parser.parse_args()
if args.cpp:
cpp_file = os.path.join(os.getcwd(),args.cpp)
else:
cpp_file = os.path.join(os.getcwd(),"ui_about_simple.cpp")
cppcontent = generate_content(projects)
if args.new or not os.path.isfile(args.cpp):
pp_create_ui_about_simple_cpp(cpp_file, cppheader, cppcontent, cppfooter)
else:
pp_change_ui_about_simple_cpp(cpp_file, cppcontent)