1
0
Fork 0
mirror of https://github.com/YunoHost/apps.git synced 2024-09-03 20:06:07 +02:00

Merge branch 'update_app_levels' of https://github.com/YunoHost/apps into update_app_levels

This commit is contained in:
Éric Gaspar 2024-06-07 19:12:35 +02:00
commit cfc0b83acd
16 changed files with 332 additions and 212 deletions

View file

@ -13,6 +13,7 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
token: ${{ secrets.YUNOHOST_BOT_TOKEN }} token: ${{ secrets.YUNOHOST_BOT_TOKEN }}
- name: Set up Python 3.11 - name: Set up Python 3.11
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:

View file

@ -14,25 +14,29 @@ jobs:
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: 3.11 python-version: 3.11
- name: Install dependencies - name: Install dependencies
run: | run: |
cd tools/readme_generator/ cd tools/readme_generator/
pip install -r requirements.txt pip install -r requirements.txt
- name: Save old messges.pot for diffing later - name: Save old messges.pot for diffing later
run: | run: |
cd tools/readme_generator/ cd tools/readme_generator/
cp messages.pot messages.pot.old cp messages.pot messages.pot.old
- name: Try to generate messages.pot - name: Try to generate messages.pot
run: | run: |
cd tools/readme_generator/ cd tools/readme_generator/
pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot . pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot .
- shell: pwsh
id: check_files_changed - name: Check if files changed
run: | run: |
$HasDiff = python .github/diff_pot_files.py tools/readme_generator/messages.pot.old tools/readme_generator/messages.pot HAS_DIFF=$(python .github/diff_pot_files.py tools/readme_generator/messages.pot.old tools/readme_generator/messages.pot)
Write-Host "::set-output name=files_changed::$HasDiff" echo "HAS_DIFF=$HAS_DIFF" >> $GITHUB_ENV
- name: Create Pull Request - name: Create Pull Request
if: steps.check_files_changed.outputs.files_changed == 'true' if: ${{ env.HAS_DIFF == 'true' }}
uses: peter-evans/create-pull-request@v6 uses: peter-evans/create-pull-request@v6
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -15,15 +15,8 @@ jobs:
with: with:
options: "." options: "."
continue-on-error: true continue-on-error: true
- shell: pwsh
id: check_files_changed
run: |
# Diff HEAD with the previous commit
$diff = git diff
$HasDiff = $diff.Length -gt 0
Write-Host "::set-output name=files_changed::$HasDiff"
- name: Create Pull Request - name: Create Pull Request
if: steps.check_files_changed.outputs.files_changed == 'true'
uses: peter-evans/create-pull-request@v6 uses: peter-evans/create-pull-request@v6
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -11,15 +11,8 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: uncenter/setup-taplo@v1 - uses: uncenter/setup-taplo@v1
- run: taplo fmt - run: taplo fmt
- shell: pwsh
id: check_files_changed
run: |
# Diff HEAD with the previous commit
$diff = git diff
$HasDiff = $diff.Length -gt 0
Write-Host "::set-output name=files_changed::$HasDiff"
- name: Create Pull Request - name: Create Pull Request
if: steps.check_files_changed.outputs.files_changed == 'true'
uses: peter-evans/create-pull-request@v6 uses: peter-evans/create-pull-request@v6
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -43,7 +43,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "social_media" category = "social_media"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
state = "working" state = "working"
subtags = [ "microblogging", "pictures" ] subtags = [ "microblogging", "pictures" ]
url = "https://github.com/YunoHost-Apps/acropolis_ynh" url = "https://github.com/YunoHost-Apps/acropolis_ynh"
@ -70,7 +70,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "system_tools" category = "system_tools"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
state = "working" state = "working"
subtags = [ "db" ] subtags = [ "db" ]
url = "https://github.com/YunoHost-Apps/adminer_ynh" url = "https://github.com/YunoHost-Apps/adminer_ynh"
@ -165,7 +165,7 @@ url = "https://github.com/YunoHost-Apps/archivist_ynh"
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
antifeatures = [ "alpha-software" ] antifeatures = [ "alpha-software" ]
category = "small_utilities" category = "small_utilities"
level = 7 level = 4
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/armadietto_ynh" url = "https://github.com/YunoHost-Apps/armadietto_ynh"
@ -245,7 +245,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "publishing" category = "publishing"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
potential_alternative_to = [ "Blogger", "Coldfusion", "Wix" ] potential_alternative_to = [ "Blogger", "Coldfusion", "Wix" ]
state = "working" state = "working"
subtags = [ "blog" ] subtags = [ "blog" ]
@ -511,7 +511,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "publishing" category = "publishing"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
potential_alternative_to = [ "Disqus" ] potential_alternative_to = [ "Disqus" ]
state = "working" state = "working"
subtags = [ "website" ] subtags = [ "website" ]
@ -681,7 +681,7 @@ url = "https://github.com/YunoHost-Apps/dendrite_ynh"
[dex] [dex]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "system_tools" category = "system_tools"
level = 6 level = 0
state = "working" state = "working"
subtags = [ "network" ] subtags = [ "network" ]
url = "https://github.com/YunoHost-Apps/dex_ynh" url = "https://github.com/YunoHost-Apps/dex_ynh"
@ -851,7 +851,7 @@ url = "https://github.com/YunoHost-Apps/domoticz_ynh"
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
branch = "main" branch = "main"
category = "dev" category = "dev"
level = 8 level = 4
state = "working" state = "working"
subtags = [ "programming" ] subtags = [ "programming" ]
url = "https://github.com/YunoHost-Apps/dont-code_ynh" url = "https://github.com/YunoHost-Apps/dont-code_ynh"
@ -988,7 +988,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "small_utilities" category = "small_utilities"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/encryptor-decryptor_ynh" url = "https://github.com/YunoHost-Apps/encryptor-decryptor_ynh"
@ -1089,7 +1089,7 @@ url = "https://github.com/YunoHost-Apps/fastapi_ynh"
[fider] [fider]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "productivity_and_management" category = "productivity_and_management"
level = 3 level = 0
state = "working" state = "working"
subtags = [ "poll" ] subtags = [ "poll" ]
url = "https://github.com/YunoHost-Apps/fider_ynh" url = "https://github.com/YunoHost-Apps/fider_ynh"
@ -1115,7 +1115,7 @@ url = "https://github.com/YunoHost-Apps/filepizza_ynh"
[firefish] [firefish]
added_date = 1691055044 # 2023/08/03 added_date = 1691055044 # 2023/08/03
category = "social_media" category = "social_media"
level = 0 level = 7
potential_alternative_to = [ "Calckey", "Mastodon", "Misskey", "Pleroma", "Threads", "X" ] potential_alternative_to = [ "Calckey", "Mastodon", "Misskey", "Pleroma", "Threads", "X" ]
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/firefish_ynh" url = "https://github.com/YunoHost-Apps/firefish_ynh"
@ -1247,7 +1247,7 @@ url = "https://github.com/YunoHost-Apps/freshrss_ynh"
[friendica] [friendica]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "social_media" category = "social_media"
level = 8 level = 6
potential_alternative_to = [ "Facebook" ] potential_alternative_to = [ "Facebook" ]
state = "working" state = "working"
subtags = [ "microblogging" ] subtags = [ "microblogging" ]
@ -1373,7 +1373,7 @@ url = "https://github.com/YunoHost-Apps/glance_ynh"
[glitchsoc] [glitchsoc]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "social_media" category = "social_media"
level = 6 level = 8
state = "working" state = "working"
subtags = [ "microblogging" ] subtags = [ "microblogging" ]
url = "https://github.com/YunoHost-Apps/glitchsoc_ynh" url = "https://github.com/YunoHost-Apps/glitchsoc_ynh"
@ -2130,7 +2130,7 @@ url = "https://github.com/YunoHost-Apps/loki_ynh"
[lstu] [lstu]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "small_utilities" category = "small_utilities"
level = 8 level = 6
potential_alternative_to = [ "bitly" ] potential_alternative_to = [ "bitly" ]
state = "working" state = "working"
subtags = [ "url_shortener" ] subtags = [ "url_shortener" ]
@ -2231,17 +2231,6 @@ state = "working"
subtags = [ "chat" ] subtags = [ "chat" ]
url = "https://github.com/YunoHost-Apps/matrix-appservice-irc_ynh" url = "https://github.com/YunoHost-Apps/matrix-appservice-irc_ynh"
[matrix-puppet-discord]
added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ]
category = "communication"
deprecated_date = 1711055457 # 2024/03/21
level = 6
potential_alternative_to = [ "Discord" ]
state = "working"
subtags = [ "chat" ]
url = "https://github.com/YunoHost-Apps/matrix-puppet-discord_ynh"
[matterbridge] [matterbridge]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "communication" category = "communication"
@ -2623,7 +2612,7 @@ url = "https://github.com/YunoHost-Apps/nitter_ynh"
[noalyss] [noalyss]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "productivity_and_management" category = "productivity_and_management"
level = 8 level = 0
potential_alternative_to = [ "Exact Online", "WinBooks", "Yooz" ] potential_alternative_to = [ "Exact Online", "WinBooks", "Yooz" ]
state = "working" state = "working"
subtags = [ "accounting", "business_and_ngos" ] subtags = [ "accounting", "business_and_ngos" ]
@ -2655,7 +2644,7 @@ url = "https://github.com/YunoHost-Apps/nodered_ynh"
[nomad] [nomad]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "dev" category = "dev"
level = 8 level = 1
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/nomad_ynh" url = "https://github.com/YunoHost-Apps/nomad_ynh"
@ -2944,7 +2933,7 @@ url = "https://github.com/YunoHost-Apps/petrolette_ynh"
[pgadmin] [pgadmin]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "system_tools" category = "system_tools"
level = 7 level = 8
state = "working" state = "working"
subtags = [ "db" ] subtags = [ "db" ]
url = "https://github.com/YunoHost-Apps/pgadmin_ynh" url = "https://github.com/YunoHost-Apps/pgadmin_ynh"
@ -3168,7 +3157,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "publishing" category = "publishing"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
potential_alternative_to = [ "Wix" ] potential_alternative_to = [ "Wix" ]
state = "working" state = "working"
subtags = [ "website" ] subtags = [ "website" ]
@ -3459,7 +3448,7 @@ url = "https://github.com/YunoHost-Apps/samba_ynh"
[satdress] [satdress]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "productivity_and_management" category = "productivity_and_management"
level = 8 level = 0
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/satdress_ynh" url = "https://github.com/YunoHost-Apps/satdress_ynh"
@ -3484,7 +3473,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "small_utilities" category = "small_utilities"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/scrumblr_ynh" url = "https://github.com/YunoHost-Apps/scrumblr_ynh"
@ -3772,7 +3761,7 @@ added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ] antifeatures = [ "deprecated-software" ]
category = "system_tools" category = "system_tools"
deprecated_date = 1717071136 # 2024/05/30 deprecated_date = 1717071136 # 2024/05/30
level = 8 level = 7
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/ssh_chroot_dir_ynh" url = "https://github.com/YunoHost-Apps/ssh_chroot_dir_ynh"
@ -3896,7 +3885,7 @@ url = "https://github.com/YunoHost-Apps/teampass_ynh"
[technitium-dns] [technitium-dns]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "system_tools" category = "system_tools"
level = 6 level = 8
state = "working" state = "working"
subtags = [ "network" ] subtags = [ "network" ]
url = "https://github.com/YunoHost-Apps/technitium-dns_ynh" url = "https://github.com/YunoHost-Apps/technitium-dns_ynh"
@ -4001,7 +3990,7 @@ url = "https://github.com/YunoHost-Apps/traccar_ynh"
[tracim] [tracim]
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
category = "office" category = "office"
level = 6 level = 0
potential_alternative_to = [ "Dropbox", "Google Drive", "Slack", "Trello" ] potential_alternative_to = [ "Dropbox", "Google Drive", "Slack", "Trello" ]
state = "working" state = "working"
url = "https://github.com/YunoHost-Apps/tracim_ynh" url = "https://github.com/YunoHost-Apps/tracim_ynh"
@ -4158,7 +4147,7 @@ url = "https://github.com/YunoHost-Apps/vikunja_ynh"
[vore] [vore]
added_date = 1690540859 # 2023/07/28 added_date = 1690540859 # 2023/07/28
category = "reading" category = "reading"
level = 7 level = 0
state = "working" state = "working"
subtags = [ "rssreader" ] subtags = [ "rssreader" ]
url = "https://github.com/YunoHost-Apps/vore_ynh" url = "https://github.com/YunoHost-Apps/vore_ynh"
@ -4346,7 +4335,7 @@ url = "https://github.com/YunoHost-Apps/yacy_ynh"
[yarr] [yarr]
added_date = 1715771420 # 2024/05/15 added_date = 1715771420 # 2024/05/15
category = "reading" category = "reading"
level = 7 level = 0
state = "working" state = "working"
subtags = [ "rssreader" ] subtags = [ "rssreader" ]
url = "https://github.com/YunoHost-Apps/yarr_ynh" url = "https://github.com/YunoHost-Apps/yarr_ynh"
@ -4423,7 +4412,7 @@ url = "https://github.com/YunoHost-Apps/zap_ynh"
added_date = 1674232499 # 2023/01/20 added_date = 1674232499 # 2023/01/20
antifeatures = [ "replaced-by-another-app" ] antifeatures = [ "replaced-by-another-app" ]
category = "small_utilities" category = "small_utilities"
level = 7 level = 4
potential_alternative_to = [ "Pastebin" ] potential_alternative_to = [ "Pastebin" ]
state = "working" state = "working"
subtags = [ "pastebin" ] subtags = [ "pastebin" ]

