Compare commits

...

7 commits

Author SHA1 Message Date
554ceaf5be
peertube/trom
All checks were successful
/ job (push) Successful in 1m17s
2025-03-24 14:13:00 +01:00
8b49d6958c
lint 2025-02-22 21:23:05 +01:00
6a985e0b89
lint 2025-02-22 20:56:41 +01:00
77e12933fd
lint 2025-02-22 20:34:26 +01:00
7c5916ceb0
lint 2025-02-18 22:05:22 +01:00
2a32fee946
lint 2025-02-18 21:16:35 +01:00
3dacff41a5
lint 2025-02-18 20:58:05 +01:00
3 changed files with 216 additions and 196 deletions

205
build.py
View file

@ -12,13 +12,13 @@ def run(*args):
def main():
time = datetime.datetime.now()
time_id = time.strftime('%Y%m%d%H%M%S')
style = 'css'
script = 'js'
time_id = time.strftime("%Y%m%d%H%M%S")
style = "css"
script = "js"
root = os.path.dirname(os.path.realpath(__file__))
input_directory = os.path.join(root, 'in')
out = os.path.join(root, 'out')
web = os.path.join(out, 'web')
input_directory = os.path.join(root, "in")
out = os.path.join(root, "out")
web = os.path.join(out, "web")
if os.path.exists(web):
shutil.rmtree(web)
os.makedirs(web)
@ -26,17 +26,17 @@ def main():
css = os.path.join(gen, style)
js = os.path.join(gen, script)
#
run('rsync', '--archive', f'{input_directory}/', f'{web}/')
run("rsync", "--archive", f"{input_directory}/", f"{web}/")
for directory in [css, js]:
os.makedirs(directory)
#
link_gv = os.path.join(root, 'link.gv')
link_svg = os.path.join(gen, 'link.svg')
run('dot', link_gv, '-Tsvg', '-o', link_svg)
with open(link_svg, 'br') as f:
link_text = f.read().decode('u8')
page_file = os.path.join(web, 'index.html')
page_text = f'''\
link_gv = os.path.join(root, "link.gv")
link_svg = os.path.join(gen, "link.svg")
run("dot", link_gv, "-Tsvg", "-o", link_svg)
with open(link_svg, "br") as f:
link_text = f.read().decode("u8")
page_file = os.path.join(web, "index.html")
page_text = f"""\
<!DOCTYPE html>
<html>
@ -195,9 +195,9 @@ Last update: {time.strftime('%Y/%m/%d %H:%M:%S')}
</body>
</html>
'''
css_file = os.path.join(css, 'index.css')
css_text = f'''\
"""
css_file = os.path.join(css, "index.css")
css_text = """\
@media screen and (max-aspect-ratio: 10/16) {{
body {{
@ -327,9 +327,9 @@ border-color: rgb(255,0,255);
border-style: solid;
border-width: 1px;
}}
'''
js_file = os.path.join(js, 'index.js')
js_text = f'''\
"""
js_file = os.path.join(js, "index.js")
js_text = """\
function check(tab) {{
const tabs = tab.split('/')
let id = 'tab'
@ -376,23 +376,23 @@ function main() {{
function swap() {{
document.body.classList.toggle('dark')
}}
'''
# {link_text}
with open(page_file, 'bw') as f:
f.write(page_text.encode('u8'))
with open(css_file, 'bw') as f:
f.write(css_text.encode('u8'))
with open(js_file, 'bw') as f:
f.write(js_text.encode('u8'))
"""
# {link_text}
with open(page_file, "bw") as f:
f.write(page_text.encode("u8"))
with open(css_file, "bw") as f:
f.write(css_text.encode("u8"))
with open(js_file, "bw") as f:
f.write(js_text.encode("u8"))
tabs = {
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'about': f'''\
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"about": """\
About
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'bio': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"bio": """\
<h1>Marc Beninca</h1>
Welcome to a recap attempt of my IT life!
@ -418,15 +418,15 @@ I had the occasion to develop projects in:
</ul>
To be continued
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'books': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"books": """\
<ul>
<li><a href="https://www.tradepub.com">TradePub</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'buy': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"buy": """\
<ul>
<li><a href="https://www.i-comparateur.com">i-comparateur</a></li>
</ul>
@ -451,24 +451,24 @@ To be continued…
<ul>
<li><a href="https://www.leboncoin.fr">Le bon coin</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'comments': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"comments": """\
<ul>
<li><a href="https://www.youtube.com/@LogicallyAnswered/videos">Logically Answered</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'cv': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"cv": """\
<ul class="cards">
<li class="card"><a href="pdf/cv.en.pdf">
<img src="img/en.svg" /><br />English</a></li>
<li class="card"><a href="pdf/cv.fr.pdf">
<img src="img/fr.svg" /><br />Français</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'repos': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"repos": """\
<ul>
<li><a href="https://forge.rwx.work/marc.beninca">RWX</a></li>
</ul><ul>
@ -509,9 +509,9 @@ To be continued…
<ul>
<li>Gforge</li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'health': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"health": """\
<ul>
<li><a href="https://www.youtube.com/@chubbyemu/videos">Chubby Emu</a></li>
<li><a href="https://www.youtube.com/@drekberg/videos">Sten Ekberg</a></li>
@ -524,9 +524,9 @@ To be continued…
<ul>
<li><a href="https://www.youtube.com/@ivredevie/videos">Ivre de vie</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'id': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"id": """\
<table>
<tr><th colspan="2">OpenPGP</th><td colspan="3" rowspan="4"><img src="img/marc.jpeg" /></td></tr>
@ -549,7 +549,7 @@ To be continued…
<td colspan="3"><a href="https://devs.live/users/marc_beninca">Pleroma</a></td>
<td><a href="https://vimeo.com/marcbeninca">Vimeo</a></td>
</tr><tr>
<td colspan="2"><a href="https://peertube.iriseden.eu/a/marc_beninca">PeerTube</a></td>
<td colspan="2"><a href="https://videos.trom.tf/@marc_beninca">PeerTube</a></td>
<td><a href="https://openstreetmap.org/user/Marc Beninca">OpenStreetMap</a></td>
<td><a href="https://youtube.com/@marc.beninca">YouTube</a></td>
</tr><tr>
@ -579,9 +579,9 @@ To be continued…
<tr><td colspan="2"><a href="https://forge.rwx.work/marc.beninca">forge.rwx.work</a></td></tr>
</table>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'learn': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"learn": """\
<ul>
<li><a href="https://roadmap.sh">Roadmap</a></li>
<li><a href="https://teachyourselfcs.com">Teach Yourself Computer Science</a></li>
@ -597,9 +597,9 @@ To be continued…
<ul>
<li><a href="https://overthewire.org">Over The Wire</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'links': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"links": """\
<ul>
<li><a href="https://marc-beninca.8b.io">8bio</a></li>
<li><a href="https://allmylinks.com/marc-beninca">AllMyLinks</a></li>
@ -639,9 +639,9 @@ To be continued…
<li><a href="https://vu.fr/marc-beninca">Vu.Fr</a></li>
<li><a href="https://zaap.bio/marc.beninca">Zaap</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'music': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"music": """\
<ul>
<li><a href="https://www.youtube.com/watch?v=_ITiwPMUzho">3 AM Coding Session</a></li>
</ul>
@ -666,9 +666,9 @@ To be continued…
<ul>
<li><a href="http://radio.garden/visit/pessac">Radio Garden</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'profiles': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"profiles": """\
<ul class="cards">
<li class="card"><a href="https://forge.rwx.work/marc.beninca">
<img src="img/ForgeJo.svg" /><br />ForgeJo</a></li>
@ -679,7 +679,7 @@ To be continued…
</ul>
<hr />
<ul class="cards">
<li class="card"><a href="https://peertube.iriseden.eu/c/marc.beninca">
<li class="card"><a href="https://videos.trom.tf/@marc.beninca">
<img src="img/PeerTube.png" /><br />PeerTube</a></li>
<li class="card"><a href="https://pixelfed.social/marc.beninca">
<img src="img/PixelFed.svg" /><br />PixelFed</a></li>
@ -693,9 +693,9 @@ To be continued…
<li class="card"><a href="https://instagram.com/marc.beninca">
<img src="img/InstaGram.png" /><br />InstaGram</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'lsgm': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"lsgm": """\
<h1>Live Scan Grub Menu</h1>
Setup a whole EFI System Partition:
<ul>
@ -708,8 +708,8 @@ BASH experimenting:
<ul>
<li><a href="https://youtu.be/mx2lhm7qClc">2023/05/04: 1st boot into QCOW storage with encrypted data partition</a></li>
</ul>
''',
'ofsp': f'''\
""",
"ofsp": """\
<h1>Operating File System Profile</h1>
Build from mirror a full operating system bootable file image:
<ul>
@ -730,9 +730,9 @@ BASH experimenting:
<li><a href="https://youtu.be/YhoY2gisXg4">2023/06/20: Graphical User Interface too</a></li>
<li><a href="https://youtu.be/PSHswxc9oU8">2023/06/13: Textual User Interface only</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'social': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"social": """\
<ul>
<li><a href="https://calckey.org">Calckey</a></li>
<li><a href="https://joinmastodon.org">Mastodon</a></li>
@ -759,9 +759,9 @@ BASH experimenting:
<ul>
<li><a href="https://nextdoor.com">NextDoor</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'software': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"software": """\
<ul>
<li><a href="https://developer.puri.sm/Librem5">Librem 5</a></li>
</ul>
@ -783,16 +783,16 @@ BASH experimenting:
<li><a href="https://www.talos.dev">Talos Linux</a></li>
<li><a href="https://www.endlessos.org/os">Endless OS</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'style': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"style": """\
<ul>
<li><input type="checkbox" id="dark" onclick="swap()">Dark</input></li>
<li><input type="checkbox" id="debug" onclick="debug()">Debug</input></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'tasks': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"tasks": """\
<ul>
<li>categorize music</li>
</ul>
@ -805,9 +805,9 @@ BASH experimenting:
<ul>
<li>implement search</li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'tbm': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"tbm": """\
<ul class="cards">
<li class="card"><a href="https://montempsreel.infotbm.com/arret/1224">Bertin B</a></li>
<li class="card"><a href="https://montempsreel.infotbm.com/arret/7">Bertin V</a></li>
@ -816,9 +816,9 @@ BASH experimenting:
<li class="card"><a href="https://montempsreel.infotbm.com/arret/7802">Médiathèque V</a></li>
<li class="card"><a href="https://montempsreel.infotbm.com/arret/371">Peixotto V</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'trips': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"trips": """\
<ul>
<li>Belgium<ul>
<li>Brussels</li>
@ -860,9 +860,9 @@ BASH experimenting:
<li>Tennessee</li>
</ul></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'vegan': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"vegan": """\
<ul>
<li><a href="https://www.youtube.com/@CheapLazyVegan/videos">Cheap Lazy Vegan</a></li>
<li><a href="https://www.youtube.com/@gazoakleychef/videos">Gaz Oakley</a></li>
@ -886,9 +886,9 @@ BASH experimenting:
<li><a href="https://www.youtube.com/@MarieSweetandSour/videos">Marie Sweet and Sour</a></li>
<li><a href="https://www.youtube.com/@SebastienKardinal/videos">Sébastien Kardinal</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'others': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"others": """\
<ul>
<li><a href="https://bsky.app/profile/marc-beninca.bsky.social">Blue Sky</a></li>
<li><a href="https://buymeacoffee.com/marc.beninca">Buy Me A Coffee</a></li>
@ -902,7 +902,6 @@ BASH experimenting:
<li><a href="https://minds.com/marc_beninca">Minds</a></li>
<li><a href="https://odysee.com/@marc.beninca">Odysee</a></li>
<li><a href="https://paypal.me/MarcBeninca">PayPal</a></li>
<li><a href="https://peertube.iriseden.eu/a/marc_beninca">PeerTube</a></li>
<li><a href="https://pinterest.com/marc_beninca">Pinterest</a></li>
<li><a href="https://marcbeninca.podia.com">Podia</a></li>
<li><a href="https://app.revolt.chat/invite/01FREKCG3P2P0YMAHQSCPSW4GD">Revolt</a></li>
@ -918,15 +917,15 @@ BASH experimenting:
<ul>
<li><a href="">KissBank</a></li>
</ul>
''',
#⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
'unsorted': f'''\
""",
# ⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅
"unsorted": """\
<ul>
<li><a href="https://foss.events">FOSS Events</a></li>
</ul>
''',
""",
}
if __name__ == '__main__':
if __name__ == "__main__":
main()

