From b3c0f821cf03daa79be4cf57e79f6428acd38177 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Sat, 30 Apr 2022 19:44:08 +0200 Subject: make it useful --- format.py | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hints.json | 90 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 202 insertions(+), 12 deletions(-) create mode 100755 format.py diff --git a/format.py b/format.py new file mode 100755 index 0000000..7873494 --- /dev/null +++ b/format.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: CC0-1.0 +# +# Copyright (C) 2022 Wojtek Kosior +# +# Available under the terms of Creative Commons Zero v1.0 Universal. + +import json +import random +import click +import sys +from pathlib import Path + +MAX_WIDTH = 80 +INDENT = 3 + +here = Path(__file__).resolve().parent + +trans_suggestions = { + 'en': 'suggestions', + 'pl': 'sugestie' +} + +trans_hint = { + 'en': 'Random digital freedom hint', + 'pl': 'Losowa wskazówka dla wolności cyfrowej' +} + +trans_note = { + 'en': 'FSF concerns', + 'pl': 'zastrzeżenia FSF' +} + +no_dangling_chars_langs = {'pl'} + +def wrap_text_block(text, max_width, forbid_dangling_chars=False, + subsequent_indent=0): + lines = [] + + for paragraph in text.split('\n'): + line = '' + accumulated_word = '' + + for word in paragraph.split(' '): + if not word: + continue + + accumulated_word += word + + if forbid_dangling_chars and len(accumulated_word) == 1: + accumulated_word += ' ' + continue + + if len(line) + len(accumulated_word) + 1 <= max_width: + if line: + line += ' ' + line += accumulated_word + else: + lines.append(line) + line = ' ' * subsequent_indent + accumulated_word + + accumulated_word = '' + + if line and line != ' ' * subsequent_indent: + lines.append(line) + line = '' + + return lines + +def format_hint(hint, hint_id, langs, max_width=MAX_WIDTH, indent=INDENT): + lines = [] + + for lang in langs: + lines.append(f'{trans_hint[lang]} #{hint_id}: {hint["name"][lang]}') + + block = wrap_text_block(hint['text'][lang], max_width - indent, + lang in no_dangling_chars_langs) + + lines.extend(' ' * indent + l for l in block) + + suggested = hint.get('suggested') + if suggested: + lines.append('/'.join(trans_suggestions[l] for l in langs) + ':') + + for sug_id, sug in enumerate(suggested): + sug_line = f'{sug_id + 1}. {sug["name"]} <{sug["url"]}>' + block = wrap_text_block(sug_line, max_width, + lang in no_dangling_chars_langs, indent) + lines.extend(block) + + note = sug.get('note') + if not note: + continue + + for lang in langs: + block = wrap_text_block(f'{trans_note[lang]}: {note[lang]}', + max_width - indent, + lang in no_dangling_chars_langs, indent) + + lines.extend(' ' * indent + l for l in block) + + return '\n'.join(lines) + +hints = json.load((here / 'hints.json').open()) + +@click.command() +@click.option('-i', '--hint-id', default='-1', type=click.types.INT, + show_default=True, help='which hint to format (-1 for random)') +def main(hint_id): + if hint_id == -1: + [(hint_id, hint)] = random.sample([*hints.items()], 1) + else: + hint_id = str(hint_id) + hint = hints.get(hint_id) + + if hint is None: + print("No such hint!", file=sys.stderr) + return sys.exit(1) + + print(format_hint(hint, hint_id, [*hint['name'].keys()])) + +if __name__ == '__main__': + main() diff --git a/hints.json b/hints.json index b90671f..be48117 100644 --- a/hints.json +++ b/hints.json @@ -3,7 +3,7 @@ "name": { "en": "web browsers", "pl": "przeglądarki internetowe" - } + }, "text": { "en": "Running Google Chrome, Mozilla Firefox of Apple Safari? Consider switching to an ethical browser that respects your freedom.", "pl": "Używasz Google Chrome, Mozilla Firefox lub Apple Safari? Rozważ przerzucenie się na etyczną przeglądarkę, która szanuje Twoją wolność." @@ -11,7 +11,11 @@ "suggested": [ { "name": "LibreWolf", - "url": "https://librewolf.net/" + "url": "https://librewolf.net/", + "note": { + "en": "Supprts enabling harmful DRM in the options.", + "pl": "Wspiera włączanie szkodliwego DRM'a w opcjach." + } }, { "name": "TorBrowser", @@ -87,23 +91,35 @@ "name": { "en": "mobile operating systems", "pl": "mobilne systemy operacyjne" - } + }, "text": { "en": "If you wisely plan your next mobile phone purchase, you can avoid being exploited by megacorporations. An easy option is to choose a device that runs a liberated version of Android. You might also consider a GNU/Linux phone if you feel you're a geek.", - "pl": "Jeśli mądrze zaplanujesz zakup swojego następnego telefonu komórkwego, możesz uniknąć bycia wykorzystywanym przez megakorporacje. Łatwą opcją jest wybranie urządzenia, które działa pod wolną wersją Androida. Możesz też rozważyć telefon z GNU/Linuxem jeśli czujesz, że jesteś gikiem." + "pl": "Jeśli mądrze zaplanujesz zakup swojego następnego telefonu komórkwego, możesz uniknąć bycia wykorzystywanym przez megakorporacje. Łatwą opcją jest wybranie urządzenia, które działa pod wolną wersją Androida. Możesz też rozważyć telefon z GNU/Linuxem, jeśli czujesz, że jesteś gikiem." }, "suggested": [ { "name": "/e/OS", - "url": "https://e.foundation/e-os/" + "url": "https://e.foundation/e-os/", + "note": { + "en": "Is not 100% Free Software.", + "pl": "Nie jest w 100% Wolnym Oprogramowaniem." + } }, { "name": "PinePhone & Postmarket OS", - "url": "https://pine64.com/product-category/pinephone/" + "url": "https://pine64.com/product-category/pinephone/", + "note": { + "en": "Is not 100% Free Software.", + "pl": "Nie jest w 100% Wolnym Oprogramowaniem." + } }, { "name": "NitroPhone & GrapheneOS", - "url": "https://shop.nitrokey.com/shop/product/nitrophone-1-199" + "url": "https://shop.nitrokey.com/shop/product/nitrophone-1-199", + "note": { + "en": "Is not 100% Free Software.", + "pl": "Nie jest w 100% Wolnym Oprogramowaniem." + } } ] }, @@ -135,7 +151,11 @@ "suggested": [ { "name": "F-Droid", - "url": "https://f-droid.org/" + "url": "https://f-droid.org/", + "note": { + "en": "It does not meet \"Free Software Distribution Guidelines\".", + "pl": "Nie spełnia \"Free Software Distribution Guidelines\"." + } } ] }, @@ -151,11 +171,27 @@ "suggested": [ { "name": "BugBlueButton", - "url": "https://bigbluebutton.org/" + "url": "https://bigbluebutton.org/", + "note": { + "en": "Not all JS is labeled and integration with unethical services is possible.", + "pl": "Nie cały JS jest otagowany i możliwa jest integracja z nieetecznymi serwisami." + } }, { "name": "Jitsi Meet", - "url": "https://jitsi.org/jitsi-meet/" + "url": "https://jitsi.org/jitsi-meet/", + "note": { + "en": "Not all JS is labeled and integration with unethical services is possible.", + "pl": "Nie cały JS jest otagowany i możliwa jest integracja z nieetecznymi serwisami." + } + }, + { + "name": "CHATONS (VIDEO-CONFERENCE)", + "url": "https://entraide.chatons.org/en/", + "note": { + "en": "Not all JS is labeled.", + "pl": "Nie cały JS jest otagowany." + } } ] }, @@ -165,8 +201,38 @@ "pl": "czaty" }, "text": { - "en": "WatsApp, Facebook Messenger, Discord - they are all proprietary and centralized. XMPP is a decent chat protocol with video calls support that can replace them. Wnd-to-end encryption included!", + "en": "WatsApp, Facebook Messenger, Discord - they are all proprietary and centralized. XMPP is a decent chat protocol with video calls support that can replace them. End-to-end encryption included!", "pl": "WatsApp, Facebook Messenger, Discord, Slack - one wszystkie są własnościowe i zcentralizowane. XMPP jest przyzwoitym protokołem czatu ze wsparciem dla rozmów wideo, który może je zastąpić. Szyfrowanie od-końca-do-końca w zestawie!" - } + }, + "suggested": [ + { + "name": "Disroot", + "url": "https://disroot.org/en/services/xmpp" + }, + { + "name": "list.jabber.at", + "url": "https://list.jabber.at/" + } + ] + }, + "8": { + "name": { + "en": "collaborative spreadsheets", + "pl": "arkusze kalkulacyjne z możliwością współpracy" + }, + "text": { + "en": "Many of us are getting told to enter data into Google Sheets. Worse, the some of the data is often personal or sensitive. Meanwhile, there exist other in-browser spreadsheets that are libre and snooping-free.", + "pl": "Wielu z nas każe się pisywać dane do Arkuszy Google. Jakby tego było mało, część z tego to często dane osobowe lub poufne. Tymczasem istnieją inne przeglądarkowe arkusze, które są wolnym oprogramowaniem i nie śledzą." + }, + "suggested": [ + { + "name": "CHATONS (COLLABORATIVE SPREADSHEET)", + "url": "https://entraide.chatons.org/en/", + "note": { + "en": "Not all JS is labeled.", + "pl": "Nie cały JS jest otagowany." + } + } + ] } } -- cgit v1.2.3