View file

@ -186,6 +186,16 @@ potential_alternative_to = [ "Google Groups" ]
subtags = [ "email" ] subtags = [ "email" ]
url = "https://github.com/yunohost-apps/mailman_ynh" url = "https://github.com/yunohost-apps/mailman_ynh"
[matrix-puppet-discord]
added_date = 1674232499 # 2023/01/20
antifeatures = [ "deprecated-software" ]
category = "communication"
deprecated_date = 1711055457 # 2024/03/21
killed_date = 1717576274 # 2024/06/05
potential_alternative_to = [ "Discord" ]
subtags = [ "chat" ]
url = "https://github.com/YunoHost-Apps/matrix-puppet-discord_ynh"
[mediadrop] [mediadrop]
added_date = 1554588215 # 2019/04/07 added_date = 1554588215 # 2019/04/07
category = "multimedia" category = "multimedia"

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n" "POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-03-23 00:54+0000\n" "PO-Revision-Date: 2024-06-06 14:54+0000\n"
"Last-Translator: OniriCorpe <oniricorpe@disroot.org>\n" "Last-Translator: Éric Gaspar <junk.eg@free.fr>\n"
"Language-Team: Spanish <https://translate.yunohost.org/projects/yunohost/" "Language-Team: Spanish <https://translate.yunohost.org/projects/yunohost/"
"apps/es/>\n" "apps/es/>\n"
"Language: es\n" "Language: es\n"
@ -17,6 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.4.3\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:162 #: app.py:162
@ -26,7 +27,7 @@ msgstr "App %(app_id)s no encontrada"
#: app.py:165 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" msgstr "Debes iniciar sesión para poder iniciar una aplicación"
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33 #: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid "" msgid ""
@ -36,14 +37,19 @@ msgid ""
"least 5 topics, reading at least 30 posts, and spending at least 10 minutes " "least 5 topics, reading at least 30 posts, and spending at least 10 minutes "
"reading posts." "reading posts."
msgstr "" msgstr ""
"Tenga en cuenta que, debido a varios abusos, restringimos el inicio de "
"sesión en la tienda de aplicaciones a usuarios de 'nivel de confianza 1'.<br/"
"><br/>El 'nivel de confianza 1' se obtiene después de interactuar un mínimo "
"con el foro, y más específicamente: ingresar al menos 5 temas, leer al menos "
"30 publicaciones y dedicar al menos 10 minutos a leer publicaciones."
#: app.py:210 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr "Debes iniciar sesión para enviar una aplicación a la lista de deseos"
#: app.py:225 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr "Token CSRF no válido. Actualice la página e inténtelo de nuevo"
#: app.py:263 #: app.py:263
msgid "" msgid ""