View file

@ -1,61 +1,83 @@
from __future__ import annotations
import os
from pathlib import Path
import subprocess
PORT = 22
USER = 'mspe'
ROOT = 'public_html'
PROTOCOL = 'https'
USER = "mspe"
ROOT = "public_html"
PROTOCOL = "https"
DIR = False
class PubNix:
def __init__(self, dn,
ssh=None, port=PORT, user=USER,
root=ROOT, dir=DIR, web=None, sub=None):
def __init__(
self,
dn,
ssh: str | None = None,
port: int = PORT,
user: str = USER,
root: str = ROOT,
dir: bool = DIR,
web: str | None = None,
sub: bool | None = None,
):
self.dn = dn
self.ssh = f'{ssh}.{self.dn}' if ssh else self.dn
self.ssh = f"{ssh}.{self.dn}" if ssh else self.dn
self.port = port
self.user = user
self.root = root
self.web = f'{web}.{self.dn}' if web else self.dn
self.web = f"{web}.{self.dn}" if web else self.dn
if sub:
self.fqdn = f'{self.user}.{self.web}'
self.fqdn = f"{self.user}.{self.web}"
self.context = None
else:
self.fqdn = self.web
self.context = f'~{self.user}'
self.path = os.path.join(self.root, self.fqdn) if dir else self.root
self.target = f'{self.user}@{self.ssh}:{self.path}'
self.url = [f'{PROTOCOL}:', str(), self.fqdn]
self.context = f"~{self.user}"
self.path = (Path(self.root) / self.fqdn) if dir else self.root
self.target = f"{self.user}@{self.ssh}:{self.path}"
self.url = [f"{PROTOCOL}:", "", self.fqdn]
if self.context:
self.url.append(self.context)
self.url = '/'.join(self.url)
self.url = "/".join(self.url)
def capturun(self, *args):
return self.run(*args, capture_output=True)
def run(self, *args, **kwargs):
return subprocess.run(['ssh',
'-o', 'LogLevel Error',
'-p', str(self.port),
f'{self.user}@{self.ssh}',
'--',
*args,
], **kwargs)
return subprocess.run(
[
"ssh",
"-o",
"LogLevel Error",
"-p",
str(self.port),
f"{self.user}@{self.ssh}",
"--",
*args,
],
**kwargs,
)
def disk_free(self):
process = self.capturun('df', '-h', os.curdir)
return process.stdout.decode('UTF-8').strip()
def disk_free(self) -> str:
"""Fetch free space information."""
process = self.capturun("df", "-h", os.curdir)
return process.stdout.decode("UTF-8").strip()
def os(self):
ps = self.capturun('cat', '/etc/os-release')
def os(self) -> str:
"""Fetch Operating System release information."""
ps = self.capturun("cat", "/etc/os-release")
if ps.returncode == 0:
for line in ps.stdout.decode('UTF-8').strip().split(os.linesep):
if 'PRETTY_NAME' in line:
return line.split('=')[1].split('"')[1]
for line in ps.stdout.decode("UTF-8").strip().split(os.linesep):
if "PRETTY_NAME" in line:
text = line.split("=")[1].split('"')[1]
break
else:
text = ""
return text
else:
return self.capturun('uname', '-sr').stdout.decode('UTF-8').strip()
return self.capturun("uname", "-sr").stdout.decode("UTF-8").strip()
def __str__(self):
def __str__(self) -> str:
"""Return target & url."""
return os.linesep.join([self.target, self.url])