View file

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n" "POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-05-20 21:19+0000\n" "PO-Revision-Date: 2024-06-06 14:54+0000\n"
"Last-Translator: ppr <pouetpouetratatouille@gmail.com>\n" "Last-Translator: Éric Gaspar <junk.eg@free.fr>\n"
"Language-Team: French <https://translate.yunohost.org/projects/yunohost/apps/" "Language-Team: French <https://translate.yunohost.org/projects/yunohost/apps/"
"fr/>\n" "fr/>\n"
"Language: fr\n" "Language: fr\n"
@ -492,7 +492,7 @@ msgstr "Niveau 8"
#: templates/charts.html:107 #: templates/charts.html:107
#, python-format #, python-format
msgid "Level %(level)s:" msgid "Level %(level)s:"
msgstr "Niveau %(level)s:" msgstr "Niveau %(level)s:"
#: templates/charts.html:107 #: templates/charts.html:107
msgid "Total:" msgid "Total:"
@ -615,7 +615,6 @@ msgid "Inactive (%(days)s days ago)"
msgstr "Inactif (%(days)s jours)" msgstr "Inactif (%(days)s jours)"
#: templates/dash.html:177 #: templates/dash.html:177
#, fuzzy
msgid "Packaging v1" msgid "Packaging v1"
msgstr "Packaging v1" msgstr "Packaging v1"

View file

@ -8,14 +8,16 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-05-09 23:14+0200\n" "POT-Creation-Date: 2024-05-09 23:14+0200\n"
"PO-Revision-Date: 2024-02-21 06:08+0100\n" "PO-Revision-Date: 2024-06-06 14:54+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: Éric Gaspar <junk.eg@free.fr>\n"
"Language-Team: pt <LL@li.org>\n" "Language-Team: Portuguese <https://translate.yunohost.org/projects/yunohost/"
"apps/pt/>\n"
"Language: pt\n" "Language: pt\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Weblate 5.4.3\n"
"Generated-By: Babel 2.14.0\n" "Generated-By: Babel 2.14.0\n"
#: app.py:162 #: app.py:162
@ -25,7 +27,7 @@ msgstr ""
#: app.py:165 #: app.py:165
msgid "You must be logged in to be able to star an app" msgid "You must be logged in to be able to star an app"
msgstr "" msgstr "Você deve estar logado para poder marcar um aplicativo com estrela"
#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33 #: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33
msgid "" msgid ""
@ -35,14 +37,20 @@ msgid ""
"least 5 topics, reading at least 30 posts, and spending at least 10 minutes " "least 5 topics, reading at least 30 posts, and spending at least 10 minutes "
"reading posts." "reading posts."
msgstr "" msgstr ""
"Observe que, devido a vários abusos, restringimos o login na app store para "
"usuários de 'nível de confiança 1'.<br/><br/>O 'nível de confiança 1' é "
"obtido após uma interação mínima com o fórum e, mais especificamente: "
"inserir pelo menos 5 tópicos, ler pelo menos 30 postagens e passar pelo "
"menos 10 minutos lendo postagens."
#: app.py:210 #: app.py:210
msgid "You must be logged in to submit an app to the wishlist" msgid "You must be logged in to submit an app to the wishlist"
msgstr "" msgstr ""
"Você deve estar logado para enviar um aplicativo para a lista de desejos"
#: app.py:225 #: app.py:225
msgid "Invalid CSRF token, please refresh the page and try again" msgid "Invalid CSRF token, please refresh the page and try again"
msgstr "" msgstr "Token CSRF inválido. Atualize a página e tente novamente"
#: app.py:263 #: app.py:263
msgid "" msgid ""