121
sync.py
View file

@ -1,79 +1,78 @@
#! /usr/bin/env python3
"""Synchronize to remote pubnixes."""
import os
from __future__ import annotations
from logging import log
from os import sep
from pathlib import Path
from pubnix import PubNix
import subprocess
import pubnix
ARGS = [
{'dn':'blinkenshell.org',
'ssh': 'ssh', 'port': 2222, 'web': 'u', 'sub': True},
{'dn':'ctrl-c.club', 'sub': False},
{'dn':'dimension.sh', 'sub': True},
{'dn':'envs.net', 'sub': True},
{'dn':'freeshell.de', 'sub': False},
# {'dn':'hextilde.xyz', 'sub': True},
{'dn':'insomnia247.nl', 'dir': True, 'sub': True},
{'dn':'p.projectsegfau.lt', 'sub': True},
# {'dn':'pubnix.pink', 'web': 'sites', 'sub': False},
{'dn':'rawtext.club', 'sub': False},
{'dn':'rw.rs', 'sub': False},
{'dn':'thunix.net', 'sub': False},
{'dn':'tilde.32bit.cafe', 'root': 'www', 'sub': False},
{'dn':'tilde.cafe', 'sub': True},
{'dn':'tilde.club', 'sub': False},
{'dn':'tilde.fun', 'root': 'html', 'sub': False},
{'dn':'tilde.green', 'sub': False},
{'dn':'tilde.guru', 'sub': False},
{'dn':'tilde.institute', 'sub': True},
{'dn':'tilde.pink', 'sub': False},
{'dn':'tilde.team', 'sub': True},
{'dn':'tilde.town', 'sub': False},
# {'dn':'trash.town', 'sub': False},
# permissions
# {'dn':'sdf.org', 'root': 'html', 'sub': True},
{
"dn": "blinkenshell.org",
"ssh": "ssh",
"port": 2222,
"web": "u",
"sub": True,
},
{"dn": "ctrl-c.club", "sub": False},
{"dn": "dimension.sh", "sub": True},
{"dn": "envs.net", "sub": True},
{"dn": "freeshell.de", "sub": False},
{"dn": "insomnia247.nl", "dir": True, "sub": True},
{"dn": "p.projectsegfau.lt", "sub": True},
{"dn": "rawtext.club", "sub": False},
{"dn": "rw.rs", "sub": False},
{"dn": "thunix.net", "sub": False},
{"dn": "tilde.32bit.cafe", "root": "www", "sub": False},
{"dn": "tilde.cafe", "sub": True},
{"dn": "tilde.club", "sub": False},
{"dn": "tilde.fun", "root": "html", "sub": False},
{"dn": "tilde.green", "sub": False},
{"dn": "tilde.guru", "sub": False},
{"dn": "tilde.institute", "sub": True},
{"dn": "tilde.pink", "sub": False},
{"dn": "tilde.team", "sub": True},
{"dn": "tilde.town", "sub": False},
# old
{'dn':'fr.tild3.org', 'sub': True},
{'dn':'remotes.club', 'port': 9022, 'root': 'web', 'sub': True},
{'dn':'squiggle.city', 'sub': False},
# down
# {'dn':'aussies.space', 'sub': False},
# {'dn':'heathens.club', 'root': 'www', 'sub': False},
# {'dn':'vern.cc', 'sub': True},
{"dn": "fr.tild3.org", "sub": True},
{"dn": "remotes.club", "port": 9022, "root": "web", "sub": True},
{"dn": "squiggle.city", "sub": False},
]
PUBNIXES = [pubnix.PubNix(**args) for args in ARGS]
PUBNIXES = [PubNix(**args) for args in ARGS]
def sync(root, pubnix, exclude=None):
def sync(root: Path, pubnix: PubNix, exclude: list[str] | None = None) -> None:
"""Synchronize local root directory with pubnix."""
args = [
'rsync',
'--archive',
'--checksum',
'--delete-before',
'--rsh', f"ssh -o 'LogLevel Error' -p {pubnix.port}",
'--partial',
'--progress',
'--verbose',
os.path.join(root, str()),
"rsync",
"--archive",
"--checksum",
"--delete-before",
"--rsh",
f"ssh -o 'LogLevel Error' -p {pubnix.port}",
"--partial",
"--progress",
"--verbose",
f"{root}{sep}",
]
for item in exclude:
args.extend(['--exclude', os.path.join(str(), item)])
args.append(os.path.join(pubnix.target, str()))
if exclude:
for item in exclude:
args.extend(["--exclude", f"{sep}{item}"])
args.append(f"{pubnix.target}{sep}")
subprocess.call(args, stdout=subprocess.DEVNULL)
def main():
root = os.path.dirname(os.path.realpath(__file__))
root = os.path.join(root, 'out', 'web')
dns_length = max([len(pubnix.dn) for pubnix in PUBNIXES])
for pubnix in PUBNIXES:
print()
print(pubnix)
# print(f'{pubnix.dn.rjust(dns_length)} → ', end=str(), flush=True)
sync(root, pubnix, exclude=['__pycache__', 'pgp.asc'])
# print(pubnix.disk_free())
# print(pubnix.os())
def main() -> None:
"""Synchronize content on remote pubnixes."""
root = Path(__file__).resolve().parent / "out" / "web"
for pn in PUBNIXES:
log()
log(pn)
sync(root, pn, exclude=["__pycache__", "pgp.asc"])
if __name__ == '__main__':
if __name__ == "__main__":
main()