View file

@ -3,6 +3,7 @@
import argparse import argparse
import shutil import shutil
import logging import logging
from itertools import repeat
from multiprocessing import Pool from multiprocessing import Pool
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@ -24,7 +25,9 @@ def app_cache_folder(app: str) -> Path:
return APPS_CACHE_DIR / app return APPS_CACHE_DIR / app
def app_cache_clone(app: str, infos: dict[str, str]) -> None: def app_cache_clone(
app: str, infos: dict[str, str], all_branches: bool = False
) -> None:
logging.info("Cloning %s...", app) logging.info("Cloning %s...", app)
git_depths = { git_depths = {
"notworking": 5, "notworking": 5,
@ -37,18 +40,27 @@ def app_cache_clone(app: str, infos: dict[str, str]) -> None:
infos["url"], infos["url"],
to_path=app_cache_folder(app), to_path=app_cache_folder(app),
depth=git_depths.get(infos["state"], git_depths["default"]), depth=git_depths.get(infos["state"], git_depths["default"]),
single_branch=True, single_branch=not all_branches,
branch=infos.get("branch", "master"), branch=infos.get("branch", "master"),
) )
def app_cache_clone_or_update(app: str, infos: dict[str, str]) -> None: def app_cache_clone_or_update(
app: str,
infos: dict[str, str],
ssh_clone: bool = False,
fetch_all_branches: bool = False,
) -> None:
app_path = app_cache_folder(app) app_path = app_cache_folder(app)
# Patch url for ssh clone
if ssh_clone:
infos["url"] = infos["url"].replace("https://github.com/", "git@github.com:")
# Don't refresh if already refreshed during last hour # Don't refresh if already refreshed during last hour
age = git_repo_age(app_path) age = git_repo_age(app_path)
if age is False: if age is False:
app_cache_clone(app, infos) app_cache_clone(app, infos, fetch_all_branches)
return return
# if age < 3600: # if age < 3600:
@ -60,6 +72,10 @@ def app_cache_clone_or_update(app: str, infos: dict[str, str]) -> None:
repo.remote("origin").set_url(infos["url"]) repo.remote("origin").set_url(infos["url"])
branch = infos.get("branch", "master") branch = infos.get("branch", "master")
if fetch_all_branches:
repo.git.remote("set-branches", "origin", "*")
repo.remote("origin").fetch()
else:
if repo.active_branch != branch: if repo.active_branch != branch:
all_branches = [str(b) for b in repo.branches] all_branches = [str(b) for b in repo.branches]
if branch in all_branches: if branch in all_branches:
@ -73,16 +89,24 @@ def app_cache_clone_or_update(app: str, infos: dict[str, str]) -> None:
def __app_cache_clone_or_update_mapped(data): def __app_cache_clone_or_update_mapped(data):
name, info = data name, info, ssh_clone, all_branches = data
try: try:
app_cache_clone_or_update(name, info) app_cache_clone_or_update(name, info, ssh_clone, all_branches)
except Exception as err: except Exception as err:
logging.error("[App caches] Error while updating %s: %s", name, err) logging.error("[App caches] Error while updating %s: %s", name, err)
def apps_cache_update_all(apps: dict[str, dict[str, Any]], parallel: int = 8) -> None: def apps_cache_update_all(
apps: dict[str, dict[str, Any]],
parallel: int = 8,
ssh_clone: bool = False,
all_branches: bool = False,
) -> None:
with Pool(processes=parallel) as pool: with Pool(processes=parallel) as pool:
tasks = pool.imap_unordered(__app_cache_clone_or_update_mapped, apps.items()) tasks = pool.imap_unordered(
__app_cache_clone_or_update_mapped,
zip(apps.keys(), apps.values(), repeat(ssh_clone), repeat(all_branches)),
)
for _ in tqdm.tqdm(tasks, total=len(apps.keys()), ascii=" ·#"): for _ in tqdm.tqdm(tasks, total=len(apps.keys()), ascii=" ·#"):
pass pass
@ -101,6 +125,20 @@ def __run_for_catalog():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true") parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument("-j", "--processes", type=int, default=8) parser.add_argument("-j", "--processes", type=int, default=8)
parser.add_argument(
"-s",
"--ssh",
action=argparse.BooleanOptionalAction,
default=False,
help="Use ssh clones instead of https",
)
parser.add_argument(
"-b",
"--all-branches",
action=argparse.BooleanOptionalAction,
default=False,
help="Download all branches from repo",
)
parser.add_argument( parser.add_argument(
"-c", "-c",
"--cleanup", "--cleanup",
@ -114,7 +152,12 @@ def __run_for_catalog():
if args.cleanup: if args.cleanup:
apps_cache_cleanup(get_catalog()) apps_cache_cleanup(get_catalog())
apps_cache_update_all(get_catalog(), parallel=args.processes) apps_cache_update_all(
get_catalog(),
parallel=args.processes,
ssh_clone=args.ssh,
all_branches=args.all_branches,
)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -17,6 +17,7 @@ from langcodes import Language
README_GEN_DIR = Path(__file__).resolve().parent README_GEN_DIR = Path(__file__).resolve().parent
APPS_REPO_ROOT = README_GEN_DIR.parent.parent APPS_REPO_ROOT = README_GEN_DIR.parent.parent
TRANSLATIONS_DIR = README_GEN_DIR / "translations"
def value_for_lang(values: Dict, lang: str): def value_for_lang(values: Dict, lang: str):
if not isinstance(values, dict): if not isinstance(values, dict):
@ -54,13 +55,13 @@ def generate_READMEs(app_path: Path):
return return
poparser = PoFileParser({}) poparser = PoFileParser({})
poparser.parse(open("messages.pot")) poparser.parse((README_GEN_DIR / "messages.pot").open(encoding="utf-8"))
# we only want to translate a README if all strings are translatables so we # we only want to translate a README if all strings are translatables so we
# do this loop to detect which language provides a full translation # do this loop to detect which language provides a full translation
fully_translated_langs: List[str] = [] fully_translated_langs: List[str] = []
for available_translations in os.listdir("translations"): for available_translations in os.listdir(TRANSLATIONS_DIR):
translations = Translations.load("translations", available_translations) translations = Translations.load(TRANSLATIONS_DIR, available_translations)
is_fully_translated = True is_fully_translated = True
for sentence in poparser.catalog: for sentence in poparser.catalog:
@ -111,7 +112,7 @@ def generate_READMEs(app_path: Path):
loader=FileSystemLoader(README_GEN_DIR / "templates"), loader=FileSystemLoader(README_GEN_DIR / "templates"),
extensions=["jinja2.ext.i18n"], extensions=["jinja2.ext.i18n"],
) )
translations = Translations.load("translations", [lang]) translations = Translations.load(TRANSLATIONS_DIR, [lang])
env.install_gettext_translations(translations) env.install_gettext_translations(translations)
template = env.get_template("README.md.j2") template = env.get_template("README.md.j2")
@ -169,7 +170,7 @@ def generate_READMEs(app_path: Path):
links_to_other_READMEs = [] links_to_other_READMEs = []
for language in fully_translated_langs: for language in fully_translated_langs:
translations = Translations.load("translations", [language]) translations = Translations.load(TRANSLATIONS_DIR, [language])
language_name_in_itself = Language.get(language).autonym() language_name_in_itself = Language.get(language).autonym()
links_to_other_READMEs.append( links_to_other_READMEs.append(
( (

View file

@ -1,101 +0,0 @@
#!/usr/bin/env python3
import hashlib
import hmac
from functools import cache
import tempfile
from pathlib import Path
from git import Actor, Repo
from sanic import HTTPResponse, Request, Sanic, response
from make_readme import generate_READMEs
TOOLS_DIR = Path(__file__).resolve().parent.parent
app = Sanic(__name__)
@cache
def github_webhook_secret() -> str:
return (
(TOOLS_DIR / ".github_webhook_secret")
.open("r", encoding="utf-8")
.read()
.strip()
)
@cache
def github_login() -> str:
return (TOOLS_DIR / ".github_login").open("r", encoding="utf-8").read().strip()
@cache
def github_token() -> str:
return (TOOLS_DIR / ".github_token").open("r", encoding="utf-8").read().strip()
@app.route("/github", methods=["GET"])
async def main_route(request: Request) -> HTTPResponse:
return response.text(
"You aren't supposed to go on this page using a browser, it's for webhooks push instead."
)
@app.route("/github", methods=["POST"])
async def on_push(request: Request) -> HTTPResponse:
header_signature = request.headers.get("X-Hub-Signature")
if header_signature is None:
print("no header X-Hub-Signature")
return response.json({"error": "No X-Hub-Signature"}, 403)
sha_name, signature = header_signature.split("=")
if sha_name != "sha1":
print("signing algo isn't sha1, it's '%s'" % sha_name)
return response.json({"error": "Signing algorightm is not sha1 ?!"}, 501)
# HMAC requires the key to be bytes, but data is string
mac = hmac.new(
github_webhook_secret().encode(), msg=request.body, digestmod=hashlib.sha1
)
if not hmac.compare_digest(str(mac.hexdigest()), str(signature)):
return response.json({"error": "Bad signature ?!"}, 403)
data = request.json
repository = data["repository"]["full_name"]
branch = data["ref"].split("/", 2)[2]
print(f"{repository} -> branch '{branch}'")
with tempfile.TemporaryDirectory() as folder_str:
folder = Path(folder_str)
repo = Repo.clone_from(
f"https://{github_login()}:{github_token()}@github.com/{repository}",
to_path=folder,
single_branch=True,
branch=branch,
)
generate_READMEs(folder)
repo.git.add("README*.md")
repo.git.add("ALL_README.md")
diff_empty = len(repo.index.diff("HEAD")) == 0
if diff_empty:
print("nothing to do")
return response.text("nothing to do")
repo.index.commit(
"Auto-update READMEs", author=Actor("yunohost-bot", "yunohost@yunohost.org")
)
repo.remote().push(quiet=False)
return response.text("ok")
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8123, debug=True)

View file

@ -1,16 +0,0 @@
[Unit]
Description=Auto-README webhook gunicorn daemon
After=network.target
[Service]
PIDFile=/run/gunicorn/autoreadme_webhook-pid
User=autoreadme_webhook
Group=autoreadme_webhook
WorkingDirectory=__PATH_TO_README_GENERATOR__
ExecStart=__PATH_TO_README_GENERATOR__/venv/bin/gunicorn -w 4 -b 127.0.0.1:8123 webhook:app
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

174
tools/webhooks/webhook.py Executable file
View file

@ -0,0 +1,174 @@
#!/usr/bin/env python3
import sys
import hashlib
import argparse
import hmac
from functools import cache
import tempfile
import logging
from pathlib import Path
from typing import Optional
from git import Actor, Repo, GitCommandError
from sanic import HTTPResponse, Request, Sanic, response
# add apps/tools to sys.path
sys.path.insert(0, str(Path(__file__).parent.parent))
from readme_generator.make_readme import generate_READMEs
TOOLS_DIR = Path(__file__).resolve().parent.parent
DEBUG = False
UNSAFE = False
APP = Sanic(__name__)
@cache
def github_webhook_secret() -> str:
return (
(TOOLS_DIR / ".github_webhook_secret")
.open("r", encoding="utf-8")
.read()
.strip()
)
@cache
def github_login() -> str:
return (TOOLS_DIR / ".github_login").open("r", encoding="utf-8").read().strip()
@cache
def github_token() -> str:
return (TOOLS_DIR / ".github_token").open("r", encoding="utf-8").read().strip()
@APP.route("/github", methods=["GET"])
async def github_get(request: Request) -> HTTPResponse:
return response.text(
"You aren't supposed to go on this page using a browser, it's for webhooks push instead."
)
@APP.route("/github", methods=["POST"])
async def github_post(request: Request) -> HTTPResponse:
if UNSAFE and (signatures_reply := check_webhook_signatures(request)):
return signatures_reply
event = request.headers.get("X-Github-Event")
if event == "push":
return on_push(request)
return response.json({"error": f"Unknown event '{event}'"}, 422)
def check_webhook_signatures(request: Request) -> Optional[HTTPResponse]:
logging.warning("Unsafe webhook!")
header_signature = request.headers.get("X-Hub-Signature")
if header_signature is None:
logging.error("no header X-Hub-Signature")
return response.json({"error": "No X-Hub-Signature"}, 403)
sha_name, signature = header_signature.split("=")
if sha_name != "sha1":
logging.error("signing algo isn't sha1, it's '%s'" % sha_name)
return response.json({"error": "Signing algorightm is not sha1 ?!"}, 501)
# HMAC requires the key to be bytes, but data is string
mac = hmac.new(
github_webhook_secret().encode(), msg=request.body, digestmod=hashlib.sha1
)
if not hmac.compare_digest(str(mac.hexdigest()), str(signature)):
return response.json({"error": "Bad signature ?!"}, 403)
return None
def on_push(request: Request) -> HTTPResponse:
data = request.json
repository = data["repository"]["full_name"]
branch = data["ref"].split("/", 2)[2]
logging.info(f"{repository} -> branch '{branch}'")
need_push = False
with tempfile.TemporaryDirectory() as folder_str:
folder = Path(folder_str)
repo = Repo.clone_from(
f"https://{github_login()}:{github_token()}@github.com/{repository}",
to_path=folder,
)
# First rebase the testing branch if possible
if branch in ["master", "testing"]:
result = git_repo_rebase_testing_fast_forward(repo)
need_push = need_push or result
repo.git.checkout(branch)
result = generate_and_commit_readmes(repo)
need_push = need_push or result
if not need_push:
logging.debug("nothing to do")
return response.text("nothing to do")
logging.debug(f"Pushing {repository}")
repo.remote().push(quiet=False, all=True)
return response.text("ok")
def generate_and_commit_readmes(repo: Repo) -> bool:
assert repo.working_tree_dir is not None
generate_READMEs(Path(repo.working_tree_dir))
repo.git.add("README*.md")
repo.git.add("ALL_README.md")
diff_empty = len(repo.index.diff("HEAD")) == 0
if diff_empty:
return False
repo.index.commit(
"Auto-update READMEs", author=Actor("yunohost-bot", "yunohost@yunohost.org")
)
return True
def git_repo_rebase_testing_fast_forward(repo: Repo) -> bool:
try:
repo.git.checkout("testing")
except GitCommandError:
return False
if not repo.is_ancestor("testing", "master"):
return False
repo.git.merge("master", ff_only=True)
return True
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action="store_true")
parser.add_argument(
"-u",
"--unsafe",
action="store_true",
help="Disable Github signature checks on webhooks, for debug only.",
)
args = parser.parse_args()
if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
global DEBUG, UNSAFE
DEBUG = args.debug
UNSAFE = args.unsafe
APP.run(host="127.0.0.1", port=8123, debug=args.debug)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,16 @@
[Unit]
Description=Github webhooks for YunoHost-Apps management
After=network.target
[Service]
PIDFile=/run/gunicorn/yunohost_apps_webhooks-pid
User=yunohost_apps_webhooks
Group=yunohost_apps_webhooks
WorkingDirectory=__PATH_TO_APPS_TOOLS__/webhooks
ExecStart=__PATH_TO_APPS_TOOLS__/webhooks/venv/bin/python3 webhook.py
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target